diff options
| author | cgd <cgd@NetBSD.org> | 1993-04-08 01:10:47 +0000 |
|---|---|---|
| committer | cgd <cgd@NetBSD.org> | 1993-04-08 01:10:47 +0000 |
| commit | 09208352b3d8b20e05dffc9bca2a7be80a0e537b (patch) | |
| tree | 4707b0de3a74674a25ae4ccc0cc5cd746967bfda /gnu/lib | |
| parent | 9b082a69f06aa0152bc72b5a4b8f566d945beb23 (diff) | |
gnulib == libraries under the GPL which need to go in the main tree.
starting out, this is regex-0.12
Diffstat (limited to 'gnu/lib')
29 files changed, 19621 insertions, 0 deletions
diff --git a/gnu/lib/Makefile b/gnu/lib/Makefile new file mode 100644 index 00000000000..e2ba68b0e24 --- /dev/null +++ b/gnu/lib/Makefile @@ -0,0 +1,5 @@ +# $Header: /cvsroot/src/gnu/lib/Attic/Makefile,v 1.1 1993/04/08 01:10:47 cgd Exp $ + +SUBDIR= regex-0.12 + +.include <bsd.subdir.mk> diff --git a/gnu/lib/libregex/AUTHORS b/gnu/lib/libregex/AUTHORS new file mode 100644 index 00000000000..058be996a27 --- /dev/null +++ b/gnu/lib/libregex/AUTHORS @@ -0,0 +1,10 @@ +Richard Stallman -- original version and continuing revisions of + regex.c and regex.h, and original version of the documentation. + +Karl Berry and Kathryn Hargreaves -- extensive modifications to above, + and all test files. + +Jim Blandy -- original version of re_set_registers, revisions to regex.c. + +Joe Arceneaux, David MacKenzie, Mike Haertel, Charles Hannum, and +probably others -- revisions to regex.c. diff --git a/gnu/lib/libregex/COPYING b/gnu/lib/libregex/COPYING new file mode 100644 index 00000000000..a43ea2126fb --- /dev/null +++ b/gnu/lib/libregex/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gnu/lib/libregex/ChangeLog b/gnu/lib/libregex/ChangeLog new file mode 100644 index 00000000000..ef919d276a7 --- /dev/null +++ b/gnu/lib/libregex/ChangeLog @@ -0,0 +1,3030 @@ +Fri Apr 2 17:31:59 1993 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * Released version 0.12. + + * regex.c (regerror): If errcode is zero, that's not a valid + error code, according to POSIX, but return "Success." + + * regex.c (regerror): Remember to actually fetch the message + from re_error_msg. + + * regex.c (regex_compile): Don't use the trick for ".*\n" on + ".+\n". Since the latter involves laying an extra choice + point, the backward jump isn't adjusted properly. + +Thu Mar 25 21:35:18 1993 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * regex.c (regex_compile): In the handle_open and handle_close + sections, clear pending_exact to zero. + +Tue Mar 9 12:03:07 1993 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu) + + * regex.c (re_search_2): In the loop which searches forward + using fastmap, don't forget to cast the character from the + string to an unsigned before using it as an index into the + translate map. + +Thu Jan 14 15:41:46 1993 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu) + + * regex.h: Never define const; let the callers do it. + configure.in: Don't define USING_AUTOCONF. + +Wed Jan 6 20:49:29 1993 Jim Blandy (jimb@geech.gnu.ai.mit.edu) + + * regex.c (regerror): Abort if ERRCODE is out of range. + +Sun Dec 20 16:19:10 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * configure.in: Arrange to #define USING_AUTOCONF. + * regex.h: If USING_AUTOCONF is #defined, don't mess with + `const' at all; autoconf has taken care of it. + +Mon Dec 14 21:40:39 1992 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu) + + * regex.h (RE_SYNTAX_AWK): Fix typo. From Arnold Robbins. + +Sun Dec 13 20:35:39 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * regex.c (compile_range): Fetch the range start and end by + casting the pattern pointer to an `unsigned char *' before + fetching through it. + +Sat Dec 12 09:41:01 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * regex.c: Undo change of 12/7/92; it's better for Emacs to + #define HAVE_CONFIG_H. + +Fri Dec 11 22:00:34 1992 Jim Meyering (meyering@hal.gnu.ai.mit.edu) + + * regex.c: Define and use isascii-protected ctype.h macros. + +Fri Dec 11 05:10:38 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * regex.c (re_match_2): Undo Karl's November 10th change; it + keeps the group in :\(.*\) from matching :/ properly. + +Mon Dec 7 19:44:56 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu) + + * regex.c: #include config.h if either HAVE_CONFIG_H or emacs + is #defined. + +Tue Dec 1 13:33:17 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * regex.c [HAVE_CONFIG_H]: Include config.h. + +Wed Nov 25 23:46:02 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * regex.c (regcomp): Add parens around bitwise & for clarity. + Initialize preg->allocated to prevent segv. + +Tue Nov 24 09:22:29 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * regex.c: Use HAVE_STRING_H, not USG. + * configure.in: Check for string.h, not USG. + +Fri Nov 20 06:33:24 1992 Karl Berry (karl@cs.umb.edu) + + * regex.c (SIGN_EXTEND_CHAR) [VMS]: Back out of this change, + since Roland Roberts now says it was a localism. + +Mon Nov 16 07:01:36 1992 Karl Berry (karl@cs.umb.edu) + + * regex.h (const) [!HAVE_CONST]: Test another cpp symbol (from + Autoconf) before zapping const. + +Sun Nov 15 05:36:42 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu) + + * regex.c, regex.h: Changes for VMS from Roland B Roberts + <roberts@nsrl31.nsrl.rochester.edu>. + +Thu Nov 12 11:31:15 1992 Karl Berry (karl@cs.umb.edu) + + * Makefile.in (distfiles): Include INSTALL. + +Tue Nov 10 09:29:23 1992 Karl Berry (karl@cs.umb.edu) + + * regex.c (re_match_2): At maybe_pop_jump, if at end of string + and pattern, just quit the matching loop. + + * regex.c (LETTER_P): Rename to `WORDCHAR_P'. + + * regex.c (AT_STRINGS_{BEG,END}): Take `d' as an arg; change + callers. + + * regex.c (re_match_2) [!emacs]: In wordchar and notwordchar + cases, advance d. + +Wed Nov 4 15:43:58 1992 Karl Berry (karl@hal.gnu.ai.mit.edu) + + * regex.h (const) [!__STDC__]: Don't define if it's already defined. + +Sat Oct 17 19:28:19 1992 Karl Berry (karl@cs.umb.edu) + + * regex.c (bcmp, bcopy, bzero): Only #define if they are not + already #defined. + + * configure.in: Use AC_CONST. + +Thu Oct 15 08:39:06 1992 Karl Berry (karl@cs.umb.edu) + + * regex.h (const) [!const]: Conditionalize. + +Fri Oct 2 13:31:42 1992 Karl Berry (karl@cs.umb.edu) + + * regex.h (RE_SYNTAX_ED): New definition. + +Sun Sep 20 12:53:39 1992 Karl Berry (karl@cs.umb.edu) + + * regex.[ch]: remove traces of `longest_p' -- dumb idea to put + this into the pattern buffer, as it means parallelism loses. + + * Makefile.in (config.status): use sh to run configure --no-create. + + * Makefile.in (realclean): OK, don't remove configure. + +Sat Sep 19 09:05:08 1992 Karl Berry (karl@hayley) + + * regex.c (PUSH_FAILURE_POINT, POP_FAILURE_POINT) [DEBUG]: keep + track of how many failure points we push and pop. + (re_match_2) [DEBUG]: declare variables for that, and print results. + (DEBUG_PRINT4): new macro. + + * regex.h (re_pattern_buffer): new field `longest_p' (to + eliminate backtracking if the user doesn't need it). + * regex.c (re_compile_pattern): initialize it (to 1). + (re_search_2): set it to zero if register information is not needed. + (re_match_2): if it's set, don't backtrack. + + * regex.c (re_search_2): update fastmap only after checking that + the pattern is anchored. + + * regex.c (re_match_2): do more debugging at maybe_pop_jump. + + * regex.c (re_search_2): cast result of TRANSLATE for use in + array subscript. + +Thu Sep 17 19:47:16 1992 Karl Berry (karl@geech.gnu.ai.mit.edu) + + * Version 0.11. + +Wed Sep 16 08:17:10 1992 Karl Berry (karl@hayley) + + * regex.c (INIT_FAIL_STACK): rewrite as statements instead of a + complicated comma expr, to avoid compiler warnings (and also + simplify). + (re_compile_fastmap, re_match_2): change callers. + + * regex.c (POP_FAILURE_POINT): cast pop of regstart and regend + to avoid compiler warnings. + + * regex.h (RE_NEWLINE_ORDINARY): remove this syntax bit, and + remove uses. + * regex.c (at_{beg,end}line_loc_p): go the last mile: remove + the RE_NEWLINE_ORDINARY case which made the ^ in \n^ be an anchor. + +Tue Sep 15 09:55:29 1992 Karl Berry (karl@hayley) + + * regex.c (at_begline_loc_p): new fn. + (at_endline_loc_p): simplify at_endline_op_p. + (regex_compile): in ^/$ cases, call the above. + + * regex.c (POP_FAILURE_POINT): rewrite the fn as a macro again, + as lord's profiling indicates the function is 20% of the time. + (re_match_2): callers changed. + + * configure.in (AC_MEMORY_H): remove, since we never use memcpy et al. + +Mon Sep 14 17:49:27 1992 Karl Berry (karl@hayley) + + * Makefile.in (makeargs): include MFLAGS. + +Sun Sep 13 07:41:45 1992 Karl Berry (karl@hayley) + + * regex.c (regex_compile): in \1..\9 case, make it always + invalid to use \<digit> if there is no preceding <digit>th subexpr. + * regex.h (RE_NO_MISSING_BK_REF): remove this syntax bit. + + * regex.c (regex_compile): remove support for invalid empty groups. + * regex.h (RE_NO_EMPTY_GROUPS): remove this syntax bit. + + * regex.c (FREE_VARIABLES) [!REGEX_MALLOC]: define as alloca (0), + to reclaim memory. + + * regex.h (RE_SYNTAX_POSIX_SED): don't bother with this. + +Sat Sep 12 13:37:21 1992 Karl Berry (karl@hayley) + + * README: incorporate emacs.diff. + + * regex.h (_RE_ARGS) [!__STDC__]: define as empty parens. + + * configure.in: add AC_ALLOCA. + + * Put test files in subdir test, documentation in subdir doc. + Adjust Makefile.in and configure.in accordingly. + +Thu Sep 10 10:29:11 1992 Karl Berry (karl@hayley) + + * regex.h (RE_SYNTAX_{POSIX_,}SED): new definitions. + +Wed Sep 9 06:27:09 1992 Karl Berry (karl@hayley) + + * Version 0.10. + +Tue Sep 8 07:32:30 1992 Karl Berry (karl@hayley) + + * xregex.texinfo: put the day of month into the date. + + * Makefile.in (realclean): remove Texinfo-generated files. + (distclean): remove empty sorted index files. + (clean): remove dvi files, etc. + + * configure.in: test for more Unix variants. + + * fileregex.c: new file. + Makefile.in (fileregex): new target. + + * iregex.c (main): move variable decls to smallest scope. + + * regex.c (FREE_VARIABLES): free reg_{,info_}dummy. + (re_match_2): check that the allocation for those two succeeded. + + * regex.c (FREE_VAR): replace FREE_NONNULL with this. + (FREE_VARIABLES): call it. + (re_match_2) [REGEX_MALLOC]: initialize all our vars to NULL. + + * tregress.c (do_match): generalize simple_match. + (SIMPLE_NONMATCH): new macro. + (SIMPLE_MATCH): change from routine. + + * Makefile.in (regex.texinfo): make file readonly, so we don't + edit it by mistake. + + * many files (re_default_syntax): rename to `re_syntax_options'; + call re_set_syntax instead of assigning to the variable where + possible. + +Mon Sep 7 10:12:16 1992 Karl Berry (karl@hayley) + + * syntax.skel: don't use prototypes. + + * {configure,Makefile}.in: new files. + + * regex.c: include <string.h> `#if USG || STDC_HEADERS'; remove + obsolete test for `POSIX', and test for BSRTING. + Include <strings.h> if we are not USG or STDC_HEADERS. + Do not include <unistd.h>. What did we ever need that for? + + * regex.h (RE_NO_EMPTY_ALTS): remove this. + (RE_SYNTAX_AWK): remove from here, too. + * regex.c (regex_compile): remove the check. + * xregex.texinfo (Alternation Operator): update. + * other.c (test_others): remove tests for this. + + * regex.h (RE_DUP_MAX): undefine if already defined. + + * regex.h: (RE_SYNTAX_POSIX*): redo to allow more operators, and + define new syntaxes with the minimal set. + + * syntax.skel (main): used sscanf instead of scanf. + + * regex.h (RE_SYNTAX_*GREP): new definitions from mike. + + * regex.c (regex_compile): initialize the upper bound of + intervals at the beginning of the interval, not the end. + (From pclink@qld.tne.oz.au.) + + * regex.c (handle_bar): rename to `handle_alt', for consistency. + + * regex.c ({store,insert}_{op1,op2}): new routines (except the last). + ({STORE,INSERT}_JUMP{,2}): macros to replace the old routines, + which took arguments in different orders, and were generally weird. + + * regex.c (PAT_PUSH*): rename to `BUF_PUSH*' -- we're not + appending info to the pattern! + +Sun Sep 6 11:26:49 1992 Karl Berry (karl@hayley) + + * regex.c (regex_compile): delete the variable + `following_left_brace', since we never use it. + + * regex.c (print_compiled_pattern): don't print the fastmap if + it's null. + + * regex.c (re_compile_fastmap): handle + `on_failure_keep_string_jump' like `on_failure_jump'. + + * regex.c (re_match_2): in `charset{,_not' case, cast the bit + count to unsigned, not unsigned char, in case we have a full + 32-byte bit list. + + * tregress.c (simple_match): remove. + (simple_test): rename as `simple_match'. + (simple_compile): print the error string if the compile failed. + + * regex.c (DO_RANGE): rewrite as a function, `compile_range', so + we can debug it. Change pattern characters to unsigned char + *'s, and change the range variable to an unsigned. + (regex_compile): change calls. + +Sat Sep 5 17:40:49 1992 Karl Berry (karl@hayley) + + * regex.h (_RE_ARGS): new macro to put in argument lists (if + ANSI) or omit them (if K&R); don't declare routines twice. + + * many files (obscure_syntax): rename to `re_default_syntax'. + +Fri Sep 4 09:06:53 1992 Karl Berry (karl@hayley) + + * GNUmakefile (extraclean): new target. + (realclean): delete the info files. + +Wed Sep 2 08:14:42 1992 Karl Berry (karl@hayley) + + * regex.h: doc fix. + +Sun Aug 23 06:53:15 1992 Karl Berry (karl@hayley) + + * regex.[ch] (re_comp): no const in the return type (from djm). + +Fri Aug 14 07:25:46 1992 Karl Berry (karl@hayley) + + * regex.c (DO_RANGE): declare variables as unsigned chars, not + signed chars (from jimb). + +Wed Jul 29 18:33:53 1992 Karl Berry (karl@claude.cs.umb.edu) + + * Version 0.9. + + * GNUmakefile (distclean): do not remove regex.texinfo. + (realclean): remove it here. + + * tregress.c (simple_test): initialize buf.buffer. + +Sun Jul 26 08:59:38 1992 Karl Berry (karl@hayley) + + * regex.c (push_dummy_failure): new opcode and corresponding + case in the various routines. Pushed at the end of + alternatives. + + * regex.c (jump_past_next_alt): rename to `jump_past_alt', for + brevity. + (no_pop_jump): rename to `jump'. + + * regex.c (regex_compile) [DEBUG]: terminate printing of pattern + with a newline. + + * NEWS: new file. + + * tregress.c (simple_{compile,match,test}): routines to simplify all + these little tests. + + * tregress.c: test for matching as much as possible. + +Fri Jul 10 06:53:32 1992 Karl Berry (karl@hayley) + + * Version 0.8. + +Wed Jul 8 06:39:31 1992 Karl Berry (karl@hayley) + + * regex.c (SIGN_EXTEND_CHAR): #undef any previous definition, as + ours should always work properly. + +Mon Jul 6 07:10:50 1992 Karl Berry (karl@hayley) + + * iregex.c (main) [DEBUG]: conditionalize the call to + print_compiled_pattern. + + * iregex.c (main): initialize buf.buffer to NULL. + * tregress (test_regress): likewise. + + * regex.c (alloca) [sparc]: #if on HAVE_ALLOCA_H instead. + + * tregress.c (test_regress): didn't have jla's test quite right. + +Sat Jul 4 09:02:12 1992 Karl Berry (karl@hayley) + + * regex.c (re_match_2): only REGEX_ALLOCATE all the register + vectors if the pattern actually has registers. + (match_end): new variable to avoid having to use best_regend[0]. + + * regex.c (IS_IN_FIRST_STRING): rename to FIRST_STRING_P. + + * regex.c: doc fixes. + + * tregess.c (test_regress): new fastmap test forwarded by rms. + + * tregress.c (test_regress): initialize the fastmap field. + + * tregress.c (test_regress): new test from jla that aborted + in re_search_2. + +Fri Jul 3 09:10:05 1992 Karl Berry (karl@hayley) + + * tregress.c (test_regress): add tests for translating charsets, + from kaoru. + + * GNUmakefile (common): add alloca.o. + * alloca.c: new file, copied from bison. + + * other.c (test_others): remove var `buf', since it's no longer used. + + * Below changes from ro@TechFak.Uni-Bielefeld.DE. + + * tregress.c (test_regress): initialize buf.allocated. + + * regex.c (re_compile_fastmap): initialize `succeed_n_p'. + + * GNUmakefile (regex): depend on $(common). + +Wed Jul 1 07:12:46 1992 Karl Berry (karl@hayley) + + * Version 0.7. + + * regex.c: doc fixes. + +Mon Jun 29 08:09:47 1992 Karl Berry (karl@fosse) + + * regex.c (pop_failure_point): change string vars to + `const char *' from `unsigned char *'. + + * regex.c: consolidate debugging stuff. + (print_partial_compiled_pattern): avoid enum clash. + +Mon Jun 29 07:50:27 1992 Karl Berry (karl@hayley) + + * xmalloc.c: new file. + * GNUmakefile (common): add it. + + * iregex.c (print_regs): new routine (from jimb). + (main): call it. + +Sat Jun 27 10:50:59 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu) + + * xregex.c (re_match_2): When we have accepted a match and + restored d from best_regend[0], we need to set dend + appropriately as well. + +Sun Jun 28 08:48:41 1992 Karl Berry (karl@hayley) + + * tregress.c: rename from regress.c. + + * regex.c (print_compiled_pattern): improve charset case to ease + byte-counting. + Also, don't distinguish between Emacs and non-Emacs + {not,}wordchar opcodes. + + * regex.c (print_fastmap): move here. + * test.c: from here. + * regex.c (print_{{partial,}compiled_pattern,double_string}): + rename from ..._printer. Change calls here and in test.c. + + * regex.c: create from xregex.c and regexinc.c for once and for + all, and change the debug fns to be extern, instead of static. + * GNUmakefile: remove traces of xregex.c. + * test.c: put in externs, instead of including regexinc.c. + + * xregex.c: move interactive main program and scanstring to iregex.c. + * iregex.c: new file. + * upcase.c, printchar.c: new files. + + * various doc fixes and other cosmetic changes throughout. + + * regexinc.c (compiled_pattern_printer): change variable name, + for consistency. + (partial_compiled_pattern_printer): print other info about the + compiled pattern, besides just the opcodes. + * xregex.c (regex_compile) [DEBUG]: print the compiled pattern + when we're done. + + * xregex.c (re_compile_fastmap): in the duplicate case, set + `can_be_null' and return. + Also, set `bufp->can_be_null' according to a new variable, + `path_can_be_null'. + Also, rewrite main while loop to not test `p != NULL', since + we never set it that way. + Also, eliminate special `can_be_null' value for the endline case. + (re_search_2): don't test for the special value. + * regex.h (struct re_pattern_buffer): remove the definition. + +Sat Jun 27 15:00:40 1992 Karl Berry (karl@hayley) + + * xregex.c (re_compile_fastmap): remove the `RE_' from + `REG_RE_MATCH_NULL_AT_END'. + Also, assert the fastmap in the pattern buffer is non-null. + Also, reset `succeed_n_p' after we've + paid attention to it, instead of every time through the loop. + Also, in the `anychar' case, only clear fastmap['\n'] if the + syntax says to, and don't return prematurely. + Also, rearrange cases in some semblance of a rational order. + * regex.h (REG_RE_MATCH_NULL_AT_END): remove the `RE_' from the name. + + * other.c: take bug reports from here. + * regress.c: new file for them. + * GNUmakefile (test): add it. + * main.c (main): new possible test. + * test.h (test_type): new value in enum. + +Thu Jun 25 17:37:43 1992 Karl Berry (karl@hayley) + + * xregex.c (scanstring) [test]: new function from jimb to allow some + escapes. + (main) [test]: call it (on the string, not the pattern). + + * xregex.c (main): make return type `int'. + +Wed Jun 24 10:43:03 1992 Karl Berry (karl@hayley) + + * xregex.c (pattern_offset_t): change to `int', for the benefit + of patterns which compile to more than 2^15 bytes. + + * xregex.c (GET_BUFFER_SPACE): remove spurious braces. + + * xregex.texinfo (Using Registers): put in a stub to ``document'' + the new function. + * regex.h (re_set_registers) [!__STDC__]: declare. + * xregex.c (re_set_registers): declare K&R style (also move to a + different place in the file). + +Mon Jun 8 18:03:28 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu) + + * regex.h (RE_NREGS): Doc fix. + + * xregex.c (re_set_registers): New function. + * regex.h (re_set_registers): Declaration for new function. + +Fri Jun 5 06:55:18 1992 Karl Berry (karl@hayley) + + * main.c (main): `return 0' instead of `exit (0)'. (From Paul Eggert) + + * regexinc.c (SIGN_EXTEND_CHAR): cast to unsigned char. + (extract_number, EXTRACT_NUMBER): don't bother to cast here. + +Tue Jun 2 07:37:53 1992 Karl Berry (karl@hayley) + + * Version 0.6. + + * Change copyrights to `1985, 89, ...'. + + * regex.h (REG_RE_MATCH_NULL_AT_END): new macro. + * xregex.c (re_compile_fastmap): initialize `can_be_null' to + `p==pend', instead of in the test at the top of the loop (as + it was, it was always being set). + Also, set `can_be_null'=1 if we would jump to the end of the + pattern in the `on_failure_jump' cases. + (re_search_2): check if `can_be_null' is 1, not nonzero. This + was the original test in rms' regex; why did we change this? + + * xregex.c (re_compile_fastmap): rename `is_a_succeed_n' to + `succeed_n_p'. + +Sat May 30 08:09:08 1992 Karl Berry (karl@hayley) + + * xregex.c (re_compile_pattern): declare `regnum' as `unsigned', + not `regnum_t', for the benefit of those patterns with more + than 255 groups. + + * xregex.c: rename `failure_stack' to `fail_stack', for brevity; + likewise for `match_nothing' to `match_null'. + + * regexinc.c (REGEX_REALLOCATE): take both the new and old + sizes, and copy only the old bytes. + * xregex.c (DOUBLE_FAILURE_STACK): pass both old and new. + * This change from Thorsten Ohl. + +Fri May 29 11:45:22 1992 Karl Berry (karl@hayley) + + * regexinc.c (SIGN_EXTEND_CHAR): define as `(signed char) c' + instead of relying on __CHAR_UNSIGNED__, to work with + compilers other than GCC. From Per Bothner. + + * main.c (main): change return type to `int'. + +Mon May 18 06:37:08 1992 Karl Berry (karl@hayley) + + * regex.h (RE_SYNTAX_AWK): typo in RE_RE_UNMATCHED... + +Fri May 15 10:44:46 1992 Karl Berry (karl@hayley) + + * Version 0.5. + +Sun May 3 13:54:00 1992 Karl Berry (karl@hayley) + + * regex.h (struct re_pattern_buffer): now it's just `regs_allocated'. + (REGS_UNALLOCATED, REGS_REALLOCATE, REGS_FIXED): new constants. + * xregex.c (regexec, re_compile_pattern): set the field appropriately. + (re_match_2): and use it. bufp can't be const any more. + +Fri May 1 15:43:09 1992 Karl Berry (karl@hayley) + + * regexinc.c: unconditionally include <sys/types.h>, first. + + * regex.h (struct re_pattern_buffer): rename + `caller_allocated_regs' to `regs_allocated_p'. + * xregex.c (re_compile_pattern): same change here. + (regexec): and here. + (re_match_2): reallocate registers if necessary. + +Fri Apr 10 07:46:50 1992 Karl Berry (karl@hayley) + + * regex.h (RE_SYNTAX{_POSIX,}_AWK): new definitions from Arnold. + +Sun Mar 15 07:34:30 1992 Karl Berry (karl at hayley) + + * GNUmakefile (dist): versionize regex.{c,h,texinfo}. + +Tue Mar 10 07:05:38 1992 Karl Berry (karl at hayley) + + * Version 0.4. + + * xregex.c (PUSH_FAILURE_POINT): always increment the failure id. + (DEBUG_STATEMENT) [DEBUG]: execute the statement even if `debug'==0. + + * xregex.c (pop_failure_point): if the saved string location is + null, keep the current value. + (re_match_2): at fail, test for a dummy failure point by + checking the restored pattern value, not string value. + (re_match_2): new case, `on_failure_keep_string_jump'. + (regex_compile): output this opcode in the .*\n case. + * regexinc.c (re_opcode_t): define the opcode. + (partial_compiled_pattern_pattern): add the new case. + +Mon Mar 9 09:09:27 1992 Karl Berry (karl at hayley) + + * xregex.c (regex_compile): optimize .*\n to output an + unconditional jump to the ., instead of pushing failure points + each time through the loop. + + * xregex.c (DOUBLE_FAILURE_STACK): compute the maximum size + ourselves (and correctly); change callers. + +Sun Mar 8 17:07:46 1992 Karl Berry (karl at hayley) + + * xregex.c (failure_stack_elt_t): change to `const char *', to + avoid warnings. + + * regex.h (re_set_syntax): declare this. + + * xregex.c (pop_failure_point) [DEBUG]: conditionally pass the + original strings and sizes; change callers. + +Thu Mar 5 16:35:35 1992 Karl Berry (karl at claude.cs.umb.edu) + + * xregex.c (regnum_t): new type for register/group numbers. + (compile_stack_elt_t, regex_compile): use it. + + * xregex.c (regexec): declare len as `int' to match re_search. + + * xregex.c (re_match_2): don't declare p1 twice. + + * xregex.c: change `while (1)' to `for (;;)' to avoid silly + compiler warnings. + + * regex.h [__STDC__]: use #if, not #ifdef. + + * regexinc.c (REGEX_REALLOCATE): cast the result of alloca to + (char *), to avoid warnings. + + * xregex.c (regerror): declare variable as const. + + * xregex.c (re_compile_pattern, re_comp): define as returning a const + char *. + * regex.h (re_compile_pattern, re_comp): likewise. + +Thu Mar 5 15:57:56 1992 Karl Berry (karl@hal) + + * xregex.c (regcomp): declare `syntax' as unsigned. + + * xregex.c (re_match_2): try to avoid compiler warnings about + unsigned comparisons. + + * GNUmakefile (test-xlc): new target. + + * regex.h (reg_errcode_t): remove trailing comma from definition. + * regexinc.c (re_opcode_t): likewise. + +Thu Mar 5 06:56:07 1992 Karl Berry (karl at hayley) + + * GNUmakefile (dist): add version numbers automatically. + (versionfiles): new variable. + (regex.{c,texinfo}): don't add version numbers here. + * regex.h: put in placeholder instead of the version number. + +Fri Feb 28 07:11:33 1992 Karl Berry (karl at hayley) + + * xregex.c (re_error_msg): declare const, since it is. + +Sun Feb 23 05:41:57 1992 Karl Berry (karl at fosse) + + * xregex.c (PAT_PUSH{,_2,_3}, ...): cast args to avoid warnings. + (regex_compile, regexec): return REG_NOERROR, instead + of 0, on success. + (boolean): define as char, and #define false and true. + * regexinc.c (STREQ): cast the result. + +Sun Feb 23 07:45:38 1992 Karl Berry (karl at hayley) + + * GNUmakefile (test-cc, test-hc, test-pcc): new targets. + + * regex.inc (extract_number, extract_number_and_incr) [DEBUG]: + only define if we are debugging. + + * xregex.c [_AIX]: do #pragma alloca first if necessary. + * regexinc.c [_AIX]: remove the #pragma from here. + + * regex.h (reg_syntax_t): declare as unsigned, and redo the enum + as #define's again. Some compilers do stupid things with enums. + +Thu Feb 20 07:19:47 1992 Karl Berry (karl at hayley) + + * Version 0.3. + + * xregex.c, regex.h (newline_anchor_match_p): rename to + `newline_anchor'; dumb idea to change the name. + +Tue Feb 18 07:09:02 1992 Karl Berry (karl at hayley) + + * regexinc.c: go back to original, i.e., don't include + <string.h> or define strchr. + * xregex.c (regexec): don't bother with adding characters after + newlines to the fastmap; instead, just don't use a fastmap. + * xregex.c (regcomp): set the buffer and fastmap fields to zero. + + * xregex.texinfo (GNU r.e. compiling): have to initialize more + than two fields. + + * regex.h (struct re_pattern_buffer): rename `newline_anchor' to + `newline_anchor_match_p', as we're back to two cases. + * xregex.c (regcomp, re_compile_pattern, re_comp): change + accordingly. + (re_match_2): at begline and endline, POSIX is not a special + case anymore; just check newline_anchor_match_p. + +Thu Feb 13 16:29:33 1992 Karl Berry (karl at hayley) + + * xregex.c (*empty_string*): rename to *null_string*, for brevity. + +Wed Feb 12 06:36:22 1992 Karl Berry (karl at hayley) + + * xregex.c (re_compile_fastmap): at endline, don't set fastmap['\n']. + (re_match_2): rewrite the begline/endline cases to take account + of the new field newline_anchor. + +Tue Feb 11 14:34:55 1992 Karl Berry (karl at hayley) + + * regexinc.c [!USG etc.]: include <strings.h> and define strchr + as index. + + * xregex.c (re_search_2): when searching backwards, declare `c' + as a char and use casts when using it as an array subscript. + + * xregex.c (regcomp): if REG_NEWLINE, set + RE_HAT_LISTS_NOT_NEWLINE. Set the `newline_anchor' field + appropriately. + (regex_compile): compile [^...] as matching a \n according to + the syntax bit. + (regexec): if doing REG_NEWLINE stuff, compile a fastmap and add + characters after any \n's to the newline. + * regex.h (RE_HAT_LISTS_NOT_NEWLINE): new syntax bit. + (struct re_pattern_buffer): rename `posix_newline' to + `newline_anchor', define constants for its values. + +Mon Feb 10 07:22:50 1992 Karl Berry (karl at hayley) + + * xregex.c (re_compile_fastmap): combine the code at the top and + bottom of the loop, as it's essentially identical. + +Sun Feb 9 10:02:19 1992 Karl Berry (karl at hayley) + + * xregex.texinfo (POSIX Translate Tables): remove this, as it + doesn't match the spec. + + * xregex.c (re_compile_fastmap): if we finish off a path, go + back to the top (to set can_be_null) instead of returning + immediately. + + * xregex.texinfo: changes from bob. + +Sat Feb 1 07:03:25 1992 Karl Berry (karl at hayley) + + * xregex.c (re_search_2): doc fix (from rms). + +Fri Jan 31 09:52:04 1992 Karl Berry (karl at hayley) + + * xregex.texinfo (GNU Searching): clarify the range arg. + + * xregex.c (re_match_2, at_endline_op_p): add extra parens to + get rid of GCC 2's (silly, IMHO) warning about && within ||. + + * xregex.c (common_op_match_empty_string_p): use + MATCH_NOTHING_UNSET_VALUE, not -1. + +Thu Jan 16 08:43:02 1992 Karl Berry (karl at hayley) + + * xregex.c (SET_REGS_MATCHED): only set the registers from + lowest to highest. + + * regexinc.c (MIN): new macro. + * xregex.c (re_match_2): only check min (num_regs, + regs->num_regs) when we set the returned regs. + + * xregex.c (re_match_2): set registers after the first + num_regs to -1 before we return. + +Tue Jan 14 16:01:42 1992 Karl Berry (karl at hayley) + + * xregex.c (re_match_2): initialize max (RE_NREGS, re_nsub + 1) + registers (from rms). + + * xregex.c, regex.h: don't abbreviate `19xx' to `xx'. + + * regexinc.c [!emacs]: include <sys/types.h> before <unistd.h>. + (from ro@thp.Uni-Koeln.DE). + +Thu Jan 9 07:23:00 1992 Karl Berry (karl at hayley) + + * xregex.c (*unmatchable): rename to `match_empty_string_p'. + (CAN_MATCH_NOTHING): rename to `REG_MATCH_EMPTY_STRING_P'. + + * regexinc.c (malloc, realloc): remove prototypes, as they can + cause clashes (from rms). + +Mon Jan 6 12:43:24 1992 Karl Berry (karl at claude.cs.umb.edu) + + * Version 0.2. + +Sun Jan 5 10:50:38 1992 Karl Berry (karl at hayley) + + * xregex.texinfo: bring more or less up-to-date. + * GNUmakefile (regex.texinfo): generate from regex.h and + xregex.texinfo. + * include.awk: new file. + + * xregex.c: change all calls to the fn extract_number_and_incr + to the macro. + + * xregex.c (re_match_2) [emacs]: in at_dot, use PTR_CHAR_POS + 1, + instead of bf_* and sl_*. Cast d to unsigned char *, to match + the declaration in Emacs' buffer.h. + [emacs19]: in before_dot, at_dot, and after_dot, likewise. + + * regexinc.c: unconditionally include <sys/types.h>. + + * regexinc.c (alloca) [!alloca]: Emacs config files sometimes + define this, so don't define it if it's already defined. + +Sun Jan 5 06:06:53 1992 Karl Berry (karl at fosse) + + * xregex.c (re_comp): fix type conflicts with regex_compile (we + haven't been compiling this). + + * regexinc.c (SIGN_EXTEND_CHAR): use `__CHAR_UNSIGNED__', not + `CHAR_UNSIGNED'. + + * regexinc.c (NULL) [!NULL]: define it (as zero). + + * regexinc.c (extract_number): remove the temporaries. + +Sun Jan 5 07:50:14 1992 Karl Berry (karl at hayley) + + * regex.h (regerror) [!__STDC__]: return a size_t, not a size_t *. + + * xregex.c (PUSH_FAILURE_POINT, ...): declare `destination' as + `char *' instead of `void *', to match alloca declaration. + + * xregex.c (regerror): use `size_t' for the intermediate values + as well as the return type. + + * xregex.c (regexec): cast the result of malloc. + + * xregex.c (regexec): don't initialize `private_preg' in the + declaration, as old C compilers can't do that. + + * xregex.c (main) [test]: declare printchar void. + + * xregex.c (assert) [!DEBUG]: define this to do nothing, and + remove #ifdef DEBUG's from around asserts. + + * xregex.c (re_match_2): remove error message when not debugging. + +Sat Jan 4 09:45:29 1992 Karl Berry (karl at hayley) + + * other.c: test the bizarre duplicate case in re_compile_fastmap + that I just noticed. + + * test.c (general_test): don't test registers beyond the end of + correct_regs, as well as regs. + + * xregex.c (regex_compile): at handle_close, don't assign to + *inner_group_loc if we didn't push a start_memory (because the + group number was too big). In fact, don't push or pop the + inner_group_offset in that case. + + * regex.c: rename to xregex.c, since it's not the whole thing. + * regex.texinfo: likewise. + * GNUmakefile: change to match. + + * regex.c [DEBUG]: only include <stdio.h> if debugging. + + * regexinc.c (SIGN_EXTEND_CHAR) [CHAR_UNSIGNED]: if it's already + defined, don't redefine it. + + * regex.c: define _GNU_SOURCE at the beginning. + * regexinc.c (isblank) [!isblank]: define it. + (isgraph) [!isgraph]: change conditional to this, and remove the + sequent stuff. + + * regex.c (regex_compile): add `blank' character class. + + * regex.c (regex_compile): don't use a uchar variable to loop + through all characters. + + * regex.c (regex_compile): at '[', improve logic for checking + that we have enough space for the charset. + + * regex.h (struct re_pattern_buffer): declare translate as char + * again. We only use it as an array subscript once, I think. + + * regex.c (TRANSLATE): new macro to cast the data character + before subscripting. + (num_internal_regs): rename to `num_regs'. + +Fri Jan 3 07:58:01 1992 Karl Berry (karl at hayley) + + * regex.h (struct re_pattern_buffer): declare `allocated' and + `used' as unsigned long, since these are never negative. + + * regex.c (compile_stack_element): rename to compile_stack_elt_t. + (failure_stack_element): similarly. + + * regexinc.c (TALLOC, RETALLOC): new macros to simplify + allocation of arrays. + + * regex.h (re_*) [__STDC__]: don't declare string args unsigned + char *; that makes them incompatible with string constants. + (struct re_pattern_buffer): declare the pattern and translate + table as unsigned char *. + * regex.c (most routines): use unsigned char vs. char consistently. + + * regex.h (re_compile_pattern): do not declare the length arg as + const. + * regex.c (re_compile_pattern): likewise. + + * regex.c (POINTER_TO_REG): rename to `POINTER_TO_OFFSET'. + + * regex.h (re_registers): declare `start' and `end' as + `regoff_t', instead of `int'. + + * regex.c (regexec): if either of the malloc's for the register + information fail, return failure. + + * regex.h (RE_NREGS): define this again, as 30 (from jla). + (RE_ALLOCATE_REGISTERS): remove this. + (RE_SYNTAX_*): remove it from definitions. + (re_pattern_buffer): remove `return_default_num_regs', add + `caller_allocated_regs'. + * regex.c (re_compile_pattern): clear no_sub and + caller_allocated_regs in the pattern. + (regcomp): set caller_allocated_regs. + (re_match_2): do all register allocation at the end of the + match; implement new semantics. + + * regex.c (MAX_REGNUM): new macro. + (regex_compile): at handle_open and handle_close, if the group + number is too large, don't push the start/stop memory. + +Thu Jan 2 07:56:10 1992 Karl Berry (karl at hayley) + + * regex.c (re_match_2): if the back reference is to a group that + never matched, then goto fail, not really_fail. Also, don't + test if the pattern can match the empty string. Why did we + ever do that? + (really_fail): this label no longer needed. + + * regexinc.c [STDC_HEADERS]: use only this to test if we should + include <stdlib.h>. + + * regex.c (DO_RANGE, regex_compile): translate in all cases + except the single character after a \. + + * regex.h (RE_AWK_CLASS_HACK): rename to + RE_BACKSLASH_ESCAPE_IN_LISTS. + * regex.c (regex_compile): change use. + + * regex.c (re_compile_fastmap): do not translate the characters + again; we already translated them at compilation. (From ylo@ngs.fi.) + + * regex.c (re_match_2): in case for at_dot, invert sense of + comparison and find the character number properly. (From + worley@compass.com.) + (re_match_2) [emacs]: remove the cases for before_dot and + after_dot, since there's no way to specify them, and the code + is wrong (judging from this change). + +Wed Jan 1 09:13:38 1992 Karl Berry (karl at hayley) + + * psx-{interf,basic,extend}.c, other.c: set `t' as the first + thing, so that if we run them in sucession, general_test's + kludge to see if we're doing POSIX tests works. + + * test.h (test_type): add `all_test'. + * main.c: add case for `all_test'. + + * regexinc.c (partial_compiled_pattern_printer, + double_string_printer): don't print anything if we're passed null. + + * regex.c (PUSH_FAILURE_POINT): do not scan for the highest and + lowest active registers. + (re_match_2): compute lowest/highest active regs at start_memory and + stop_memory. + (NO_{LOW,HIGH}EST_ACTIVE_REG): new sentinel values. + (pop_failure_point): return the lowest/highest active reg values + popped; change calls. + + * regex.c [DEBUG]: include <assert.h>. + (various routines) [DEBUG]: change conditionals to assertions. + + * regex.c (DEBUG_STATEMENT): new macro. + (PUSH_FAILURE_POINT): use it to increment num_regs_pushed. + (re_match_2) [DEBUG]: only declare num_regs_pushed if DEBUG. + + * regex.c (*can_match_nothing): rename to *unmatchable. + + * regex.c (re_match_2): at stop_memory, adjust argument reading. + + * regex.h (re_pattern_buffer): declare `can_be_null' as a 2-bit + bit field. + + * regex.h (re_pattern_buffer): declare `buffer' unsigned char *; + no, dumb idea. The pattern can have signed number. + + * regex.c (re_match_2): in maybe_pop_jump case, skip over the + right number of args to the group operators, and don't do + anything with endline if posix_newline is not set. + + * regex.c, regexinc.c (all the things we just changed): go back + to putting the inner group count after the start_memory, + because we need it in the on_failure_jump case in re_match_2. + But leave it after the stop_memory also, since we need it + there in re_match_2, and we don't have any way of getting back + to the start_memory. + + * regexinc.c (partial_compiled_pattern_printer): adjust argument + reading for start/stop_memory. + * regex.c (re_compile_fastmap, group_can_match_nothing): likewise. + +Tue Dec 31 10:15:08 1991 Karl Berry (karl at hayley) + + * regex.c (bits list routines): remove these. + (re_match_2): get the number of inner groups from the pattern, + instead of keeping track of it at start and stop_memory. + Put the count after the stop_memory, not after the + start_memory. + (compile_stack_element): remove `fixup_inner_group' member, + since we now put it in when we can compute it. + (regex_compile): at handle_open, don't push the inner group + offset, and at handle_close, don't pop it. + + * regex.c (level routines): remove these, and their uses in + regex_compile. This was another manifestation of having to find + $'s that were endlines. + + * regex.c (regexec): this does searching, not matching (a + well-disguised part of the standard). So rewrite to use + `re_search' instead of `re_match'. + * psx-interf.c (test_regexec): add tests to, uh, match. + + * regex.h (RE_TIGHT_ALT): remove this; nobody uses it. + * regex.c: remove the code that was supposed to implement it. + + * other.c (test_others): ^ and $ never match newline characters; + RE_CONTEXT_INVALID_OPS doesn't affect anchors. + + * psx-interf.c (test_regerror): update for new error messages. + + * psx-extend.c: it's now ok to have an alternative be just a $, + so remove all the tests which supposed that was invalid. + +Wed Dec 25 09:00:05 1991 Karl Berry (karl at hayley) + + * regex.c (regex_compile): in handle_open, don't skip over ^ and + $ when checking for an empty group. POSIX has changed the + grammar. + * psx-extend.c (test_posix_extended): thus, move (^$) tests to + valid section. + + * regexinc.c (boolean): move from here to test.h and regex.c. + * test files: declare verbose, omit_register_tests, and + test_should_match as boolean. + + * psx-interf.c (test_posix_c_interface): remove the `c_'. + * main.c: likewise. + + * psx-basic.c (test_posix_basic): ^ ($) is an anchor after + (before) an open (close) group. + + * regex.c (re_match_2): in endline, correct precedence of + posix_newline condition. + +Tue Dec 24 06:45:11 1991 Karl Berry (karl at hayley) + + * test.h: incorporate private-tst.h. + * test files: include test.h, not private-tst.h. + + * test.c (general_test): set posix_newline to zero if we are + doing POSIX tests (unfortunately, it's difficult to call + regcomp in this case, which is what we should really be doing). + + * regex.h (reg_syntax_t): make this an enumeration type which + defines the syntax bits; renames re_syntax_t. + + * regex.c (at_endline_op_p): don't preincrement p; then if it's + not an empty string op, we lose. + + * regex.h (reg_errcode_t): new enumeration type of the error + codes. + * regex.c (regex_compile): return that type. + + * regex.c (regex_compile): in [, initialize + just_had_a_char_class to false; somehow I had changed this to + true. + + * regex.h (RE_NO_CONSECUTIVE_REPEATS): remove this, since we + don't use it, and POSIX doesn't require this behavior anymore. + * regex.c (regex_compile): remove it from here. + + * regex.c (regex_compile): remove the no_op insertions for + verify_and_adjust_endlines, since that doesn't exist anymore. + + * regex.c (regex_compile) [DEBUG]: use printchar to print the + pattern, so unprintable bytes will print properly. + + * regex.c: move re_error_msg back. + * test.c (general_test): print the compile error if the pattern + was invalid. + +Mon Dec 23 08:54:53 1991 Karl Berry (karl at hayley) + + * regexinc.c: move re_error_msg here. + + * regex.c (re_error_msg): the ``message'' for success must be + NULL, to keep the interface to re_compile_pattern the same. + (regerror): if the msg is null, use "Success". + + * rename most test files for consistency. Change Makefile + correspondingly. + + * test.c (most routines): add casts to (unsigned char *) when we + call re_{match,search}{,_2}. + +Sun Dec 22 09:26:06 1991 Karl Berry (karl at hayley) + + * regex.c (re_match_2): declare string args as unsigned char * + again; don't declare non-pointer args const; declare the + pattern buffer const. + (re_match): likewise. + (re_search_2, re_search): likewise, except don't declare the + pattern const, since we make a fastmap. + * regex.h [__STDC__]: change prototypes. + + * regex.c (regex_compile): return an error code, not a string. + (re_err_list): new table to map from error codes to string. + (re_compile_pattern): return an element of re_err_list. + (regcomp): don't test all the strings. + (regerror): just use the list. + (put_in_buffer): remove this. + + * regex.c (equivalent_failure_points): remove this. + + * regex.c (re_match_2): don't copy the string arguments into + non-const pointers. We never alter the data. + + * regex.c (re_match_2): move assignment to `is_a_jump_n' out of + the main loop. Just initialize it right before we do + something with it. + + * regex.[ch] (re_match_2): don't declare the int parameters const. + +Sat Dec 21 08:52:20 1991 Karl Berry (karl at hayley) + + * regex.h (re_syntax_t): new type; declare to be unsigned + (previously we used int, but since we do bit operations on + this, unsigned is better, according to H&S). + (obscure_syntax, re_pattern_buffer): use that type. + * regex.c (re_set_syntax, regex_compile): likewise. + + * regex.h (re_pattern_buffer): new field `posix_newline'. + * regex.c (re_comp, re_compile_pattern): set to zero. + (regcomp): set to REG_NEWLINE. + * regex.h (RE_HAT_LISTS_NOT_NEWLINE): remove this (we can just + check `posix_newline' instead.) + + * regex.c (op_list_type, op_list, add_op): remove these. + (verify_and_adjust_endlines): remove this. + (pattern_offset_list_type, *pattern_offset* routines): and these. + These things all implemented the nonleading/nontrailing position + code, which was very long, had a few remaining problems, and + is no longer needed. So... + + * regexinc.c (STREQ): new macro to abbreviate strcmp(,)==0, for + brevity. Change various places in regex.c to use it. + + * regex{,inc}.c (enum regexpcode): change to a typedef + re_opcode_t, for brevity. + + * regex.h (re_syntax_table) [SYNTAX_TABLE]: remove this; it + should only be in regex.c, I think, since we don't define it + in this case. Maybe it should be conditional on !SYNTAX_TABLE? + + * regexinc.c (partial_compiled_pattern_printer): simplify and + distinguish the emacs/not-emacs (not)wordchar cases. + +Fri Dec 20 08:11:38 1991 Karl Berry (karl at hayley) + + * regexinc.c (regexpcode) [emacs]: only define the Emacs opcodes + if we are ifdef emacs. + + * regex.c (BUF_PUSH*): rename to PAT_PUSH*. + + * regex.c (regex_compile): in $ case, go back to essentially the + original code for deciding endline op vs. normal char. + (at_endline_op_p): new routine. + * regex.h (RE_ANCHORS_ONLY_AT_ENDS, RE_CONTEXT_INVALID_ANCHORS, + RE_REPEATED_ANCHORS_AWAY, RE_NO_ANCHOR_AT_NEWLINE): remove + these. POSIX has simplified the rules for anchors in draft + 11.2. + (RE_NEWLINE_ORDINARY): new syntax bit. + (RE_CONTEXT_INDEP_ANCHORS): change description to be compatible + with POSIX. + * regex.texinfo (Syntax Bits): remove the descriptions. + +Mon Dec 16 08:12:40 1991 Karl Berry (karl at hayley) + + * regex.c (re_match_2): in jump_past_next_alt, unconditionally + goto no_pop. The only register we were finding was one which + enclosed the whole alternative expression, not one around an + individual alternative. So we were never doing what we + thought we were doing, and this way makes (|a) against the + empty string fail. + + * regex.c (regex_compile): remove `highest_ever_regnum', and + don't restore regnum from the stack; just put it into a + temporary to put into the stop_memory. Otherwise, groups + aren't numbered consecutively. + + * regex.c (is_in_compile_stack): rename to + `group_in_compile_stack'; remove unnecessary test for the + stack being empty. + + * regex.c (re_match_2): in on_failure_jump, skip no_op's before + checking for the start_memory, in case we were called from + succeed_n. + +Sun Dec 15 16:20:48 1991 Karl Berry (karl at hayley) + + * regex.c (regex_compile): in duplicate case, use + highest_ever_regnum instead of regnum, since the latter is + reverted at stop_memory. + + * regex.c (re_match_2): in on_failure_jump, if the * applied to + a group, save the information for that group and all inner + groups (by making it active), even though we're not inside it + yet. + +Sat Dec 14 09:50:59 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_ITEM, POP_FAILURE_ITEM): new macros. + Use them instead of copying the stack manipulating a zillion + times. + + * regex.c (PUSH_FAILURE_POINT, pop_failure_point) [DEBUG]: save + and restore a unique identification value for each failure point. + + * regexinc.c (partial_compiled_pattern_printer): don't print an + extra / after duplicate commands. + + * regex.c (regex_compile): in back-reference case, allow a back + reference to register `regnum'. Otherwise, even `\(\)\1' + fails, since regnum is 1 at the back-reference. + + * regex.c (re_match_2): in fail, don't examine the pattern if we + restored to pend. + + * test_private.h: rename to private_tst.h. Change includes. + + * regex.c (extend_bits_list): compute existing size for realloc + in bytes, not blocks. + + * regex.c (re_match_2): in jump_past_next_alt, the for loop was + missing its (empty) statement. Even so, some register tests + still fail, although in a different way than in the previous change. + +Fri Dec 13 15:55:08 1991 Karl Berry (karl at hayley) + + * regex.c (re_match_2): in jump_past_next_alt, unconditionally + goto no_pop, since we weren't properly detecting if the + alternative matched something anyway. No, we need to not jump + to keep the register values correct; just change to not look at + register zero and not test RE_NO_EMPTY_ALTS (which is a + compile-time thing). + + * regex.c (SET_REGS_MATCHED): start the loop at 1, since we never + care about register zero until the very end. (I think.) + + * regex.c (PUSH_FAILURE_POINT, pop_failure_point): go back to + pushing and popping the active registers, instead of only doing + the registers before a group: (fooq|fo|o)*qbar against fooqbar + fails, since we restore back into the middle of group 1, yet it + isn't active, because the previous restore clobbered the active flag. + +Thu Dec 12 17:25:36 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_POINT): do not call + `equivalent_failure_points' after all; it causes the registers + to be ``wrong'' (according to POSIX), and an infinite loop on + `((a*)*)*' against `ab'. + + * regex.c (re_compile_fastmap): don't push `pend' on the failure + stack. + +Tue Dec 10 10:30:03 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_POINT): if pushing same failure point that + is on the top of the stack, fail. + (equivalent_failure_points): new routine. + + * regex.c (re_match_2): add debug statements for every opcode we + execute. + + * regex.c (regex_compile/handle_close): restore + `fixup_inner_group_count' and `regnum' from the stack. + +Mon Dec 9 13:51:15 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_POINT): declare `this_reg' as int, so + unsigned arithmetic doesn't happen when we don't want to save + the registers. + +Tue Dec 3 08:11:10 1991 Karl Berry (karl at hayley) + + * regex.c (extend_bits_list): divide size by bits/block. + + * regex.c (init_bits_list): remove redundant assignmen to + `bits_list_ptr'. + + * regexinc.c (partial_compiled_pattern_printer): don't do *p++ + twice in the same expr. + + * regex.c (re_match_2): at on_failure_jump, use the correct + pattern positions for getting the stuff following the start_memory. + + * regex.c (struct register_info): remove the bits_list for the + inner groups; make that a separate variable. + +Mon Dec 2 10:42:07 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_POINT): don't pass `failure_stack' as an + arg; change callers. + + * regex.c (PUSH_FAILURE_POINT): print items in order they are + pushed. + (pop_failure_point): likewise. + + * regex.c (main): prompt for the pattern and string. + + * regex.c (FREE_VARIABLES) [!REGEX_MALLOC]: declare as nothing; + remove #ifdefs from around calls. + + * regex.c (extract_number, extract_number_and_incr): declare static. + + * regex.c: remove the canned main program. + * main.c: new file. + * Makefile (COMMON): add main.o. + +Tue Sep 24 06:26:51 1991 Kathy Hargreaves (kathy at fosse) + + * regex.c (re_match_2): Made `pend' and `dend' not register variables. + Only set string2 to string1 if string1 isn't null. + Send address of p, d, regstart, regend, and reg_info to + pop_failure_point. + Put in more debug statements. + + * regex.c [debug]: Added global variable. + (DEBUG_*PRINT*): Only print if `debug' is true. + (DEBUG_DOUBLE_STRING_PRINTER): Changed DEBUG_STRING_PRINTER's + name to this. + Changed some comments. + (PUSH_FAILURE_POINT): Moved and added some debugging statements. + Was saving regstart on the stack twice instead of saving both + regstart and regend; remedied this. + [NUM_REGS_ITEMS]: Changed from 3 to 4, as now save lowest and + highest active registers instead of highest used one. + [NUM_NON_REG_ITEMS]: Changed name of NUM_OTHER_ITEMS to this. + (NUM_FAILURE_ITEMS): Use active registers instead of number 0 + through highest used one. + (re_match_2): Have pop_failure_point put things in the variables. + (pop_failure_point): Have it do what the fail case in re_match_2 + did with the failure stack, instead of throwing away the stuff + popped off. re_match_2 can ignore results when it doesn't + need them. + + +Thu Sep 5 13:23:28 1991 Kathy Hargreaves (kathy at fosse) + + * regex.c (banner): Changed copyright years to be separate. + + * regex.c [CHAR_UNSIGNED]: Put __ at both ends of this name. + [DEBUG, debug_count, *debug_p, DEBUG_PRINT_1, DEBUG_PRINT_2, + DEBUG_COMPILED_PATTERN_PRINTER ,DEBUG_STRING_PRINTER]: + defined these for debugging. + (extract_number): Added this (debuggable) routine version of + the macro EXTRACT_NUMBER. Ditto for EXTRACT_NUMBER_AND_INCR. + (re_compile_pattern): Set return_default_num_regs if the + syntax bit RE_ALLOCATE_REGISTERS is set. + [REGEX_MALLOC]: Renamed USE_ALLOCA to this. + (BUF_POP): Got rid of this, as don't ever use it. + (regex_compile): Made the type of `pattern' not be register. + If DEBUG, print the pattern to compile. + (re_match_2): If had a `$' in the pattern before a `^' then + don't record the `^' as an anchor. + Put (enum regexpcode) before references to b, as suggested + [RE_NO_BK_BRACES]: Changed RE_NO_BK_CURLY_BRACES to this. + (remove_pattern_offset): Removed this unused routine. + (PUSH_FAILURE_POINT): Changed to only save active registers. + Put in debugging statements. + (re_compile_fastmap): Made `pattern' not a register variable. + Use routine for extracting numbers instead of macro. + (re_match_2): Made `p', `mcnt' and `mcnt2' not register variables. + Added `num_regs_pushed' for debugging. + Only malloc registers if the syntax bit RE_ALLOCATE_REGISTERS is set. + Put in debug statements. + Put the macro NOTE_INNER_GROUP's code inline, as it was the + only called in one place. + For debugging, extract numbers using routines instead of macros. + In case fail: only restore pushed active registers, and added + debugging statements. + (pop_failure_point): Test for underfull stack. + (group_can_match_nothing, common_op_can_match_nothing): For + debugging, extract numbers using routines instead of macros. + (regexec): Changed formal parameters to not be prototypes. + Don't initialize `regs' or `private_preg' in their declarations. + +Tue Jul 23 18:38:36 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h [RE_CONTEX_INDEP_OPS]: Moved the anchor stuff out of + this bit. + [RE_UNMATCHED_RIGHT_PAREN_ORD]: Defined this bit. + [RE_CONTEXT_INVALID_ANCHORS]: Defined this bit. + [RE_CONTEXT_INDEP_ANCHORS]: Defined this bit. + Added RE_CONTEXT_INDEP_ANCHORS to all syntaxes which had + RE_CONTEXT_INDEP_OPS. + Took RE_ANCHORS_ONLY_AT_ENDS out of the POSIX basic syntax. + Added RE_UNMATCHED_RIGHT_PAREN_ORD to the POSIX extended + syntax. + Took RE_REPEATED_ANCHORS_AWAY out of the POSIX extended syntax. + Defined REG_NOERROR (which will probably have to go away again). + Changed the type `off_t' to `regoff_t'. + + * regex.c: Changed some commments. + (regex_compile): Added variable `had_an_endline' to keep track + of if hit a `$' since the beginning of the pattern or the last + alternative (if any). + Changed RE_CONTEXT_INVALID_OPS and RE_CONTEXT_INDEP_OPS to + RE_CONTEXT_INVALID_ANCHORS and RE_CONTEXT_INDEP_ANCHORS where + appropriate. + Put a `no_op' in the pattern if a repeat is only zero or one + times; in this case and if it is many times (whereupon a jump + backwards is pushed instead), keep track of the operator for + verify_and_adjust_endlines. + If RE_UNMATCHED_RIGHT_PAREN is set, make an unmatched + close-group operator match `)'. + Changed all error exits to exit (1). + (remove_pattern_offset): Added this routine, but don't use it. + (verify_and_adjust_endlines): At top of routine, if initialize + routines run out of memory, return true after setting + enough_memory false. + At end of endline, et al. case, don't set *p to no_op. + Repetition operators also set the level and active groups' + match statuses, unless RE_REPEATED_ANCHORS_AWAY is set. + (get_group_match_status): Put a return in front of call to get_bit. + (re_compile_fastmap): Changed is_a_succeed_n to a boolean. + If at end of pattern, then if the failure stack isn't empty, + go back to the failure point. + In *jump* case, only pop the stack if what's on top of it is + where we've just jumped to. + (re_search_2): Return -2 instead of val if val is -2. + (group_can_match_nothing, alternative_can_match_nothing, + common_op_can-match_nothing): Now pass in reg_info for the + `duplicate' case. + (re_match_2): Don't skip over the next alternative also if + empty alternatives aren't allowed. + In fail case, if failed to a backwards jump that's part of a + repetition loop, pop the current failure point and use the + next one. + (pop_failure_point): Check that there's as many register items + on the failure stack as the stack says there are. + (common_op_can_match_nothing): Added variables `ret' and + `reg_no' so can set reg_info for the group encountered. + Also break without doing anything if hit a no_op or the other + kinds of `endline's. + If not done already, set reg_info in start_memory case. + Put in no_pop_jump for an optimized succeed_n of zero repetitions. + In succeed_n case, if the number isn't zero, then return false. + Added `duplicate' case. + +Sat Jul 13 11:27:38 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (REG_NOERROR): Added this error code definition. + + * regex.c: Took some redundant parens out of macros. + (enum regexpcode): Added jump_past_next_alt. + Wrapped some macros in `do..while (0)'. + Changed some comments. + (regex_compile): Use `fixup_alt_jump' instead of `fixup_jump'. + Use `maybe_pop_jump' instead of `maybe_pop_failure_jump'. + Use `jump_past_next_alt' instead of `no_pop_jump' when at the + end of an alternative. + (re_match_2): Used REGEX_ALLOCATE for the registers stuff. + In stop_memory case: Add more boolean tests to see if the + group is in a loop. + Added jump_past_next_alt case, which doesn't jump over the + next alternative if the last one didn't match anything. + Unfortunately, to make this work with, e.g., `(a+?*|b)*' + against `bb', I also had to pop the alternative's failure + point, which in turn broke backtracking! + In fail case: Detect a dummy failure point by looking at + failure_stack.avail - 2, not stack[-2]. + (pop_failure_point): Only pop if the stack isn't empty; don't + give an error if it is. (Not sure yet this is correct.) + (group_can_match_nothing): Make it return a boolean instead of int. + Make it take an argument indicating the end of where it should look. + If find a group that can match nothing, set the pointer + argument to past the group in the pattern. + Took out cases which can share with alternative_can_match_nothing + and call common_op_can_match_nothing. + Took ++ out of switch, so could call common_op_can_match_nothing. + Wrote lots more for on_failure_jump case to handle alternatives. + Main loop now doesn't look for matching stop_memory, but + rather the argument END; return true if hit the matching + stop_memory; this way can call itself for inner groups. + (alternative_can_match_nothing): Added for alternatives. + (common_op_can_match_nothing): Added for previous two routines' + common operators. + (regerror): Returns a message saying there's no error if gets + sent REG_NOERROR. + +Wed Jul 3 10:43:15 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c: Removed unnecessary enclosing parens from several macros. + Put `do..while (0)' around a few. + Corrected some comments. + (INIT_FAILURE_STACK_SIZE): Deleted in favor of using + INIT_FAILURE_ALLOC. + (INIT_FAILURE_STACK, DOUBLE_FAILURE_STACK, PUSH_PATTERN_OP, + PUSH_FAILURE_POINT): Made routines of the same name (but with all + lowercase letters) into these macros, so could use `alloca' + when USE_ALLOCA is defined. The reason is stated below for + bits lists. Deleted analogous routines. + (re_compile_fastmap): Added variable void *destination for + PUSH_PATTERN_OP. + (re_match_2): Added variable void *destination for REGEX_REALLOCATE. + Used the failure stack macros in place of the routines. + Detected a dummy failure point by inspecting the failure stack's + (avail - 2)th element, not failure_stack.stack[-2]. This bug + arose when used the failure stack macros instead of the routines. + + * regex.c [USE_ALLOCA]: Put this conditional around previous + alloca stuff and defined these to work differently depending + on whether or not USE_ALLOCA is defined: + (REGEX_ALLOCATE): Uses either `alloca' or `malloc'. + (REGEX_REALLOCATE): Uses either `alloca' or `realloc'. + (INIT_BITS_LIST, EXTEND_BITS_LIST, SET_BIT_TO_VALUE): Defined + macro versions of routines with the same name (only with all + lowercase letters) so could use `alloc' in re_match_2. This + is to prevent core leaks when C-g is used in Emacs and to make + things faster and avoid storage fragmentation. These things + have to be macros because the results of `alloca' go away with + the routine by which it's called. + (BITS_BLOCK_SIZE, BITS_BLOCK, BITS_MASK): Moved to above the + above-mentioned macros instead of before the routines defined + below regex_compile. + (set_bit_to_value): Compacted some code. + (reg_info_type): Changed inner_groups field to be bits_list_type + so could be arbitrarily long and thus handle arbitrary nesting. + (NOTE_INNER_GROUP): Put `do...while (0)' around it so could + use as a statement. + Changed code to use bits lists. + Added variable void *destination for REGEX_REALLOCATE (whose call + is several levels in). + Changed variable name of `this_bit' to `this_reg'. + (FREE_VARIABLES): Only define and use if USE_ALLOCA is defined. + (re_match_2): Use REGEX_ALLOCATE instead of malloc. + Instead of setting INNER_GROUPS of reg_info to zero, have to + use INIT_BITS_LIST and return -2 (and free variables if + USE_ALLOCA isn't defined) if it fails. + +Fri Jun 28 13:45:07 1991 Karl Berry (karl at hayley) + + * regex.c (re_match_2): set value of `dend' when we restore `d'. + + * regex.c: remove declaration of alloca. + + * regex.c (MISSING_ISGRAPH): rename to `ISGRAPH_MISSING'. + + * regex.h [_POSIX_SOURCE]: remove these conditionals; always + define POSIX stuff. + * regex.c (_POSIX_SOURCE): change conditionals to use `POSIX' + instead. + +Sat Jun 1 16:56:50 1991 Kathy Hargreaves (kathy at hayley) + + * regex.*: Changed RE_CONTEXTUAL_* to RE_CONTEXT_*, + RE_TIGHT_VBAR to RE_TIGHT_ALT, RE_NEWLINE_OR to + RE_NEWLINE_ALT, and RE_DOT_MATCHES_NEWLINE to RE_DOT_NEWLINE. + +Wed May 29 09:24:11 1991 Karl Berry (karl at hayley) + + * regex.texinfo (POSIX Pattern Buffers): cross-reference the + correct node name (Match-beginning-of-line, not ..._line). + (Syntax Bits): put @code around all syntax bits. + +Sat May 18 16:29:58 1991 Karl Berry (karl at hayley) + + * regex.c (global): add casts to keep broken compilers from + complaining about malloc and realloc calls. + + * regex.c (isgraph) [MISSING_ISGRAPH]: change test to this, + instead of `#ifndef isgraph', since broken compilers can't + have both a macro and a symbol by the same name. + + * regex.c (re_comp, re_exec) [_POSIX_SOURCE]: do not define. + (regcomp, regfree, regexec, regerror) [_POSIX_SOURCE && !emacs]: + only define in this case. + +Mon May 6 17:37:04 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (re_search, re_search_2): Changed BUFFER to not be const. + + * regex.c (re_compile_pattern): `^' is in a leading position if + it precedes a newline. + (various routines): Added or changed header comments. + (double_pattern_offsets_list): Changed name from + `extend_pattern_offsets_list'. + (adjust_pattern_offsets_list): Changed return value from + unsigned to void. + (verify_and_adjust_endlines): Now returns `true' and `false' + instead of 1 and 0. + `$' is in a leading position if it follows a newline. + (set_bit_to_value, get_bit_value): Exit with error if POSITION < 0 + so now calling routines don't have to. + (init_failure_stack, inspect_failure_stack_top, + pop_failure_stack_top, push_pattern_op, double_failure_stack): + Now return value unsigned instead of boolean. + (re_search, re_search_2): Changed BUFP to not be const. + (re_search_2): Added variable const `private_bufp' to send to + re_match_2. + (push_failure_point): Made return value unsigned instead of boolean. + +Sat May 4 15:32:22 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (re_compile_fastmap): Added extern for this. + Changed some comments. + + * regex.c (re_compile_pattern): In case handle_bar: put invalid + pattern test before levels matching stuff. + Changed some commments. + Added optimizing test for detecting an empty alternative that + ends with a trailing '$' at the end of the pattern. + (re_compile_fastmap): Moved failure_stack stuff to before this + so could use it. Made its stack dynamic. + Made it return an int so that it could return -2 if its stack + couldn't be allocated. + Added to header comment (about the return values). + (init_failure_stack): Wrote so both re_match_2 and + re_compile_fastmap could use it similar stacks. + (double_failure_stack): Added for above reasons. + (push_pattern_op): Wrote for re_compile_fastmap. + (re_search_2): Now return -2 if re_compile_fastmap does. + (re_match_2): Made regstart and regend type failure_stack_element*. + (push_failure_point): Made pattern_place and string_place type + failure_stack_element*. + Call double_failure_stack now. + Return true instead of 1. + +Wed May 1 12:57:21 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c (remove_intervening_anchors): Avoid erroneously making + ops into no_op's by making them no_op only when they're beglines. + (verify_and_adjust_endlines): Don't make '$' a normal character + if it's before a newline. + Look for the endline op in *p, not p[1]. + (failure_stack_element): Added this declaration. + (failure_stack_type): Added this declaration. + (INIT_FAILURE_STACK_SIZE, FAILURE_STACK_EMPTY, + FAILURE_STACK_PTR_EMPTY, REMAINING_AVAIL_SLOTS): Added for + failure stack. + (FAILURE_ITEM_SIZE, PUSH_FAILURE_POINT): Deleted. + (FREE_VARIABLES): Now free failure_stack.stack instead of stackb. + (re_match_2): deleted variables `initial_stack', `stackb', + `stackp', and `stacke' and added `failure_stack' to replace them. + Replaced calls to PUSH_FAILURE_POINT with those to + push_failure_point. + (push_failure_point): Added for re_match_2. + (pop_failure_point): Rewrote to use a failure_stack_type of stack. + (can_match_nothing): Moved definition to below re_match_2. + (bcmp_translate): Moved definition to below re_match_2. + +Mon Apr 29 14:20:54 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c (enum regexpcode): Added codes endline_before_newline + and repeated_endline_before_newline so could detect these + types of endlines in the intermediate stages of a compiled + pattern. + (INIT_FAILURE_ALLOC): Renamed NFAILURES to this and set it to 5. + (BUF_PUSH): Put `do {...} while 0' around this. + (BUF_PUSH_2): Defined this to cut down on expansion of EXTEND_BUFFER. + (regex_compile): Changed some comments. + Now push endline_before_newline if find a `$' before a newline + in the pattern. + If a `$' might turn into an ordinary character, set laststart + to point to it. + In '^' case, if syntax bit RE_TIGHT_VBAR is set, then for `^' + to be in a leading position, it must be first in the pattern. + Don't have to check in one of the else clauses that it's not set. + If RE_CONTEXTUAL_INDEP_OPS isn't set but RE_ANCHORS_ONLY_AT_ENDS + is, make '^' a normal character if it isn't first in the pattern. + Can only detect at the end if a '$' after an alternation op is a + trailing one, so can't immediately detect empty alternatives + if a '$' follows a vbar. + Added a picture of the ``success jumps'' in alternatives. + Have to set bufp->used before calling verify_and_adjust_endlines. + Also do it before returning all error strings. + (remove_intervening_anchors): Now replaces the anchor with + repeated_endline_before_newline if it's an endline_before_newline. + (verify_and_adjust_endlines): Deleted SYNTAX parameter (could + use bufp's) and added GROUP_FORWARD_MATCH_STATUS so could + detect back references referring to empty groups. + Added variable `bend' to point past the end of the pattern buffer. + Added variable `previous_p' so wouldn't have to reinspect the + pattern buffer to see what op we just looked at. + Added endline_before_newline and repeated_endline_before_newline + cases. + When checking if in a trailing position, added case where '$' + has to be at the pattern's end if either of the syntax bits + RE_ANCHORS_ONLY_AT_ENDS or RE_TIGHT_VBAR are set. + Since `endline' can have the intermediate form `endline_in_repeat', + have to change it to `endline' if RE_REPEATED_ANCHORS_AWAY + isn't set. + Now disallow empty alternatives with trailing endlines in them + if RE_NO_EMPTY_ALTS is set. + Now don't make '$' an ordinary character if it precedes a newline. + Don't make it an ordinary character if it's before a newline. + Back references now affect the level matching something only if + they refer to nonempty groups. + (can_match_nothing): Now increment p1 in the switch, which + changes many of the cases, but makes the code more like what + it was derived from. + Adjust the return statement to reflect above. + (struct register_info): Made `can_match_nothing' field an int + instead of a bit so could have -1 in it if never set. + (MAX_FAILURE_ITEMS): Changed name from MAX_NUM_FAILURE_ITEMS. + (FAILURE_ITEM_SIZE): Defined how much space a failure items uses. + (PUSH_FAILURE_POINT): Changed variable `last_used_reg's name + to `highest_used_reg'. + Added variable `num_stack_items' and changed `len's name to + `stack_length'. + Test failure stack limit in terms of number of items in it, not + in terms of its length. rms' fix tested length against number + of items, which was a misunderstanding. + Use `realloc' instead of `alloca' to extend the failure stack. + Use shifts instead of multiplying by 2. + (FREE_VARIABLES): Free `stackb' instead of `initial_stack', as + might may have been reallocated. + (re_match_2): When mallocing `initial_stack', now multiply + the number of items wanted (what was there before) by + FAILURE_ITEM_SIZE. + (pop_failure_point): Need this procedure form of the macro of + the same name for debugging, so left it in and deleted the + macro. + (recomp): Don't free the pattern buffer's translate field. + +Mon Apr 15 09:47:47 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_DUP_MAX): Moved to outside of #ifdef _POSIX_SOURCE. + * regex.c (#include <sys/types.h>): Removed #ifdef _POSIX_SOURCE + condition. + (malloc, realloc): Made return type void* #ifdef __STDC__. + (enum regexpcode): Added endline_in_repeat for the compiler's + use; this never ends up on the final compiled pattern. + (INIT_PATTERN_OFFSETS_LIST_SIZE): Initial size for + pattern_offsets_list_type. + (pattern_offset_type): Type for pattern offsets. + (pattern_offsets_list_type): Type for keeping a list of + pattern offsets. + (anchor_list_type): Changed to above type. + (PATTERN_OFFSETS_LIST_PTR_FULL): Tests if a pattern offsets + list is full. + (ANCHOR_LIST_PTR_FULL): Changed to above. + (BIT_BLOCK_SIZE): Changed to BITS_BLOCK_SIZE and moved to + above bits list routines below regex_compile. + (op_list_type): Defined to be pattern_offsets_list_type. + (compile_stack_type): Changed offsets to be + pattern_offset_type instead of unsigned. + (pointer): Changed the name of all structure fields from this + to `avail'. + (COMPILE_STACK_FULL): Changed so the stack is full if `avail' + is equal to `size' instead of `size' - 1. + (GET_BUFFER_SPACE): Changed `>=' to `>' in the while statement. + (regex_compile): Added variable `enough_memory' so could check + that routine that verifies '$' positions could return an + allocation error. + (group_count): Deleted this variable, as `regnum' already does + this work. + (op_list): Added this variable to keep track of operations + needed for verifying '$' positions. + (anchor_list): Now initialize using routine + `init_pattern_offsets_list'. + Consolidated the three bits_list initializations. + In case '$': Instead of trying to go past constructs which can + follow '$', merely detect the special case where it has to be + at the pattern's end, fix up any fixup jumps if necessary, + record the anchor if necessary and add an `endline' (and + possibly two `no-op's) to the pattern; will call a routine at + the end to verify if it's in a valid position or not. + (init_pattern_offsets_list): Added to initialize pattern + offsets lists. + (extend_anchor_list): Renamed this extend_pattern_offsets_list + and renamed parameters and internal variables appropriately. + (add_pattern_offset): Added this routine which both + record_anchor_position and add_op call. + (adjust_pattern_offsets_list): Add this routine to adjust by + some increment all the pattern offsets a list of such after a + given position. + (record_anchor_position): Now send in offset instead of + calculating it and just call add_pattern_offset. + (adjust_anchor_list): Replaced by above routine. + (remove_intervening_anchors): If the anchor is an `endline' + then replace it with `endline_in_repeat' instead of `no_op'. + (add_op): Added this routine to call in regex_compile + wherever push something relevant to verifying '$' positions. + (verify_and_adjust_endlines): Added routine to (1) verify that + '$'s in a pattern buffer (represented by `endline') were in + valid positions and (2) whether or not they were anchors. + (BITS_BLOCK_SIZE): Renamed BIT_BLOCK_SIZE and moved to right + above bits list routines. + (BITS_BLOCK): Defines which array element of a bits list the + bit corresponding to a given position is in. + (BITS_MASK): Has a 1 where the bit (in a bit list array element) + for a given position is. + +Mon Apr 1 12:09:06 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c (BIT_BLOCK_SIZE): Defined this for using with + bits_list_type, abstracted from level_list_type so could use + for more things than just the level match status. + (regex_compile): Renamed `level_list' variable to + `level_match_status'. + Added variable `group_match_status' of type bits_list_type. + Kept track of whether or not for all groups any of them + matched other than the empty string, so detect if a back + reference in front of a '^' made it nonleading or not. + Do this by setting a match status bit for all active groups + whenever leave a group that matches other than the empty string. + Could detect which groups are active by going through the + stack each time, but or-ing a bits list of active groups with + a bits list of group match status is faster, so make a bits + list of active groups instead. + Have to check that '^' isn't in a leading position before + going to normal_char. + Whenever set level match status of the current level, also set + the match status of all active groups. + Increase the group count and make that group active whenever + open a group. + When close a group, only set the next level down if the + current level matches other than the empty string, and make + the current group inactive. + At a back reference, only set a level's match status if the + group to which the back reference refers matches other than + the empty string. + (init_bits_list): Added to initialize a bits list. + (get_level_value): Deleted this. (Made into + get_level_match_status.) + (extend_bits_list): Added to extend a bits list. (Made this + from deleted routine `extend_level_list'.) + (get_bit): Added to get a bit value from a bits list. (Made + this from deleted routine `get_level_value'.) + (set_bit_to_value): Added to set a bit in a bits list. (Made + this from deleted routine `set_level_value'.) + (get_level_match_status): Added this to get the match status + of a given level. (Made from get_level_value.) + (set_this_level, set_next_lower_level): Made all routines + which set bits extend the bits list if necessary, thus they + now return an unsigned value to indicate whether or not the + reallocation failed. + (increase_level): No longer extends the level list. + (make_group_active): Added to mark as active a given group in + an active groups list. + (make_group_inactive): Added to mark as inactive a given group + in an active groups list. + (set_match_status_of_active_groups): Added to set the match + status of all currently active groups. + (get_group_match_status): Added to get a given group's match status. + (no_levels_match_anything): Removed the paramenter LEVEL. + (PUSH_FAILURE_POINT): Added rms' bug fix and changed RE_NREGS + to num_internal_regs. + +Sun Mar 31 09:04:30 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_ANCHORS_ONLY_AT_ENDS): Added syntax so could + constrain '^' and '$' to only be anchors if at the beginning + and end of the pattern. + (RE_SYNTAX_POSIX_BASIC): Added the above bit. + + * regex.c (enum regexcode): Changed `unused' to `no_op'. + (this_and_lower_levels_match_nothing): Deleted forward reference. + (regex_compile): case '^': if the syntax bit RE_ANCHORS_ONLY_AT_ENDS + is set, then '^' is only an anchor if at the beginning of the + pattern; only record anchor position if the syntax bit + RE_REPEATED_ANCHORS_AWAY is set; the '^' is a normal char if + the syntax bit RE_ANCHORS_ONLY_AT_END is set and we're not at + the beginning of the pattern (and neither RE_CONTEXTUAL_INDEP_OPS + nor RE_CONTEXTUAL_INDEP_OPS syntax bits are set). + Only adjust the anchor list if the syntax bit + RE_REPEATED_ANCHORS_AWAY is set. + + * regex.c (level_list_type): Use to detect when '^' is + in a leading position. + (regex_compile): Added level_list_type level_list variable in + which we keep track of whether or not a grouping level (in its + current or most recent incarnation) matches anything besides the + empty string. Set the bit for the i-th level when detect it + should match something other than the empty string and the bit + for the (i-1)-th level when leave the i-th group. Clear all + bits for the i-th and higher levels if none of 0--(i - 1)-th's + bits are set when encounter an alternation operator on that + level. If no levels are set when hit a '^', then it is in a + leading position. We keep track of which level we're at by + increasing a variable current_level whenever we encounter an + open-group operator and decreasing it whenever we encounter a + close-group operator. + Have to adjust the anchor list contents whenever insert + something ahead of them (such as on_failure_jump's) in the + pattern. + (adjust_anchor_list): Adjusts the offsets in an anchor list by + a given increment starting at a given start position. + (get_level_value): Returns the bit setting of a given level. + (set_level_value): Sets the bit of a given level to a given value. + (set_this_level): Sets (to 1) the bit of a given level. + (set_next_lower_level): Sets (to 1) the bit of (LEVEL - 1) for a + given LEVEL. + (clear_this_and_higher_levels): Clears the bits for a given + level and any higher levels. + (extend_level_list): Adds sizeof(unsigned) more bits to a level list. + (increase_level): Increases by 1 the value of a given level variable. + (decrease_level): Decreases by 1 the value of a given level variable. + (lower_levels_match_nothing): Checks if any levels lower than + the given one match anything. + (no_levels_match_anything): Checks if any levels match anything. + (re_match_2): At case wordbeg: before looking at d-1, check that + we're not at the string's beginning. + At case wordend: Added some illuminating parentheses. + +Mon Mar 25 13:58:51 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_ANCHOR_AT_NEWLINE): Changed syntax bit name + from RE_ANCHOR_NOT_NEWLINE because an anchor never matches the + newline itself, just the empty string either before or after it. + (RE_REPEATED_ANCHORS_AWAY): Added this syntax bit for ignoring + anchors inside groups which are operated on by repetition + operators. + (RE_DOT_MATCHES_NEWLINE): Added this bit so the match-any-character + operator could match a newline when it's set. + (RE_SYNTAX_POSIX_BASIC): Set RE_DOT_MATCHES_NEWLINE in this. + (RE_SYNTAX_POSIX_EXTENDED): Set RE_DOT_MATCHES_NEWLINE and + RE_REPEATED_ANCHORS_AWAY in this. + (regerror): Changed prototypes to new POSIX spec. + + * regex.c (anchor_list_type): Added so could null out anchors inside + repeated groups. + (ANCHOR_LIST_PTR_FULL): Added for above type. + (compile_stack_element): Changed name from stack_element. + (compile_stack_type): Changed name from compile_stack. + (INIT_COMPILE_STACK_SIZE): Changed name from INIT_STACK_SIZE. + (COMPILE_STACK_EMPTY): Changed name from STACK_EMPTY. + (COMPILE_STACK_FULL): Changed name from STACK_FULL. + (regex_compile): Changed SYNTAX parameter to non-const. + Changed variable name `stack' to `compile_stack'. + If syntax bit RE_REPEATED_ANCHORS_AWAY is set, then naively put + anchors in a list when encounter them and then set them to + `unused' when detect they are within a group operated on by a + repetition operator. Need something more sophisticated than + this, as they should only get set to `unused' if they are in + positions where they would be anchors. Also need a better way to + detect contextually invalid anchors. + Changed some commments. + (is_in_compile_stack): Changed name from `is_in_stack'. + (extend_anchor_list): Added to do anchor stuff. + (record_anchor_position): Added to do anchor stuff. + (remove_intervening_anchors): Added to do anchor stuff. + (re_match_2): Now match a newline with the match-any-character + operator if RE_DOT_MATCHES_NEWLINE is set. + Compacted some code. + (regcomp): Added new POSIX newline information to the header + commment. + If REG_NEWLINE cflag is set, then now unset RE_DOT_MATCHES_NEWLINE + in syntax. + (put_in_buffer): Added to do new POSIX regerror spec. Called + by regerror. + (regerror): Changed to take a pattern buffer, error buffer and + its size, and return type `size_t', the size of the full error + message, and the first ERRBUF_SIZE - 1 characters of the full + error message in the error buffer. + +Wed Feb 27 16:38:33 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (#include <sys/types.h>): Removed this as new POSIX + standard has the user include it. + (RE_SYNTAX_POSIX_BASIC and RE_SYNTAX_POSIX_EXTENDED): Removed + RE_HAT_LISTS_NOT_NEWLINE as new POSIX standard has the cflag + REG_NEWLINE now set this. Similarly, added syntax bit + RE_ANCHOR_NOT_NEWLINE as this is now unset by REG_NEWLINE. + (RE_SYNTAX_POSIX_BASIC): Removed syntax bit + RE_NO_CONSECUTIVE_REPEATS as POSIX now allows them. + + * regex.c (#include <sys/types.h>): Added this as new POSIX + standard has the user include it instead of us putting it in + regex.h. + (extern char *re_syntax_table): Made into an extern so the + user could allocate it. + (DO_RANGE): If don't find a range end, now goto invalid_range_end + instead of unmatched_left_bracket. + (regex_compile): Made variable SYNTAX non-const.???? + Reformatted some code. + (re_compile_fastmap): Moved is_a_succeed_n's declaration to + inner braces. + Compacted some code. + (SET_NEWLINE_FLAG): Removed and put inline. + (regcomp): Made variable `syntax' non-const so can unset + RE_ANCHOR_NOT_NEWLINE syntax bit if cflag RE_NEWLINE is set. + If cflag RE_NEWLINE is set, set the RE_HAT_LISTS_NOT_NEWLINE + syntax bit and unset RE_ANCHOR_NOT_NEWLINE one of `syntax'. + +Wed Feb 20 16:33:38 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_CONSECUTIVE_REPEATS): Changed name from + RE_NO_CONSEC_REPEATS. + (REG_ENESTING): Deleted this POSIX return value, as the stack + is now unbounded. + (struct re_pattern_buffer): Changed some comments. + (re_compile_pattern): Changed a comment. + Deleted check on stack upper bound and corresponding error. + Now when there's no interval contents and it's the end of the + pattern, go to unmatched_left_curly_brace instead of end_of_pattern. + Removed nesting_too_deep error, as the stack is now unbounded. + (regcomp): Removed REG_ENESTING case, as the stack is now unbounded. + (regerror): Removed REG_ENESTING case, as the stack is now unbounded. + + * regex.c (MAX_STACK_SIZE): Deleted because don't need upper + bound on array indexed with an unsigned number. + +Sun Feb 17 15:50:24 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h: Changed and added some comments. + + * regex.c (init_syntax_once): Made `_' a word character. + (re_compile_pattern): Added a comment. + (re_match_2): Redid header comment. + (regexec): With header comment about PMATCH, corrected and + removed details found regex.h, adding a reference. + +Fri Feb 15 09:21:31 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c (DO_RANGE): Removed argument parentheses. + Now get untranslated range start and end characters and set + list bits for the translated (if at all) versions of them and + all characters between them. + (re_match_2): Now use regs->num_regs instead of num_regs_wanted + wherever possible. + (regcomp): Now build case-fold translate table using isupper + and tolower facilities so will work on foreign language characters. + +Sat Feb 9 16:40:03 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_HAT_LISTS_NOT_NEWLINE): Changed syntax bit name + from RE_LISTS_NOT_NEWLINE as it only affects nonmatching lists. + Changed all references to the match-beginning-of-string + operator to match-beginning-of-line operator, as this is what + it does. + (RE_NO_CONSEC_REPEATS): Added this syntax bit. + (RE_SYNTAX_POSIX_BASIC): Added above bit to this. + (REG_PREMATURE_END): Changed name to REG_EEND. + (REG_EXCESS_NESTING): Changed name to REG_ENESTING. + (REG_TOO_BIG): Changed name to REG_ESIZE. + (REG_INVALID_PREV_RE): Deleted this return POSIX value. + Added and changed some comments. + + * regex.c (re_compile_pattern): Now sets the pattern buffer's + `return_default_num_regs' field. + (typedef struct stack_element, stack_type, INIT_STACK_SIZE, + MAX_STACK_SIZE, STACK_EMPTY, STACK_FULL): Added for regex_compile. + (INIT_BUF_SIZE): Changed value from 28 to 32. + (BUF_PUSH): Changed name from BUFPUSH. + (MAX_BUF_SIZE): Added so could use in many places. + (IS_CHAR_CLASS_STRING): Replaced is_char_class with this. + (regex_compile): Added a stack which could grow dynamically + and which has struct elements. + Go back to initializing `zero_times_ok' and `many_time_ok' to + 0 and |=ing them inside the loop. + Now disallow consecutive repetition operators if the syntax + bit RE_NO_CONSEC_REPEATS is set. + Now detect trailing backslash when the compiler is expecting a + `?' or a `+'. + Changed calls to GET_BUFFER_SPACE which asked for 6 to ask for + 3, as that's all they needed. + Now check for trailing backslash inside lists. + Now disallow an empty alternative right before an end-of-line + operator. + Now get buffer space before leaving space for a fixup jump. + Now check if at pattern end when at open-interval operator. + Added some comments. + Now check if non-interval repetition operators follow an + interval one if the syntax bit RE_NO_CONSEC_REPEATS is set. + Now only check if what precedes an interval repetition + operator isn't a regular expression which matches one + character if the syntax bit RE_NO_CONSEC_REPEATS is set. + Now return "Unmatched [ or [^" instead of "Unmatched [". + (is_in_stack): Added to check if a given register number is in + the stack. + (re_match_2): If initial variable allocations fail, return -2, + instead of -1. + Now set reg's `num_regs' field when allocating regs. + Now before allocating them, free regs->start and end if they + aren't NULL and return -2 if either allocation fails. + Now use regs->num_regs instead of num_regs_wanted to control + regs loops. + Now increment past the newline when matching it with an + end-of-line operator. + (recomp): Added to the header comment. + Now return REG_ESUBREG if regex_compile returns "Unmatched [ + or [^" instead of doing so if it returns "Unmatched [". + Now return REG_BADRPT if in addition to returning "Missing + preceding regular expression", regex_compile returns "Invalid + preceding regular expression". + Now return new return value names (see regex.h changes). + (regexec): Added to header comment. + Initialize regs structure. + Now match whole string. + Now always free regs.start and regs.end instead of just when + the string matched. + (regerror): Now return "Regex error: Unmatched [ or [^.\n" + instead of "Regex error: Unmatched [.\n". + Now return "Regex error: Preceding regular expression either + missing or not simple.\n" instead of "Regex error: Missing + preceding regular expression.\n". + Removed REG_INVALID_PREV_RE case (it got subsumed into the + REG_BADRPT case). + +Thu Jan 17 09:52:35 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h: Changed a comment. + + * regex.c: Changed and added large header comments. + (re_compile_pattern): Now if detect that `laststart' for an + interval points to a byte code for a regular expression which + matches more than one character, make it an internal error. + (regerror): Return error message, don't print it. + +Tue Jan 15 15:32:49 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (regcomp return codes): Added GNU ones. + Updated some comments. + + * regex.c (DO_RANGE): Changed `obscure_syntax' to `syntax'. + (regex_compile): Added `following_left_brace' to keep track of + where pseudo interval following a valid interval starts. + Changed some instances that returned "Invalid regular + expression" to instead return error strings coinciding with + POSIX error codes. + Changed some comments. + Now consider only things between `[:' and `:]' to be possible + character class names. + Now a character class expression can't end a pattern; at + least a `]' must close the list. + Now if the syntax bit RE_NO_BK_CURLY_BRACES is set, then a + valid interval must be followed by yet another to get an error + for preceding an interval (in this case, the second one) with + a regular expression that matches more than one character. + Now if what follows a valid interval begins with a open + interval operator but doesn't begin a valid interval, then set + following_left_bracket to it, put it in C and go to + normal_char label. + Added some comments. + Return "Invalid character class name" instead of "Invalid + character class". + (regerror): Return messages for all POSIX error codes except + REG_ECOLLATE and REG_NEWLINE, along with all GNU error codes. + Added `break's after all cases. + (main): Call re_set_syntax instead of setting `obscure_syntax' + directly. + +Sat Jan 12 13:37:59 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (Copyright): Updated date. + (#include <sys/types.h>): Include unconditionally. + (RE_CANNOT_MATCH_NEWLINE): Deleted this syntax bit. + (RE_SYNTAX_POSIX_BASIC, RE_SYNTAX_POSIX_EXTENDED): Removed + setting the RE_ANCHOR_NOT_NEWLINE syntax bit from these. + Changed and added some comments. + (struct re_pattern_buffer): Changed some flags from chars to bits. + Added field `syntax'; holds which syntax pattern was compiled with. + Added bit flag `return_default_num_regs'. + (externs for GNU and Berkeley UNIX routines): Added `const's to + parameter types to be compatible with POSIX. + (#define const): Added to support old C compilers. + + * regex.c (Copyright): Updated date. + (enum regexpcode): Deleted `newline'. + (regex_compile): Renamed re_compile_pattern to this, added a + syntax parameter so it can set the pattern buffer's `syntax' + field. + Made `pattern', and `size' `const's so could pass to POSIX + interface routines; also made `const' whatever interval + variables had to be to make this work. + Changed references to `obscure_syntax' to new parameter `syntax'. + Deleted putting `newline' in buffer when see `\n'. + Consider invalid character classes which have nothing wrong + except the character class name; if so, return character-class error. + (is_char_class): Added routine for regex_compile. + (re_compile_pattern): added a new one which calls + regex_compile with `obscure_syntax' as the actual parameter + for the formal `syntax'. + Gave this the old routine's header comments. + Made `pattern', and `size' `const's so could use POSIX interface + routine parameters. + (re_search, re_search_2, re_match, re_match_2): Changed + `pbufp' to `bufp'. + (re_search_2, re_match_2): Changed `mstop' to `stop'. + (re_search, re_search_2): Made all parameters except `regs' + `const's so could use POSIX interface routines parameters. + (re_search_2): Added private copies of `const' parameters so + could change their values. + (re_match_2): Made all parameters except `regs' `const's so + could use POSIX interface routines parameters. + Changed `size1' and `size2' parameters to `size1_arg' and + `size2_arg' and so could change; added local `size1' and + `size2' and set to these. + Added some comments. + Deleted `newline' case. + `begline' can also possibly match if `d' contains a newline; + if it does, we have to increment d to point past the newline. + Replaced references to `obscure_syntax' with `bufp->syntax'. + (re_comp, re_exec): Made parameter `s' a `const' so could use POSIX + interface routines parameters. + Now call regex_compile, passing `obscure_syntax' via the + `syntax' parameter. + (re_exec): Made local `len' a `const' so could pass to re_search. + (regcomp): Added header comment. + Added local `syntax' to set and pass to regex_compile rather + than setting global `obscure_syntax' and passing it. + Call regex_compile with its `syntax' parameter rather than + re_compile_pattern. + Return REG_ECTYPE if character-class error. + (regexec): Don't initialize `regs' to anything. + Made `private_preg' a nonpointer so could set to what the + constant `preg' points. + Initialize `private_preg's `return_default_num_regs' field to + zero because want to return `nmatch' registers, not however + many there are subexpressions in the pattern. + Also test if `nmatch' > 0 to see if should pass re_match `regs'. + +Tue Jan 8 15:57:17 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (struct re_pattern_buffer): Reworded comment. + + * regex.c (EXTEND_BUFFER): Also reset beg_interval. + (re_search_2): Return val if val = -2. + (NUM_REG_ITEMS): Listed items in comment. + (NUM_OTHER_ITEMS): Defined this for using in > 1 definition. + (MAX_NUM_FAILURE_ITEMS): Replaced `+ 2' with NUM_OTHER_ITEMS. + (NUM_FAILURE_ITEMS): As with definition above and added to + comment. + (PUSH_FAILURE_POINT): Replaced `* 2's with `<< 1's. + (re_match_2): Test with equality with 1 to see pbufp->bol and + pbufp->eol are set. + +Fri Jan 4 15:07:22 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (struct re_pattern_buffer): Reordered some fields. + Updated some comments. + Added not_bol and not_eol fields. + (extern regcomp, regexec, regerror): Added return types. + (extern regfree): Added `extern'. + + * regex.c (min): Deleted unused macro. + (re_match_2): Compacted some code. + Removed call to macro `min' from `for' loop. + Fixed so unused registers get filled with -1's. + Fail if the pattern buffer's `not_bol' field is set and + encounter a `begline'. + Fail if the pattern buffer's `not_eol' field is set and + encounter a `endline'. + Deleted redundant check for empty stack in fail case. + Don't free pattern buffer's components in re_comp. + (regexec): Initialize variable regs. + Added `private_preg' pattern buffer so could set `not_bol' and + `not_eol' fields and hand to re_match. + Deleted naive attempt to detect anchors. + Set private pattern buffer's `not_bol' and `not_eol' fields + according to eflags value. + `nmatch' must also be > 0 for us to bother allocating + registers to send to re_match and filling pmatch + with their results after the call to re_match. + Send private pattern buffer instead of argument to re_match. + If use the registers, always free them and then set them to NULL. + (regerror): Added this Posix routine. + (regfree): Added this Posix routine. + +Tue Jan 1 15:02:45 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NREGS): Deleted this definition, as now the user + can choose how many registers to have. + (REG_NOTBOL, REG_NOTEOL): Defined these Posix eflag bits. + (REG_NOMATCH, REG_BADPAT, REG_ECOLLATE, REG_ECTYPE, + REG_EESCAPE, REG_ESUBREG, REG_EBRACK, REG_EPAREN, REG_EBRACE, + REG_BADBR, REG_ERANGE, REG_ESPACE, REG_BADRPT, REG_ENEWLINE): + Defined these return values for Posix's regcomp and regexec. + Updated some comments. + (struct re_pattern_buffer): Now typedef this as regex_t + instead of the other way around. + (struct re_registers): Added num_regs field. Made start and + end fields pointers to char instead of fixed size arrays. + (regmatch_t): Added this Posix register type. + (regcomp, regexec, regerror, regfree): Added externs for these + Posix routines. + + * regex.c (enum boolean): Typedefed this. + (re_pattern_buffer): Reformatted some comments. + (re_compile_pattern): Updated some comments. + Always push start_memory and its attendant number whenever + encounter a group, not just when its number is less than the + previous maximum number of registers; same for stop_memory. + Get 4 bytes of buffer space instead of 2 when pushing a + set_number_at. + (can_match_nothing): Added this to elaborate on and replace + code in re_match_2. + (reg_info_type): Made can_match_nothing field a bit instead of int. + (MIN): Added for re_match_2. + (re_match_2 macros): Changed all `for' loops which used + RE_NREGS to now use num_internal_regs as upper bounds. + (MAX_NUM_FAILURE_ITEMS): Use num_internal_regs instead of RE_NREGS. + (POP_FAILURE_POINT): Added check for empty stack. + (FREE_VARIABLES): Added this to free (and set to NULL) + variables allocated in re_match_2. + (re_match_2): Rearranged parameters to be in order. + Added variables num_regs_wanted (how many registers the user wants) + and num_internal_regs (how many groups there are). + Allocated initial_stack, regstart, regend, old_regstart, + old_regend, reginfo, best_regstart, and best_regend---all + which used to be fixed size arrays. Free them all and return + -1 if any fail. + Free above variables if starting position pos isn't valid. + Changed all `for' loops which used RE_NREGS to now use + num_internal_regs as upper bounds---except for the loops which + fill regs; then use num_regs_wanted. + Allocate regs if the user has passed it and wants more than 0 + registers filled. + Set regs->start[i] and regs->end[i] to -1 if either + regstart[i] or regend[i] equals -1, not just the first. + Free allocated variables before returning. + Updated some comments. + (regcomp): Return REG_ESPACE, REG_BADPAT, REG_EPAREN when + appropriate. + Free translate array. + (regexec): Added this Posix interface routine. + +Mon Dec 24 14:21:13 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: If _POSIX_SOURCE is defined then #include <sys/types.h>. + Added syntax bit RE_CANNOT_MATCH_NEWLINE. + Defined Posix cflags: REG_EXTENDED, REG_NEWLINE, REG_ICASE, and + REG_NOSUB. + Added fields re_nsub and no_sub to struct re_pattern_buffer. + Typedefed regex_t to be `struct re_pattern_buffer'. + + * regex.c (CHAR_SET_SIZE): Defined this to be 256 and replaced + incidences of this value with this constant. + (re_compile_pattern): Added switch case for `\n' and put + `newline' into the pattern buffer when encounter this. + Increment the pattern_buffer's `re_nsub' field whenever open a + group. + (re_match_2): Match a newline with `newline'---provided the + syntax bit RE_CANNOT_MATCH_NEWLINE isn't set. + (regcomp): Added this Posix interface routine. + (enum test_type): Added interface_test tag. + (main): Added Posix interface test. + +Tue Dec 18 12:58:12 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (struct re_pattern_buffer): reformatted so would fit + in texinfo documentation. + +Thu Nov 29 15:49:16 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_EMPTY_ALTS): Added this bit. + (RE_SYNTAX_POSIX_EXTENDED): Added above bit. + + * regex.c (re_compile_pattern): Disallow empty alternatives only + when RE_NO_EMPTY_ALTS is set, not when RE_CONTEXTUAL_INVALID_OPS is. + Changed RE_NO_BK_CURLY_BRACES to RE_NO_BK_PARENS when testing + for empty groups at label handle_open. + At label handle_bar: disallow empty alternatives if RE_NO_EMPTY_ALTS + is set. + Rewrote some comments. + + (re_compile_fastmap): cleaned up code. + + (re_search_2): Rewrote comment. + + (struct register_info): Added field `inner_groups'; it records + which groups are inside of the current one. + Added field can_match_nothing; it's set if the current group + can match nothing. + Added field ever_match_something; it's set if current group + ever matched something. + + (INNER_GROUPS): Added macro to access inner_groups field of + struct register_info. + + (CAN_MATCH_NOTHING): Added macro to access can_match_nothing + field of struct register_info. + + (EVER_MATCHED_SOMETHING): Added macro to access + ever_matched_something field of struct register_info. + + (NOTE_INNER_GROUP): Defined macro to record that a given group + is inside of all currently active groups. + + (re_match_2): Added variables *p1 and mcnt2 (multipurpose). + Added old_regstart and old_regend arrays to hold previous + register values if they need be restored. + Initialize added fields and variables. + case start_memory: Find out if the group can match nothing. + Save previous register values in old_restart and old_regend. + Record that current group is inside of all currently active + groups. + If the group is inside a loop and it ever matched anything, + restore its registers to values before the last failed match. + Restore the registers for the inner groups, too. + case duplicate: Can back reference to a group that never + matched if it can match nothing. + +Thu Nov 29 11:12:54 1990 Karl Berry (karl at hayley) + + * regex.c (bcopy, ...): define these if either _POSIX_SOURCE or + STDC_HEADERS is defined; same for including <stdlib.h>. + +Sat Oct 6 16:04:55 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (struct re_pattern_buffer): Changed field comments. + + * regex.c (re_compile_pattern): Allow a `$' to precede an + alternation operator (`|' or `\|'). + Disallow `^' and/or `$' in empty groups if the syntax bit + RE_NO_EMPTY_GROUPS is set. + Wait until have parsed a valid `\{...\}' interval expression + before testing RE_CONTEXTUAL_INVALID_OPS to see if it's + invalidated by that. + Don't use RE_NO_BK_CURLY_BRACES to test whether or not a validly + parsed interval expression is invalid if it has no preceding re; + rather, use RE_CONTEXTUAL_INVALID_OPS. + If an interval parses, but there is no preceding regular + expression, yet the syntax bit RE_CONTEXTUAL_INDEP_OPS is set, + then that interval can match the empty regular expression; if + the bit isn't set, then the characters in the interval + expression are parsed as themselves (sans the backslashes). + In unfetch_interval case: Moved PATFETCH to above the test for + RE_NO_BK_CURLY_BRACES being set, which would force a goto + normal_backslash; the code at both normal_backsl and normal_char + expect a character in `c.' + +Sun Sep 30 11:13:48 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Changed some comments to use the terms used in the + documentation. + (RE_CONTEXTUAL_INDEP_OPS): Changed name from `RE_CONTEXT_INDEP_OPS'. + (RE_LISTS_NOT_NEWLINE): Changed name from `RE_HAT_NOT_NEWLINE.' + (RE_ANCHOR_NOT_NEWLINE): Added this syntax bit. + (RE_NO_EMPTY_GROUPS): Added this syntax bit. + (RE_NO_HYPHEN_RANGE_END): Deleted this syntax bit. + (RE_SYNTAX_...): Reformatted. + (RE_SYNTAX_POSIX_BASIC, RE_SYNTAX_EXTENDED): Added syntax bits + RE_ANCHOR_NOT_NEWLINE and RE_NO_EMPTY_GROUPS, and deleted + RE_NO_HYPHEN_RANGE_END. + (RE_SYNTAX_POSIX_EXTENDED): Added syntax bit RE_DOT_NOT_NULL. + + * regex.c (bcopy, bcmp, bzero): Define if _POSIX_SOURCE is defined. + (_POSIX_SOURCE): ifdef this, #include <stdlib.h> + (#ifdef emacs): Changed comment of the #endif for the its #else + clause to be `not emacs', not `emacs.' + (no_pop_jump): Changed name from `jump'. + (pop_failure_jump): Changed name from `finalize_jump.' + (maybe_pop_failure_jump): Changed name from `maybe_finalize_jump'. + (no_pop_jump_n): Changed name from `jump_n.' + (EXTEND_BUFFER): Use shift instead of multiplication to double + buf->allocated. + (DO_RANGE, recompile_pattern): Added macro to set the list bits + for a range. + (re_compile_pattern): Fixed grammar problems in some comments. + Checked that RE_NO_BK_VBAR is set to make `$' valid before a `|' + and not set to make it valid before a `\|'. + Checked that RE_NO_BK_PARENS is set to make `$' valid before a ')' + and not set to make it valid before a `\)'. + Disallow ranges starting with `-', unless the range is the + first item in a list, rather than disallowing ranges which end + with `-'. + Disallow empty groups if the syntax bit RE_NO_EMPTY_GROUPS is set. + Disallow nothing preceding `{' and `\{' if they represent the + open-interval operator and RE_CONTEXTUAL_INVALID_OPS is set. + (register_info_type): typedef-ed this using `struct register_info.' + (SET_REGS_MATCHED): Compacted the code. + (re_match_2): Made it fail if back reference a group which we've + never matched. + Made `^' not match a newline if the syntax bit + RE_ANCHOR_NOT_NEWLINE is set. + (really_fail): Added this label so could force a final fail that + would not try to use the failure stack to recover. + +Sat Aug 25 14:23:01 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_CONTEXTUAL_OPS): Changed name from RE_CONTEXT_OPS. + (global): Rewrote comments and rebroke some syntax #define lines. + + * regex.c (isgraph): Added definition for sequents. + (global): Now refer to character set lists as ``lists.'' + Rewrote comments containing ``\('' or ``\)'' to now refer to + ``groups.'' + (RE_CONTEXTUAL_OPS): Changed name from RE_CONTEXT_OPS. + + (re_compile_pattern): Expanded header comment. + +Sun Jul 15 14:50:25 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_CONTEX_INDEP_OPS): the comment's sense got turned + around when we changed how it read; changed it to be correct. + +Sat Jul 14 16:38:06 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_EMPTY_BK_REF): changed name to + RE_NO_MISSING_BK_REF, as this describes it better. + + * regex.c (re_compile_pattern): changed RE_NO_EMPTY_BK_REF + to RE_NO_MISSING_BK_REF, as above. + +Thu Jul 12 11:45:05 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_EMPTY_BRACKETS): removed this syntax bit, as + bracket expressions should *never* be empty regardless of the + syntax. Removes this bit from RE_SYNTAX_POSIX_BASIC and + RE_SYNTAX_POSIX_EXTENDED. + + * regex.c (SET_LIST_BIT): in the comment, now refer to character + sets as (non)matching sets, as bracket expressions can now match + other things in addition to characters. + (re_compile_pattern): refer to groups as such instead of `\(...\)' + or somesuch, because groups can now be enclosed in either plain + parens or backslashed ones, depending on the syntax. + In the '[' case, added a boolean just_had_a_char_class to detect + whether or not a character class begins a range (which is invalid). + Restore way of breaking out of a bracket expression to original way. + Add way to detect a range if the last thing in a bracket + expression was a character class. + Took out check for c != ']' at the end of a character class in + the else clause, as it had already been checked in the if part + that also checked the validity of the string. + Set or clear just_had_a_char_class as appropriate. + Added some comments. Changed references to character sets to + ``(non)matching lists.'' + +Sun Jul 1 12:11:29 1990 Karl Berry (karl at hayley) + + * regex.h (BYTEWIDTH): moved back to regex.c. + + * regex.h (re_compile_fastmap): removed declaration; this + shouldn't be advertised. + +Mon May 28 15:27:53 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (ifndef Sword): Made comments more specific. + (global): include <stdio.h> so can write fatal messages on + standard error. Replaced calls to assert with fprintfs to + stderr and exit (1)'s. + (PREFETCH): Reformatted to make more readable. + (AT_STRINGS_BEG): Defined to test if we're at the beginning of + the virtual concatenation of string1 and string2. + (AT_STRINGS_END): Defined to test if at the end of the virtual + concatenation of string1 and string2. + (AT_WORD_BOUNDARY): Defined to test if are at a word boundary. + (IS_A_LETTER(d)): Defined to test if the contents of the pointer D + is a letter. + (re_match_2): Rewrote the wordbound, notwordbound, wordbeg, wordend, + begbuf, and endbuf cases in terms of the above four new macros. + Called SET_REGS_MATCHED in the matchsyntax, matchnotsyntax, + wordchar, and notwordchar cases. + +Mon May 14 14:49:13 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (re_search_2): Fixed RANGE to not ever take STARTPOS + outside of virtual concatenation of STRING1 and STRING2. + Updated header comment as to this. + (re_match_2): Clarified comment about MSTOP in header. + +Sat May 12 15:39:00 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (re_search_2): Checked for out-of-range STARTPOS. + Added comments. + When searching backwards, not only get the character with which + to compare to the fastmap from string2 if the starting position + >= size1, but also if size1 is zero; this is so won't get a + segmentation fault if string1 is null. + Reformatted code at label advance. + +Thu Apr 12 20:26:21 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Added #pragma once and #ifdef...endif __REGEXP_LIBRARY. + (RE_EXACTN_VALUE): Added for search.c to use. + Reworded some comments. + + regex.c: Punctuated some comments correctly. + (NULL): Removed this. + (RE_EXACTN_VALUE): Added for search.c to use. + (<ctype.h>): Moved this include to top of file. + (<assert.h>): Added this include. + (struct regexpcode): Assigned 0 to unused and 1 to exactn + because of RE_EXACTN_VALUE. + Added comment. + (various macros): Lined up backslashes near end of line. + (insert_jump): Cleaned up the header comment. + (re_search): Corrected the header comment. + (re_search_2): Cleaned up and completed the header comment. + (re_max_failures): Updated comment. + (struct register_info): Constructed as bits so as to save space + on the stack when pushing register information. + (IS_ACTIVE): Macro for struct register_info. + (MATCHED_SOMETHING): Macro for struct register_info. + (NUM_REG_ITEMS): How many register information items for each + register we have to push on the stack at each failure. + (MAX_NUM_FAILURE_ITEMS): If push all the registers on failure, + this is how many items we push on the stack. + (PUSH_FAILURE_POINT): Now pushes whether or not the register is + currently active, and whether or not it matched something. + Checks that there's enough space allocated to accomodate all the + items we currently want to push. (Before, a test for an empty + stack sufficed because we always pushed and popped the same + number of items). + Replaced ``2'' with MAX_NUM_FAILURE_POINTS when ``2'' refers + to how many things get pushed on the stack each time. + When copy the stack into the newly allocated storage, now only copy + the area in use. + Clarified comment. + (POP_FAILURE_POINT): Defined to use in places where put number + of registers on the stack into a variable before using it to + decrement the stack, so as to not confuse the compiler. + (IS_IN_FIRST_STRING): Defined to check if a pointer points into + the first string. + (SET_REGS_MATCHED): Changed to use the struct register_info + bits; also set the matched-something bit to false if the + register isn't currently active. (This is a redundant setting.) + (re_match_2): Cleaned up and completed the header comment. + Updated the failure stack comment. + Replaced the ``2'' with MAX_NUM_FAILURE_ITEMS in the static + allocation of initial_stack, because now more than two (now up + to MAX_FAILURE_ITEMS) items get pushed on the failure stack each + time. + Ditto for stackb. + Trashed restart_seg1, regend_seg1, best_regstart_seg1, and + best_regend_seg1 because they could have erroneous information + in them, such as when matching ``a'' (in string1) and ``ab'' (in + string2) with ``(a)*ab''; before using IS_IN_FIRST_STRING to see + whether or not the register starts or ends in string1, + regstart[1] pointed past the end of string1, yet regstart_seg1 + was 0! + Added variable reg_info of type struct register_info to keep + track of currently active registers and whether or not they + currently match anything. + Commented best_regs_set. + Trashed reg_active and reg_matched_something and put the + information they held into reg_info; saves space on the stack. + Replaced NULL with '\000'. + In begline case, compacted the code. + Used assert to exit if had an internal error. + In begbuf case, because now force the string we're working on + into string2 if there aren't two strings, now allow d == string2 + if there is no string1 (and the check for that is size1 == 0!); + also now succeeds if there aren't any strings at all. + (main, ifdef canned): Put test type into a variable so could + change it while debugging. + +Sat Mar 24 12:24:13 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (GET_UNSIGNED_NUMBER): Deleted references to num_fetches. + (re_compile_pattern): Deleted num_fetches because could keep + track of the number of fetches done by saving a pointer into the + pattern. + Added variable beg_interval to be used as a pointer, as above. + Assert that beg_interval points to something when it's used as above. + Initialize succeed_n's to lower_bound because re_compile_fastmap + needs to know it. + (re_compile_fastmap): Deleted unnecessary variable is_a_jump_n. + Added comment. + (re_match_2): Put number of registers on the stack into a + variable before using it to decrement the stack, so as to not + confuse the compiler. + Updated comments. + Used error routine instead of printf and exit. + In exactn case, restored longer code from ``original'' regex.c + which doesn't test translate inside a loop. + + * regex.h: Moved #define NULL and the enum regexpcode definition + and to regex.c. Changed some comments. + + regex.c (global): Updated comments about compiling and for the + re_compile_pattern jump routines. + Added #define NULL and the enum regexpcode definition (from + regex.h). + (enum regexpcode): Added set_number_at to reset the n's of + succeed_n's and jump_n's. + (re_set_syntax): Updated its comment. + (re_compile_pattern): Moved its heading comment to after its macros. + Moved its include statement to the top of the file. + Commented or added to comments of its macros. + In start_memory case: Push laststart value before adding + start_memory and its register number to the buffer, as they + might not get added. + Added code to put a set_number_at before each succeed_n and one + after each jump_n; rewrote code in what seemed a more + straightforward manner to put all these things in the pattern so + the succeed_n's would correctly jump to the set_number_at's of + the matching jump_n's, and so the jump_n's would correctly jump + to after the set_number_at's of the matching succeed_n's. + Initialize succeed_n n's to -1. + (insert_op_2): Added this to insert an operation followed by + two integers. + (re_compile_fastmap): Added set_number_at case. + (re_match_2): Moved heading comment to after macros. + Added mention of REGS to heading comment. + No longer turn a succeed_n with n = 0 into an on_failure_jump, + because n needs to be reset each time through a loop. + Check to see if a succeed_n's n is set by its set_number_at. + Added set_number_at case. + Updated some comments. + (main): Added another main to run posix tests, which is compiled + ifdef both test and canned. (Old main is still compiled ifdef + test only). + +Tue Mar 19 09:22:55 1990 Kathy Hargreaves (kathy at hayley) + + * regex.[hc]: Change all instances of the word ``legal'' to + ``valid'' and all instances of ``illegal'' to ``invalid.'' + +Sun Mar 4 12:11:31 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Added syntax bit RE_NO_EMPTY_RANGES which is set if + an ending range point has to collate higher or equal to the + starting range point. + Added syntax bit RE_NO_HYPHEN_RANGE_END which is set if a hyphen + can't be an ending range point. + Set to two above bits in RE_SYNTAX_POSIX_BASIC and + RE_SYNTAX_POSIX_EXTENDED. + + regex.c: (re_compile_pattern): Don't allow empty ranges if the + RE_NO_EMPTY_RANGES syntax bit is set. + Don't let a hyphen be a range end if the RE_NO_HYPHEN_RANGE_END + syntax bit is set. + (ESTACK_PUSH_2): renamed this PUSH_FAILURE_POINT and made it + push all the used registers on the stack, as well as the number + of the highest numbered register used, and (as before) the two + failure points. + (re_match_2): Fixed up comments. + Added arrays best_regstart[], best_regstart_seg1[], best_regend[], + and best_regend_seg1[] to keep track of the best match so far + whenever reach the end of the pattern but not the end of the + string, and there are still failure points on the stack with + which to backtrack; if so, do the saving and force a fail. + If reach the end of the pattern but not the end of the string, + but there are no more failure points to try, restore the best + match so far, set the registers and return. + Compacted some code. + In stop_memory case, if the subexpression we've just left is in + a loop, push onto the stack the loop's on_failure_jump failure + point along with the current pointer into the string (d). + In finalize_jump case, in addition to popping the failure + points, pop the saved registers. + In the fail case, restore the registers, as well as the failure + points. + +Sun Feb 18 15:08:10 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c: (global): Defined a macro GET_BUFFER_SPACE which + makes sure you have a specified number of buffer bytes + allocated. + Redefined the macro BUFPUSH to use this. + Added comments. + + (re_compile_pattern): Call GET_BUFFER_SPACE before storing or + inserting any jumps. + + (re_match_2): Set d to string1 + pos and dend to end_match_1 + only if string1 isn't null. + Force exit from a loop if it's around empty parentheses. + In stop_memory case, if found some jumps, increment p2 before + extracting address to which to jump. Also, don't need to know + how many more times can jump_n. + In begline case, d must equal string1 or string2, in that order, + only if they are not null. + In maybe_finalize_jump case, skip over start_memorys' and + stop_memorys' register numbers, too. + +Thu Feb 15 15:53:55 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (BUFPUSH): off by one goof in deciding whether to + EXTEND_BUFFER. + +Wed Jan 24 17:07:46 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Moved definition of NULL to here. + Got rid of ``In other words...'' comment. + Added to some comments. + + regex.c: (re_compile_pattern): Tried to bulletproof some code, + i.e., checked if backward references (e.g., p[-1]) were within + the range of pattern. + + (re_compile_fastmap): Fixed a bug in succeed_n part where was + getting the amount to jump instead of how many times to jump. + + (re_search_2): Changed the name of the variable ``total'' to + ``total_size.'' + Condensed some code. + + (re_match_2): Moved the comment about duplicate from above the + start_memory case to above duplicate case. + + (global): Rewrote some comments. + Added commandline arguments to testing. + +Wed Jan 17 11:47:27 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c: (global): Defined a macro STORE_NUMBER which stores a + number into two contiguous bytes. Also defined STORE_NUMBER_AND_INCR + which does the same thing and then increments the pointer to the + storage place to point after the number. + Defined a macro EXTRACT_NUMBER which extracts a number from two + continguous bytes. Also defined EXTRACT_NUMBER_AND_INCR which + does the same thing and then increments the pointer to the + source to point to after where the number was. + +Tue Jan 16 12:09:19 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Incorporated rms' changes. + Defined RE_NO_BK_REFS syntax bit which is set when want to + interpret back reference patterns as literals. + Defined RE_NO_EMPTY_BRACKETS syntax bit which is set when want + empty bracket expressions to be illegal. + Defined RE_CONTEXTUAL_ILLEGAL_OPS syntax bit which is set when want + it to be illegal for *, +, ? and { to be first in an re or come + immediately after a | or a (, and for ^ not to appear in a + nonleading position and $ in a nontrailing position (outside of + bracket expressions, that is). + Defined RE_LIMITED_OPS syntax bit which is set when want +, ? + and | to always be literals instead of ops. + Fixed up the Posix syntax. + Changed the syntax bit comments from saying, e.g., ``0 means...'' + to ``If this bit is set, it means...''. + Changed the syntax bit defines to use shifts instead of integers. + + * regex.c: (global): Incorporated rms' changes. + + (re_compile_pattern): Incorporated rms' changes + Made it illegal for a $ to appear anywhere but inside a bracket + expression or at the end of an re when RE_CONTEXTUAL_ILLEGAL_OPS + is set. Made the same hold for $ except it has to be at the + beginning of an re instead of the end. + Made the re "[]" illegal if RE_NO_EMPTY_BRACKETS is set. + Made it illegal for | to be first or last in an re, or immediately + follow another | or a (. + Added and embellished some comments. + Allowed \{ to be interpreted as a literal if RE_NO_BK_CURLY_BRACES + is set. + Made it illegal for *, +, ?, and { to appear first in an re, or + immediately follow a | or a ( when RE_CONTEXTUAL_ILLEGAL_OPS is set. + Made back references interpreted as literals if RE_NO_BK_REFS is set. + Made recursive intervals either illegal (if RE_NO_BK_CURLY_BRACES + isn't set) or interpreted as literals (if is set), if RE_INTERVALS + is set. + Made it treat +, ? and | as literals if RE_LIMITED_OPS is set. + Cleaned up some code. + +Thu Dec 21 15:31:32 1989 Kathy Hargreaves (kathy at hayley) + + * regex.c: (global): Moved RE_DUP_MAX to regex.h and made it + equal 2^15 - 1 instead of 1000. + Defined NULL to be zero. + Moved the definition of BYTEWIDTH to regex.h. + Made the global variable obscure_syntax nonstatic so the tests in + another file could use it. + + (re_compile_pattern): Defined a maximum length (CHAR_CLASS_MAX_LENGTH) + for character class strings (i.e., what's between the [: and the + :]'s). + Defined a macro SET_LIST_BIT(c) which sets the bit for C in a + character set list. + Took out comments that EXTEND_BUFFER clobbers C. + Made the string "^" match itself, if not RE_CONTEXT_IND_OPS. + Added character classes to bracket expressions. + Change the laststart pointer saved with the start of each + subexpression to point to start_memory instead of after the + following register number. This is because the subexpression + might be in a loop. + Added comments and compacted some code. + Made intervals only work if preceded by an re matching a single + character or a subexpression. + Made back references to nonexistent subexpressions illegal if + using POSIX syntax. + Made intervals work on the last preceding character of a + concatenation of characters, e.g., ab{0,} matches abbb, not abab. + Moved macro PREFETCH to outside the routine. + + (re_compile_fastmap): Added succeed_n to work analogously to + on_failure_jump if n is zero and jump_n to work analogously to + the other backward jumps. + + (re_match_2): Defined macro SET_REGS_MATCHED to set which + current subexpressions had matches within them. + Changed some comments. + Added reg_active and reg_matched_something arrays to keep track + of in which subexpressions currently have matched something. + Defined MATCHING_IN_FIRST_STRING and replaced ``dend == end_match_1'' + with it to make code easier to understand. + Fixed so can apply * and intervals to arbitrarily nested + subexpressions. (Lots of previous bugs here.) + Changed so won't match a newline if syntax bit RE_DOT_NOT_NULL is set. + Made the upcase array nonstatic so the testing file could use it also. + + (main.c): Moved the tests out to another file. + + (tests.c): Moved all the testing stuff here. + +Sat Nov 18 19:30:30 1989 Kathy Hargreaves (kathy at hayley) + + * regex.c: (re_compile_pattern): Defined RE_DUP_MAX, the maximum + number of times an interval can match a pattern. + Added macro GET_UNSIGNED_NUMBER (used to get below): + Added variables lower_bound and upper_bound for upper and lower + bounds of intervals. + Added variable num_fetches so intervals could do backtracking. + Added code to handle '{' and "\{" and intervals. + Added to comments. + + (store_jump_n): (Added) Stores a jump with a number following the + relative address (for intervals). + + (insert_jump_n): (Added) Inserts a jump_n. + + (re_match_2): Defined a macro ESTACK_PUSH_2 for the error stack; + it checks for overflow and reallocates if necessary. + + * regex.h: Added bits (RE_INTERVALS and RE_NO_BK_CURLY_BRACES) + to obscure syntax to indicate whether or not + a syntax handles intervals and recognizes either \{ and + \} or { and } as operators. Also added two syntaxes + RE_SYNTAX_POSIX_BASIC and RE_POSIX_EXTENDED and two command codes + to the enumeration regexpcode; they are succeed_n and jump_n. + +Sat Nov 18 19:30:30 1989 Kathy Hargreaves (kathy at hayley) + + * regex.c: (re_compile_pattern): Defined INIT_BUFF_SIZE to get rid + of repeated constants in code. Tested with value 1. + Renamed PATPUSH as BUFPUSH, since it pushes things onto the + buffer, not the pattern. Also made this macro extend the buffer + if it's full (so could do the following): + Took out code at top of loop that checks to see if buffer is going + to be full after 10 additions (and reallocates if necessary). + + (insert_jump): Rearranged declaration lines so comments would read + better. + + (re_match_2): Compacted exactn code and added more comments. + + (main): Defined macros TEST_MATCH and MATCH_SELF to do + testing; took out loop so could use these instead. + +Tue Oct 24 20:57:18 1989 Kathy Hargreaves (kathy at hayley) + + * regex.c (re_set_syntax): Gave argument `syntax' a type. + (store_jump, insert_jump): made them void functions. + +Local Variables: +mode: indented-text +left-margin: 8 +version-control: never +End: diff --git a/gnu/lib/libregex/INSTALL b/gnu/lib/libregex/INSTALL new file mode 100644 index 00000000000..014e0f728ad --- /dev/null +++ b/gnu/lib/libregex/INSTALL @@ -0,0 +1,117 @@ +This is a generic INSTALL file for utilities distributions. +If this package does not come with, e.g., installable documentation or +data files, please ignore the references to them below. + +To compile this package: + +1. Configure the package for your system. In the directory that this +file is in, type `./configure'. If you're using `csh' on an old +version of System V, you might need to type `sh configure' instead to +prevent `csh' from trying to execute `configure' itself. + +The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation, and +creates the Makefile(s) (one in each subdirectory of the source +directory). In some packages it creates a C header file containing +system-dependent definitions. It also creates a file `config.status' +that you can run in the future to recreate the current configuration. + +Running `configure' takes a minute or two. While it is running, it +prints some messages that tell what it is doing. If you don't want to +see the messages, run `configure' with its standard output redirected +to `/dev/null'; for example, `./configure >/dev/null'. + +To compile the package in a different directory from the one +containing the source code, you must use a version of `make' that +supports the VPATH variable, such as GNU `make'. `cd' to the directory +where you want the object files and executables to go and run +`configure'. `configure' automatically checks for the source code in +the directory that `configure' is in and in `..'. If for some reason +`configure' is not in the source code directory that you are +configuring, then it will report that it can't find the source code. +In that case, run `configure' with the option `--srcdir=DIR', where +DIR is the directory that contains the source code. + +By default, `make install' will install the package's files in +/usr/local/bin, /usr/local/lib, /usr/local/man, etc. You can specify +an installation prefix other than /usr/local by giving `configure' the +option `--prefix=PATH'. Alternately, you can do so by giving a value +for the `prefix' variable when you run `make', e.g., + make prefix=/usr/gnu + +You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If +you give `configure' the option `--exec-prefix=PATH' or set the +`make' variable `exec_prefix' to PATH, the package will use PATH as +the prefix for installing programs and libraries. Data files and +documentation will still use the regular prefix. Normally, all files +are installed using the regular prefix. + +Another `configure' option is useful mainly in `Makefile' rules for +updating `config.status' and `Makefile'. The `--no-create' option +figures out the configuration for your system and records it in +`config.status', without actually configuring the package (creating +`Makefile's and perhaps a configuration header file). Later, you can +run `./config.status' to actually configure the package. You can also +give `config.status' the `--recheck' option, which makes it re-run +`configure' with the same arguments you used before. This option is +useful if you change `configure'. + +Some packages pay attention to `--with-PACKAGE' options to `configure', +where PACKAGE is something like `gnu-libc' or `x' (for the X Window System). +The README should mention any --with- options that the package recognizes. + +`configure' ignores any other arguments that you give it. + +If your system requires unusual options for compilation or linking +that `configure' doesn't know about, you can give `configure' initial +values for some variables by setting them in the environment. In +Bourne-compatible shells, you can do that on the command line like +this: + CC='gcc -traditional' DEFS=-D_POSIX_SOURCE ./configure + +The `make' variables that you might want to override with environment +variables when running `configure' are: + +(For these variables, any value given in the environment overrides the +value that `configure' would choose:) +CC C compiler program. + Default is `cc', or `gcc' if `gcc' is in your PATH. +INSTALL Program to use to install files. + Default is `install' if you have it, `cp' otherwise. + +(For these variables, any value given in the environment is added to +the value that `configure' chooses:) +DEFS Configuration options, in the form `-Dfoo -Dbar ...' + Do not use this variable in packages that create a + configuration header file. +LIBS Libraries to link with, in the form `-lfoo -lbar ...' + +If you need to do unusual things to compile the package, we encourage +you to figure out how `configure' could check whether to do them, and +mail diffs or instructions to the address given in the README so we +can include them in the next release. + +2. Type `make' to compile the package. If you want, you can override +the `make' variables CFLAGS and LDFLAGS like this: + + make CFLAGS=-O2 LDFLAGS=-s + +3. If the package comes with self-tests and you want to run them, +type `make check'. If you're not sure whether there are any, try it; +if `make' responds with something like + make: *** No way to make target `check'. Stop. +then the package does not come with self-tests. + +4. Type `make install' to install programs, data files, and +documentation. + +5. You can remove the program binaries and object files from the +source directory by typing `make clean'. To also remove the +Makefile(s), the header file containing system-dependent definitions +(if the package uses one), and `config.status' (all the files that +`configure' created), type `make distclean'. + +The file `configure.in' is used as a template to create `configure' by +a program called `autoconf'. You will only need it if you want to +regenerate `configure' using a newer version of `autoconf'. diff --git a/gnu/lib/libregex/Makefile b/gnu/lib/libregex/Makefile new file mode 100644 index 00000000000..a7141a2f49e --- /dev/null +++ b/gnu/lib/libregex/Makefile @@ -0,0 +1,11 @@ +# $Header: /cvsroot/src/gnu/lib/libregex/Attic/Makefile,v 1.1 1993/04/08 01:11:28 cgd Exp $ + +LIB= gnuregex +CFLAGS+=-DHAVE_STRING_H=1 +SRCS= regex.c +NOMAN= noman + +afterinstall: + install -c -o root -g wheel -m 444 ${.CURDIR}/regex.h /usr/include + +.include <bsd.lib.mk> diff --git a/gnu/lib/libregex/Makefile.gnu b/gnu/lib/libregex/Makefile.gnu new file mode 100644 index 00000000000..0976aa8bdc4 --- /dev/null +++ b/gnu/lib/libregex/Makefile.gnu @@ -0,0 +1,99 @@ +# Generated automatically from Makefile.in by configure. +# Makefile for regex. +# +# Copyright (C) 1992, 1993 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +version = 0.12 + +# You can define CPPFLAGS on the command line. Aside from system-specific +# flags, you can define: +# -DREGEX_MALLOC to use malloc/realloc/free instead of alloca. +# -DDEBUG to enable the compiled pattern disassembler and execution +# tracing; code runs substantially slower. +# -DEXTRACT_MACROS to use the macros EXTRACT_* (as opposed to +# the corresponding C procedures). If not -DDEBUG, the macros +# are used. +CPPFLAGS = + +# Likewise, you can override CFLAGS to optimize, use -Wall, etc. +CFLAGS = -g + +# Ditto for LDFLAGS and LOADLIBES. +LDFLAGS = +LOADLIBES = + +srcdir = . +VPATH = . + +CC = gcc +DEFS = -DHAVE_STRING_H=1 + +SHELL = /bin/sh + +subdirs = doc test + +default all:: regex.o +.PHONY: default all + +regex.o: regex.c regex.h + $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $< + +clean mostlyclean:: + rm -f *.o + +distclean:: clean + rm -f Makefile config.status + +extraclean:: distclean + rm -f patch* *~* *\#* *.orig *.rej *.bak core a.out + +configure: configure.in + autoconf + +config.status: configure + sh configure --no-create + +Makefile: Makefile.in config.status + sh config.status + +makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' \ +DEFS='$(DEFS)' LDFLAGS='$(LDFLAGS)' LOADLIBES='$(LOADLIBES)' + +default all install \ +mostlyclean clean distclean extraclean realclean \ +TAGS check:: + for d in $(subdirs); do (cd $$d; $(MAKE) $(makeargs) $@); done +.PHONY: install mostlyclean clean distclean extraclean realclean TAGS check + +# Prevent GNU make 3 from overflowing arg limit on system V. +.NOEXPORT: + +distfiles = AUTHORS ChangeLog COPYING INSTALL NEWS README \ + *.in configure regex.c regex.h +distdir = regex-$(version) +distargs = version=$(version) distdir=../$(distdir)/$$d +dist: TAGS configure + @echo "Version numbers in: Makefile.in, ChangeLog, NEWS," + @echo " regex.c, regex.h," + @echo " and doc/xregex.texi (if modified)." + rm -rf $(distdir) + mkdir $(distdir) + ln $(distfiles) $(distdir) + for d in $(subdirs); do (cd $$d; $(MAKE) $(distargs) dist); done + tar czhf $(distdir).tar.Z $(distdir) + rm -rf $(distdir) +.PHONY: dist diff --git a/gnu/lib/libregex/Makefile.in b/gnu/lib/libregex/Makefile.in new file mode 100644 index 00000000000..836e6de0ba5 --- /dev/null +++ b/gnu/lib/libregex/Makefile.in @@ -0,0 +1,98 @@ +# Makefile for regex. +# +# Copyright (C) 1992, 1993 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +version = 0.12 + +# You can define CPPFLAGS on the command line. Aside from system-specific +# flags, you can define: +# -DREGEX_MALLOC to use malloc/realloc/free instead of alloca. +# -DDEBUG to enable the compiled pattern disassembler and execution +# tracing; code runs substantially slower. +# -DEXTRACT_MACROS to use the macros EXTRACT_* (as opposed to +# the corresponding C procedures). If not -DDEBUG, the macros +# are used. +CPPFLAGS = + +# Likewise, you can override CFLAGS to optimize, use -Wall, etc. +CFLAGS = -g + +# Ditto for LDFLAGS and LOADLIBES. +LDFLAGS = +LOADLIBES = + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +DEFS = @DEFS@ + +SHELL = /bin/sh + +subdirs = doc test + +default all:: regex.o +.PHONY: default all + +regex.o: regex.c regex.h + $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $< + +clean mostlyclean:: + rm -f *.o + +distclean:: clean + rm -f Makefile config.status + +extraclean:: distclean + rm -f patch* *~* *\#* *.orig *.rej *.bak core a.out + +configure: configure.in + autoconf + +config.status: configure + sh configure --no-create + +Makefile: Makefile.in config.status + sh config.status + +makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' \ +DEFS='$(DEFS)' LDFLAGS='$(LDFLAGS)' LOADLIBES='$(LOADLIBES)' + +default all install \ +mostlyclean clean distclean extraclean realclean \ +TAGS check:: + for d in $(subdirs); do (cd $$d; $(MAKE) $(makeargs) $@); done +.PHONY: install mostlyclean clean distclean extraclean realclean TAGS check + +# Prevent GNU make 3 from overflowing arg limit on system V. +.NOEXPORT: + +distfiles = AUTHORS ChangeLog COPYING INSTALL NEWS README \ + *.in configure regex.c regex.h +distdir = regex-$(version) +distargs = version=$(version) distdir=../$(distdir)/$$d +dist: TAGS configure + @echo "Version numbers in: Makefile.in, ChangeLog, NEWS," + @echo " regex.c, regex.h," + @echo " and doc/xregex.texi (if modified)." + rm -rf $(distdir) + mkdir $(distdir) + ln $(distfiles) $(distdir) + for d in $(subdirs); do (cd $$d; $(MAKE) $(distargs) dist); done + tar czhf $(distdir).tar.Z $(distdir) + rm -rf $(distdir) +.PHONY: dist diff --git a/gnu/lib/libregex/NEWS b/gnu/lib/libregex/NEWS new file mode 100644 index 00000000000..b3a899b4568 --- /dev/null +++ b/gnu/lib/libregex/NEWS @@ -0,0 +1,62 @@ +Version 0.12 + +* regex.c does not #define bcmp/bcopy/bzero if they already are. + +* regex.h does not redefine `const' if it is already defined, even if + __STDC__ is not defined. + +* RE_SYNTAX_ED added (same as POSIX BRE's). + +* The following bugs have been fixed, among others: + * The pattern \w+ doesn't infinite loop. + * The pattern ".+\n" is compiled correctly. + * Expressions with more than MAX_REGNUM groups are compiled correctly. + +* Patterns that end in a repetition operator (e.g., `*') match + slightly faster if no looping is actually necessary. + +Version 0.11 (17 Sep 92) + +* Back-references to nonexistent subexpressions, as in the r.e. `abc\1', + are always invalid. Previously, they could match the literal digit, + e.g., the stated r.e. might have matched `abc1'. + +* Empty subexpressions are always valid (POSIX leaves this undefined). + +* Simplified rules for ^ and $ being anchors. + +* One minor speedup (rewriting the C procedure `pop_failure_point' as a + macro again). + +* Bug fixes involving: + - Declarations in regex.h and non-ANSI compilers. + - Bracket expressions with characters between 0x80-0xff. + - Memory leak in re_match_2 on systems requiring `alloca (0)' to + free alloca'd storage. + +* Test and documentation files moved into subdirectories. + +Version 0.10 (9 Sep 92) + +* `obscure_syntax' is now called `re_default_syntax'. + +* `re_comp's return type is no longer `const', for compatibility with BSD. + +* POSIX syntaxes now include as much functionality as possible + (consistent with the standard). + +* Compilation conditionals normalized to what the rest of GNU is + migrating towards these days. + +* Bug fixes involving: + - Ranges with characters between 0x80 and 0xff, e.g., [\001-\377]. + - `re_compile_fastmap' and the sequence `.*\n'. + - Intervals with exact counts, e.g., a{5}. + +* Changed distribution to use a standard Makefile, install the info + files, use a configure script, etc. + +Version 0.9 + +* The longest match was not always chosen: `a*|ab' didn't match `aab'. + diff --git a/gnu/lib/libregex/README b/gnu/lib/libregex/README new file mode 100644 index 00000000000..918e1a03b82 --- /dev/null +++ b/gnu/lib/libregex/README @@ -0,0 +1,60 @@ +This directory contains the GNU regex library. It is compliant with +POSIX.2, except for internationalization features. + +See the file NEWS for a list of major changes in the current release. + +See the file INSTALL for compilation instructions. (The only thing +installed is the documentation; regex.c is compiled into regex.o, but +not installed anywhere.) + +The subdirectory `doc' contains a (programmers') manual for the library. +It's probably out-of-date. Improvements are welcome. + +The subdirectory `test' contains the various tests we've written. + +We know this code is not as fast as it might be. If you have specific +suggestions, profiling results, or other such useful information to +report, please do. + +Emacs 18 is not going use this revised regex (but Emacs 19 will). If +you want to try it with Emacs 18, apply the patch at the end of this +file first. + +Mail bug reports to bug-gnu-utils@prep.ai.mit.edu. + +Please include an actual regular expression that fails (and the syntax +used to compile it); without that, there's no way to reproduce the bug, +so there's no way we can fix it. Even if you include a patch, also +include the regular expression in error; otherwise, we can't know for +sure what you're trying to fix. + +Here is the patch to make this version of regex work with Emacs 18. + +*** ORIG/search.c Tue Jan 8 13:04:55 1991 +--- search.c Sun Jan 5 10:57:00 1992 +*************** +*** 25,26 **** +--- 25,28 ---- + #include "commands.h" ++ ++ #include <sys/types.h> + #include "regex.h" +*************** +*** 477,479 **** + /* really needed. */ +! && *(searchbuf.buffer) == (char) exactn /* first item is "exact match" */ + && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */ +--- 479,482 ---- + /* really needed. */ +! /* first item is "exact match" */ +! && *(searchbuf.buffer) == (char) RE_EXACTN_VALUE + && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */ +*************** +*** 1273,1275 **** + searchbuf.allocated = 100; +! searchbuf.buffer = (char *) malloc (searchbuf.allocated); + searchbuf.fastmap = search_fastmap; +--- 1276,1278 ---- + searchbuf.allocated = 100; +! searchbuf.buffer = (unsigned char *) malloc (searchbuf.allocated); + searchbuf.fastmap = search_fastmap; diff --git a/gnu/lib/libregex/config.status b/gnu/lib/libregex/config.status new file mode 100644 index 00000000000..1b276aacf34 --- /dev/null +++ b/gnu/lib/libregex/config.status @@ -0,0 +1,59 @@ +#!/bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host sun-lamp.cs.berkeley.edu: +# +# configure + +for arg +do + case "$arg" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + exec /bin/sh configure ;; + *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;; + esac +done + +trap 'rm -f Makefile doc/Makefile test/Makefile; exit 1' 1 3 15 +CC='gcc' +INSTALL='/usr/bin/install -c' +INSTALL_PROGRAM='$(INSTALL)' +INSTALL_DATA='$(INSTALL) -m 644' +CPP='${CC-cc} -E' +ALLOCA='' +LIBS='' +srcdir='.' +DEFS=' -DHAVE_STRING_H=1' +prefix='/usr' +exec_prefix='${prefix}' +prsub='s%^prefix\([ ]*\)=\([ ]*\).*$%prefix\1=\2/usr% +s%^exec_prefix\([ ]*\)=\([ ]*\).*$%exec_prefix\1=\2${prefix}%' + +top_srcdir=$srcdir +for file in .. Makefile doc/Makefile test/Makefile; do if [ "x$file" != "x.." ]; then + srcdir=$top_srcdir + # Remove last slash and all that follows it. Not all systems have dirname. + dir=`echo $file|sed 's%/[^/][^/]*$%%'` + if test "$dir" != "$file"; then + test "$top_srcdir" != . && srcdir=$top_srcdir/$dir + test ! -d $dir && mkdir $dir + fi + echo creating $file + rm -f $file + echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file + sed -e " +$prsub +s%@CC@%$CC%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g +s%@LIBS@%$LIBS%g +s%@srcdir@%$srcdir%g +s%@DEFS@%$DEFS% +" $top_srcdir/${file}.in >> $file +fi; done + +exit 0 diff --git a/gnu/lib/libregex/configure b/gnu/lib/libregex/configure new file mode 100644 index 00000000000..29c5b803c32 --- /dev/null +++ b/gnu/lib/libregex/configure @@ -0,0 +1,462 @@ +#!/bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf. +# Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# Usage: configure [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] [--no-create] +# [--prefix=PREFIX] [--exec-prefix=PREFIX] [--with-PACKAGE] [TARGET] +# Ignores all args except --srcdir, --prefix, --exec-prefix, --no-create, and +# --with-PACKAGE unless this script has special code to handle it. + + +for arg +do + # Handle --exec-prefix with a space before the argument. + if test x$next_exec_prefix = xyes; then exec_prefix=$arg; next_exec_prefix= + # Handle --host with a space before the argument. + elif test x$next_host = xyes; then next_host= + # Handle --prefix with a space before the argument. + elif test x$next_prefix = xyes; then prefix=$arg; next_prefix= + # Handle --srcdir with a space before the argument. + elif test x$next_srcdir = xyes; then srcdir=$arg; next_srcdir= + else + case $arg in + # For backward compatibility, also recognize exact --exec_prefix. + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* | --exec=* | --exe=* | --ex=* | --e=*) + exec_prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;; + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- | --exec | --exe | --ex | --e) + next_exec_prefix=yes ;; + + -gas | --gas | --ga | --g) ;; + + -host=* | --host=* | --hos=* | --ho=* | --h=*) ;; + -host | --host | --hos | --ho | --h) + next_host=yes ;; + + -nfp | --nfp | --nf) ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre | --no-cr | --no-c | --no- | --no) + no_create=1 ;; + + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + next_prefix=yes ;; + + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*) + srcdir=`echo $arg | sed 's/[-a-z_]*=//'` ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s) + next_srcdir=yes ;; + + -with-* | --with-*) + package=`echo $arg|sed 's/-*with-//'` + # Delete all the valid chars; see if any are left. + if test -n "`echo $package|sed 's/[-a-zA-Z0-9_]*//g'`"; then + echo "configure: $package: invalid package name" >&2; exit 1 + fi + eval "with_`echo $package|sed s/-/_/g`=1" ;; + + *) ;; + esac + fi +done + +trap 'rm -f conftest* core; exit 1' 1 3 15 + +rm -f conftest* +compile='${CC-cc} $CFLAGS $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1' + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +unique_file=regex.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + srcdirdefaulted=yes + # Try the directory containing this script, then `..'. + prog=$0 + confdir=`echo $prog|sed 's%/[^/][^/]*$%%'` + test "X$confdir" = "X$prog" && confdir=. + srcdir=$confdir + if test ! -r $srcdir/$unique_file; then + srcdir=.. + fi +fi +if test ! -r $srcdir/$unique_file; then + if test x$srcdirdefaulted = xyes; then + echo "configure: Can not find sources in \`${confdir}' or \`..'." 1>&2 + else + echo "configure: Can not find sources in \`${srcdir}'." 1>&2 + fi + exit 1 +fi +# Preserve a srcdir of `.' to avoid automounter screwups with pwd. +# But we can't avoid them for `..', to make subdirectories work. +case $srcdir in + .|/*|~*) ;; + *) srcdir=`cd $srcdir; pwd` ;; # Make relative path absolute. +esac + + +if test -z "$CC"; then + echo checking for gcc + saveifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/gcc; then + CC="gcc" + break + fi + done + IFS="$saveifs" +fi +test -z "$CC" && CC="cc" + +# Find out if we are using GNU C, under whatever name. +cat > conftest.c <<EOF +#ifdef __GNUC__ + yes +#endif +EOF +${CC-cc} -E conftest.c > conftest.out 2>&1 +if egrep yes conftest.out >/dev/null 2>&1; then + GCC=1 # For later tests. +fi +rm -f conftest* + +# Make sure to not get the incompatible SysV /etc/install and +# /usr/sbin/install, which might be in PATH before a BSD-like install, +# or the SunOS /usr/etc/install directory, or the AIX /bin/install, +# or the AFS install, which mishandles nonexistent args. (Sigh.) +if test -z "$INSTALL"; then + echo checking for install + saveifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + case $dir in + /etc|/usr/sbin|/usr/etc|/usr/afsws/bin) ;; + *) + if test -f $dir/install; then + if grep dspmsg $dir/install >/dev/null 2>&1; then + : # AIX + else + INSTALL="$dir/install -c" + INSTALL_PROGRAM='$(INSTALL)' + INSTALL_DATA='$(INSTALL) -m 644' + break + fi + fi + ;; + esac + done + IFS="$saveifs" +fi +INSTALL=${INSTALL-cp} +INSTALL_PROGRAM=${INSTALL_PROGRAM-'$(INSTALL)'} +INSTALL_DATA=${INSTALL_DATA-'$(INSTALL)'} + + +echo checking for AIX +echo checking how to run the C preprocessor +if test -z "$CPP"; then + CPP='${CC-cc} -E' + cat > conftest.c <<EOF +#include <stdio.h> +EOF +err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` +if test -z "$err"; then + : +else + CPP=/lib/cpp +fi +rm -f conftest* +fi + +cat > conftest.c <<EOF +#ifdef _AIX + yes +#endif + +EOF +eval "$CPP $DEFS conftest.c > conftest.out 2>&1" +if egrep "yes" conftest.out >/dev/null 2>&1; then + DEFS="$DEFS -D_ALL_SOURCE=1" +fi +rm -f conftest* + + +echo checking for DYNIX/ptx libseq +cat > conftest.c <<EOF +#if defined(_SEQUENT_) + yes +#endif + +EOF +eval "$CPP $DEFS conftest.c > conftest.out 2>&1" +if egrep "yes" conftest.out >/dev/null 2>&1; then + SEQUENT=1 +fi +rm -f conftest* + +test -n "$SEQUENT" && test -f /usr/lib/libseq.a && + LIBS="$LIBS -lseq" + +echo checking for POSIXized ISC +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + ISC=1 # If later tests want to check for ISC. + DEFS="$DEFS -D_POSIX_SOURCE=1" + if test -n "$GCC"; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +fi + +echo checking for minix/config.h +cat > conftest.c <<EOF +#include <minix/config.h> +EOF +err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` +if test -z "$err"; then + MINIX=1 +fi +rm -f conftest* + +# The Minix shell can't assign to the same variable on the same line! +if test -n "$MINIX"; then + DEFS="$DEFS -D_POSIX_SOURCE=1" + DEFS="$DEFS -D_POSIX_1_SOURCE=2" + DEFS="$DEFS -D_MINIX=1" +fi + + +echo checking for ANSI C header files +cat > conftest.c <<EOF +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` +if test -z "$err"; then + # SunOS string.h does not declare mem*, contrary to ANSI. +echo '#include <string.h>' > conftest.c +eval "$CPP $DEFS conftest.c > conftest.out 2>&1" +if egrep "memchr" conftest.out >/dev/null 2>&1; then + # SGI's /bin/cc from Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +cat > conftest.c <<EOF +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e,f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +eval $compile +if test -s conftest && (./conftest; exit) 2>/dev/null; then + DEFS="$DEFS -DSTDC_HEADERS=1" +fi +rm -f conftest* +fi +rm -f conftest* + +fi +rm -f conftest* + +for hdr in string.h +do +trhdr=HAVE_`echo $hdr | tr '[a-z]./' '[A-Z]__'` +echo checking for ${hdr} +cat > conftest.c <<EOF +#include <${hdr}> +EOF +err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` +if test -z "$err"; then + DEFS="$DEFS -D${trhdr}=1" +fi +rm -f conftest* +done + + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo checking for working alloca.h +cat > conftest.c <<EOF +#include <alloca.h> +main() { exit(0); } +t() { char *p = alloca(2 * sizeof(int)); } +EOF +if eval $compile; then + DEFS="$DEFS -DHAVE_ALLOCA_H=1" +fi +rm -f conftest* + +decl="#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#if HAVE_ALLOCA_H +#include <alloca.h> +#else +#ifdef _AIX + #pragma alloca +#else +char *alloca (); +#endif +#endif +#endif +" +echo checking for alloca +cat > conftest.c <<EOF +$decl +main() { exit(0); } +t() { char *p = (char *) alloca(1); } +EOF +if eval $compile; then + : +else + alloca_missing=1 +fi +rm -f conftest* + +if test -n "$alloca_missing"; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.o +fi + +prog='/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *p; +char **p2; +/* HPUX 7.0 cc rejects these. */ +++p; +p2 = (char const* const*) p;' +echo checking for working const +cat > conftest.c <<EOF + +main() { exit(0); } +t() { $prog } +EOF +if eval $compile; then + : +else + DEFS="$DEFS -Dconst=" +fi +rm -f conftest* + + +if test -z "$prefix" +then + echo checking for gcc to derive installation directory prefix + saveifs="$IFS"; IFS="$IFS:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test $dir != . && test -f $dir/gcc; then + # Not all systems have dirname. + prefix=`echo $dir|sed 's%/[^/][^/]*$%%'` + break + fi + done + IFS="$saveifs" +fi + + +if test -n "$prefix"; then + test -z "$exec_prefix" && exec_prefix='${prefix}' + prsub="s%^prefix\\([ ]*\\)=\\([ ]*\\).*$%prefix\\1=\\2$prefix%" +fi +if test -n "$exec_prefix"; then + prsub="$prsub +s%^exec_prefix\\([ ]*\\)=\\([ ]*\\).*$%\ +exec_prefix\\1=\\2$exec_prefix%" +fi + +trap 'rm -f config.status; exit 1' 1 3 15 +echo creating config.status +rm -f config.status +cat > config.status <<EOF +#!/bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null`: +# +# $0 $* + +for arg +do + case "\$arg" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + exec /bin/sh $0 $* ;; + *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;; + esac +done + +trap 'rm -f Makefile doc/Makefile test/Makefile; exit 1' 1 3 15 +CC='$CC' +INSTALL='$INSTALL' +INSTALL_PROGRAM='$INSTALL_PROGRAM' +INSTALL_DATA='$INSTALL_DATA' +CPP='$CPP' +ALLOCA='$ALLOCA' +LIBS='$LIBS' +srcdir='$srcdir' +DEFS='$DEFS' +prefix='$prefix' +exec_prefix='$exec_prefix' +prsub='$prsub' +EOF +cat >> config.status <<\EOF + +top_srcdir=$srcdir +for file in .. Makefile doc/Makefile test/Makefile; do if [ "x$file" != "x.." ]; then + srcdir=$top_srcdir + # Remove last slash and all that follows it. Not all systems have dirname. + dir=`echo $file|sed 's%/[^/][^/]*$%%'` + if test "$dir" != "$file"; then + test "$top_srcdir" != . && srcdir=$top_srcdir/$dir + test ! -d $dir && mkdir $dir + fi + echo creating $file + rm -f $file + echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file + sed -e " +$prsub +s%@CC@%$CC%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g +s%@LIBS@%$LIBS%g +s%@srcdir@%$srcdir%g +s%@DEFS@%$DEFS% +" $top_srcdir/${file}.in >> $file +fi; done + +exit 0 +EOF +chmod +x config.status +test -n "$no_create" || ./config.status + diff --git a/gnu/lib/libregex/configure.in b/gnu/lib/libregex/configure.in new file mode 100644 index 00000000000..f0fc7802509 --- /dev/null +++ b/gnu/lib/libregex/configure.in @@ -0,0 +1,23 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(regex.c) + +AC_PROG_CC +AC_PROG_INSTALL + +dnl I'm not sure if AC_AIX and AC_DYNIX_SEQ are really necessary. The +dnl Autoconf documentation isn't specific about which BSD functions they +dnl provide. +AC_AIX +AC_DYNIX_SEQ +AC_ISC_POSIX +AC_MINIX + +AC_STDC_HEADERS +AC_HAVE_HEADERS(string.h) + +AC_ALLOCA +AC_CONST + +AC_PREFIX(gcc) + +AC_OUTPUT(Makefile doc/Makefile test/Makefile) diff --git a/gnu/lib/libregex/regex.c b/gnu/lib/libregex/regex.c new file mode 100644 index 00000000000..8169880d7e4 --- /dev/null +++ b/gnu/lib/libregex/regex.c @@ -0,0 +1,4948 @@ +/* Extended regular expression matching and search library, + version 0.12. + (Implements POSIX draft P10003.2/D11.2, except for + internationalization features.) + + Copyright (C) 1993 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* AIX requires this to be the first thing in the file. */ +#if defined (_AIX) && !defined (REGEX_MALLOC) + #pragma alloca +#endif + +#define _GNU_SOURCE + +/* We need this for `regex.h', and perhaps for the Emacs include files. */ +#include <sys/types.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* The `emacs' switch turns on certain matching commands + that make sense only in Emacs. */ +#ifdef emacs + +#include "lisp.h" +#include "buffer.h" +#include "syntax.h" + +/* Emacs uses `NULL' as a predicate. */ +#undef NULL + +#else /* not emacs */ + +/* We used to test for `BSTRING' here, but only GCC and Emacs define + `BSTRING', as far as I know, and neither of them use this code. */ +#if HAVE_STRING_H || STDC_HEADERS +#include <string.h> +#ifndef bcmp +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#endif +#ifndef bcopy +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#endif +#ifndef bzero +#define bzero(s, n) memset ((s), 0, (n)) +#endif +#else +#include <strings.h> +#endif + +#ifdef STDC_HEADERS +#include <stdlib.h> +#else +char *malloc (); +char *realloc (); +#endif + + +/* Define the syntax stuff for \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +#ifndef Sword +#define Sword 1 +#endif + +#ifdef SYNTAX_TABLE + +extern char *re_syntax_table; + +#else /* not SYNTAX_TABLE */ + +/* How many characters in the character set. */ +#define CHAR_SET_SIZE 256 + +static char re_syntax_table[CHAR_SET_SIZE]; + +static void +init_syntax_once () +{ + register int c; + static int done = 0; + + if (done) + return; + + bzero (re_syntax_table, sizeof re_syntax_table); + + for (c = 'a'; c <= 'z'; c++) + re_syntax_table[c] = Sword; + + for (c = 'A'; c <= 'Z'; c++) + re_syntax_table[c] = Sword; + + for (c = '0'; c <= '9'; c++) + re_syntax_table[c] = Sword; + + re_syntax_table['_'] = Sword; + + done = 1; +} + +#endif /* not SYNTAX_TABLE */ + +#define SYNTAX(c) re_syntax_table[c] + +#endif /* not emacs */ + +/* Get the interface, including the syntax bits. */ +#include "regex.h" + +/* isalpha etc. are used for the character classes. */ +#include <ctype.h> + +#ifndef isascii +#define isascii(c) 1 +#endif + +#ifdef isblank +#define ISBLANK(c) (isascii (c) && isblank (c)) +#else +#define ISBLANK(c) ((c) == ' ' || (c) == '\t') +#endif +#ifdef isgraph +#define ISGRAPH(c) (isascii (c) && isgraph (c)) +#else +#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c)) +#endif + +#define ISPRINT(c) (isascii (c) && isprint (c)) +#define ISDIGIT(c) (isascii (c) && isdigit (c)) +#define ISALNUM(c) (isascii (c) && isalnum (c)) +#define ISALPHA(c) (isascii (c) && isalpha (c)) +#define ISCNTRL(c) (isascii (c) && iscntrl (c)) +#define ISLOWER(c) (isascii (c) && islower (c)) +#define ISPUNCT(c) (isascii (c) && ispunct (c)) +#define ISSPACE(c) (isascii (c) && isspace (c)) +#define ISUPPER(c) (isascii (c) && isupper (c)) +#define ISXDIGIT(c) (isascii (c) && isxdigit (c)) + +#ifndef NULL +#define NULL 0 +#endif + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +#endif + +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we + use `alloca' instead of `malloc'. This is because using malloc in + re_search* or re_match* could cause memory leaks when C-g is used in + Emacs; also, malloc is slower and causes storage fragmentation. On + the other hand, malloc is more portable, and easier to debug. + + Because we sometimes use alloca, some routines have to be macros, + not functions -- `alloca'-allocated space disappears at the end of the + function it is called in. */ + +#ifdef REGEX_MALLOC + +#define REGEX_ALLOCATE malloc +#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) + +#else /* not REGEX_MALLOC */ + +/* Emacs already defines alloca, sometimes. */ +#ifndef alloca + +/* Make alloca work the best possible way. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if HAVE_ALLOCA_H +#include <alloca.h> +#else /* not __GNUC__ or HAVE_ALLOCA_H */ +#ifndef _AIX /* Already did AIX, up at the top. */ +char *alloca (); +#endif /* not _AIX */ +#endif /* not HAVE_ALLOCA_H */ +#endif /* not __GNUC__ */ + +#endif /* not alloca */ + +#define REGEX_ALLOCATE alloca + +/* Assumes a `char *destination' variable. */ +#define REGEX_REALLOCATE(source, osize, nsize) \ + (destination = (char *) alloca (nsize), \ + bcopy (source, destination, osize), \ + destination) + +#endif /* not REGEX_MALLOC */ + + +/* True if `size1' is non-NULL and PTR is pointing anywhere inside + `string1' or just past its end. This works if PTR is NULL, which is + a good thing. */ +#define FIRST_STRING_P(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* (Re)Allocate N items of type T using malloc, or fail. */ +#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + +#define BYTEWIDTH 8 /* In bits. */ + +#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef char boolean; +#define false 0 +#define true 1 + +/* These are the command codes that appear in compiled regular + expressions. Some opcodes are followed by argument bytes. A + command code can specify any interpretation whatsoever for its + arguments. Zero bytes may appear in the compiled regular expression. + + The value of `exactn' is needed in search.c (search_buffer) in Emacs. + So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of + `exactn' we use here must also be 1. */ + +typedef enum +{ + no_op = 0, + + /* Followed by one byte giving n, then by n literal bytes. */ + exactn = 1, + + /* Matches any (more or less) character. */ + anychar, + + /* Matches any one char belonging to specified set. First + following byte is number of bitmap bytes. Then come bytes + for a bitmap saying which chars are in. Bits in each byte + are ordered low-bit-first. A character is in the set if its + bit is 1. A character too large to have a bit in the map is + automatically not in the set. */ + charset, + + /* Same parameters as charset, but match any character that is + not one of those specified. */ + charset_not, + + /* Start remembering the text that is matched, for storing in a + register. Followed by one byte with the register number, in + the range 0 to one less than the pattern buffer's re_nsub + field. Then followed by one byte with the number of groups + inner to this one. (This last has to be part of the + start_memory only because we need it in the on_failure_jump + of re_match_2.) */ + start_memory, + + /* Stop remembering the text that is matched and store it in a + memory register. Followed by one byte with the register + number, in the range 0 to one less than `re_nsub' in the + pattern buffer, and one byte with the number of inner groups, + just like `start_memory'. (We need the number of inner + groups here because we don't have any easy way of finding the + corresponding start_memory when we're at a stop_memory.) */ + stop_memory, + + /* Match a duplicate of something remembered. Followed by one + byte containing the register number. */ + duplicate, + + /* Fail unless at beginning of line. */ + begline, + + /* Fail unless at end of line. */ + endline, + + /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + begbuf, + + /* Analogously, for end of buffer/string. */ + endbuf, + + /* Followed by two byte relative address to which to jump. */ + jump, + + /* Same as jump, but marks the end of an alternative. */ + jump_past_alt, + + /* Followed by two-byte relative address of place to resume at + in case of failure. */ + on_failure_jump, + + /* Like on_failure_jump, but pushes a placeholder instead of the + current string position when executed. */ + on_failure_keep_string_jump, + + /* Throw away latest failure point and then jump to following + two-byte relative address. */ + pop_failure_jump, + + /* Change to pop_failure_jump if know won't have to backtrack to + match; otherwise change to jump. This is used to jump + back to the beginning of a repeat. If what follows this jump + clearly won't match what the repeat does, such that we can be + sure that there is no use backtracking out of repetitions + already matched, then we change it to a pop_failure_jump. + Followed by two-byte address. */ + maybe_pop_jump, + + /* Jump to following two-byte address, and push a dummy failure + point. This failure point will be thrown away if an attempt + is made to use it for a failure. A `+' construct makes this + before the first repeat. Also used as an intermediary kind + of jump when compiling an alternative. */ + dummy_failure_jump, + + /* Push a dummy failure point and continue. Used at the end of + alternatives. */ + push_dummy_failure, + + /* Followed by two-byte relative address and two-byte number n. + After matching N times, jump to the address upon failure. */ + succeed_n, + + /* Followed by two-byte relative address, and two-byte number n. + Jump to the address N times, then fail. */ + jump_n, + + /* Set the following two-byte relative address to the + subsequent two-byte number. The address *includes* the two + bytes of number. */ + set_number_at, + + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ + +#ifdef emacs + ,before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ + + /* Matches any character whose syntax is specified. Followed by + a byte which contains a syntax code, e.g., Sword. */ + syntaxspec, + + /* Matches any character whose syntax is not that specified. */ + notsyntaxspec +#endif /* emacs */ +} re_opcode_t; + +/* Common operations on the compiled pattern. */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ + +#define STORE_NUMBER(destination, number) \ + do { \ + (destination)[0] = (number) & 0377; \ + (destination)[1] = (number) >> 8; \ + } while (0) + +/* Same as STORE_NUMBER, except increment DESTINATION to + the byte after where the number is stored. Therefore, DESTINATION + must be an lvalue. */ + +#define STORE_NUMBER_AND_INCR(destination, number) \ + do { \ + STORE_NUMBER (destination, number); \ + (destination) += 2; \ + } while (0) + +/* Put into DESTINATION a number stored in two contiguous bytes starting + at SOURCE. */ + +#define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + } while (0) + +#ifdef DEBUG +static void +extract_number (dest, source) + int *dest; + unsigned char *source; +{ + int temp = SIGN_EXTEND_CHAR (*(source + 1)); + *dest = *source & 0377; + *dest += temp << 8; +} + +#ifndef EXTRACT_MACROS /* To debug the macros. */ +#undef EXTRACT_NUMBER +#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. + SOURCE must be an lvalue. */ + +#define EXTRACT_NUMBER_AND_INCR(destination, source) \ + do { \ + EXTRACT_NUMBER (destination, source); \ + (source) += 2; \ + } while (0) + +#ifdef DEBUG +static void +extract_number_and_incr (destination, source) + int *destination; + unsigned char **source; +{ + extract_number (destination, *source); + *source += 2; +} + +#ifndef EXTRACT_MACROS +#undef EXTRACT_NUMBER_AND_INCR +#define EXTRACT_NUMBER_AND_INCR(dest, src) \ + extract_number_and_incr (&dest, &src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* If DEBUG is defined, Regex prints many voluminous messages about what + it is doing (if the variable `debug' is nonzero). If linked with the + main program in `iregex.c', you can enter patterns and strings + interactively. And if linked with the main program in `main.c' and + the other test files, you can run the already-written tests. */ + +#ifdef DEBUG + +/* We use standard I/O for debugging. */ +#include <stdio.h> + +/* It is useful to test things that ``must'' be true when debugging. */ +#include <assert.h> + +static int debug = 0; + +#define DEBUG_STATEMENT(e) e +#define DEBUG_PRINT1(x) if (debug) printf (x) +#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) print_partial_compiled_pattern (s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) print_double_string (w, s1, sz1, s2, sz2) + + +extern void printchar (); + +/* Print the fastmap in human-readable form. */ + +void +print_fastmap (fastmap) + char *fastmap; +{ + unsigned was_a_range = 0; + unsigned i = 0; + + while (i < (1 << BYTEWIDTH)) + { + if (fastmap[i++]) + { + was_a_range = 0; + printchar (i - 1); + while (i < (1 << BYTEWIDTH) && fastmap[i]) + { + was_a_range = 1; + i++; + } + if (was_a_range) + { + printf ("-"); + printchar (i - 1); + } + } + } + putchar ('\n'); +} + + +/* Print a compiled pattern string in human-readable form, starting at + the START pointer into it and ending just before the pointer END. */ + +void +print_partial_compiled_pattern (start, end) + unsigned char *start; + unsigned char *end; +{ + int mcnt, mcnt2; + unsigned char *p = start; + unsigned char *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { + switch ((re_opcode_t) *p++) + { + case no_op: + printf ("/no_op"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar ('/'); + printchar (*p++); + } + while (--mcnt); + break; + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d/%d", mcnt, *p++); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d/%d", mcnt, *p++); + break; + + case duplicate: + printf ("/duplicate/%d", *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { + register int c; + + printf ("/charset%s", + (re_opcode_t) *(p - 1) == charset_not ? "_not" : ""); + + assert (p + *p < pend); + + for (c = 0; c < *p; c++) + { + unsigned bit; + unsigned char map_byte = p[1 + c]; + + putchar ('/'); + + for (bit = 0; bit < BYTEWIDTH; bit++) + if (map_byte & (1 << bit)) + printchar (c * BYTEWIDTH + bit); + } + p += 1 + *p; + break; + } + + case begline: + printf ("/begline"); + break; + + case endline: + printf ("/endline"); + break; + + case on_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_jump/0/%d", mcnt); + break; + + case on_failure_keep_string_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_keep_string_jump/0/%d", mcnt); + break; + + case dummy_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/dummy_failure_jump/0/%d", mcnt); + break; + + case push_dummy_failure: + printf ("/push_dummy_failure"); + break; + + case maybe_pop_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/maybe_pop_jump/0/%d", mcnt); + break; + + case pop_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/pop_failure_jump/0/%d", mcnt); + break; + + case jump_past_alt: + extract_number_and_incr (&mcnt, &p); + printf ("/jump_past_alt/0/%d", mcnt); + break; + + case jump: + extract_number_and_incr (&mcnt, &p); + printf ("/jump/0/%d", mcnt); + break; + + case succeed_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2); + break; + + case jump_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2); + break; + + case set_number_at: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2); + break; + + case wordbound: + printf ("/wordbound"); + break; + + case notwordbound: + printf ("/notwordbound"); + break; + + case wordbeg: + printf ("/wordbeg"); + break; + + case wordend: + printf ("/wordend"); + +#ifdef emacs + case before_dot: + printf ("/before_dot"); + break; + + case at_dot: + printf ("/at_dot"); + break; + + case after_dot: + printf ("/after_dot"); + break; + + case syntaxspec: + printf ("/syntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; + + case notsyntaxspec: + printf ("/notsyntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; +#endif /* emacs */ + + case wordchar: + printf ("/wordchar"); + break; + + case notwordchar: + printf ("/notwordchar"); + break; + + case begbuf: + printf ("/begbuf"); + break; + + case endbuf: + printf ("/endbuf"); + break; + + default: + printf ("?%d", *(p-1)); + } + } + printf ("/\n"); +} + + +void +print_compiled_pattern (bufp) + struct re_pattern_buffer *bufp; +{ + unsigned char *buffer = bufp->buffer; + + print_partial_compiled_pattern (buffer, buffer + bufp->used); + printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated); + + if (bufp->fastmap_accurate && bufp->fastmap) + { + printf ("fastmap: "); + print_fastmap (bufp->fastmap); + } + + printf ("re_nsub: %d\t", bufp->re_nsub); + printf ("regs_alloc: %d\t", bufp->regs_allocated); + printf ("can_be_null: %d\t", bufp->can_be_null); + printf ("newline_anchor: %d\n", bufp->newline_anchor); + printf ("no_sub: %d\t", bufp->no_sub); + printf ("not_bol: %d\t", bufp->not_bol); + printf ("not_eol: %d\t", bufp->not_eol); + printf ("syntax: %d\n", bufp->syntax); + /* Perhaps we should print the translate table? */ +} + + +void +print_double_string (where, string1, size1, string2, size2) + const char *where; + const char *string1; + const char *string2; + int size1; + int size2; +{ + unsigned this_char; + + if (where == NULL) + printf ("(null)"); + else + { + if (FIRST_STRING_P (where)) + { + for (this_char = where - string1; this_char < size1; this_char++) + printchar (string1[this_char]); + + where = string2; + } + + for (this_char = where - string2; this_char < size2; this_char++) + printchar (string2[this_char]); + } +} + +#else /* not DEBUG */ + +#undef assert +#define assert(e) + +#define DEBUG_STATEMENT(e) +#define DEBUG_PRINT1(x) +#define DEBUG_PRINT2(x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) + +#endif /* not DEBUG */ + +/* 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. */ +reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; + + +/* 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; +} + +/* 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. */ + +static const char *re_error_msg[] = + { NULL, /* REG_NOERROR */ + "No match", /* REG_NOMATCH */ + "Invalid regular expression", /* REG_BADPAT */ + "Invalid collation character", /* REG_ECOLLATE */ + "Invalid character class name", /* REG_ECTYPE */ + "Trailing backslash", /* REG_EESCAPE */ + "Invalid back reference", /* REG_ESUBREG */ + "Unmatched [ or [^", /* REG_EBRACK */ + "Unmatched ( or \\(", /* REG_EPAREN */ + "Unmatched \\{", /* REG_EBRACE */ + "Invalid content of \\{\\}", /* REG_BADBR */ + "Invalid range end", /* REG_ERANGE */ + "Memory exhausted", /* REG_ESPACE */ + "Invalid preceding regular expression", /* REG_BADRPT */ + "Premature end of regular expression", /* REG_EEND */ + "Regular expression too big", /* REG_ESIZE */ + "Unmatched ) or \\)", /* REG_ERPAREN */ + }; + +/* Subroutine declarations and macros for regex_compile. */ + +static void store_op1 (), store_op2 (); +static void insert_op1 (), insert_op2 (); +static boolean at_begline_loc_p (), at_endline_loc_p (); +static boolean group_in_compile_stack (); +static reg_errcode_t compile_range (); + +/* Fetch the next character in the uncompiled pattern---translating it + if necessary. Also cast from a signed character in the constant + string passed to us by the user to an unsigned char that we can use + as an array index (in, e.g., `translate'). */ +#define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + if (translate) c = translate[c]; \ + } while (0) + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +#define PATFETCH_RAW(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + } while (0) + +/* Go backwards one character in the pattern. */ +#define PATUNFETCH p-- + + +/* If `translate' is non-null, return translate[D], else just D. We + cast the subscript to translate because some data is declared as + `char *', to avoid warnings when a string constant is passed. But + when we use a character as a subscript we must make it unsigned. */ +#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) + + +/* Macros for outputting the compiled pattern into `buffer'. */ + +/* If the buffer isn't allocated when it comes in, use this. */ +#define INIT_BUF_SIZE 32 + +/* Make sure we have at least N more bytes of space in buffer. */ +#define GET_BUFFER_SPACE(n) \ + while (b - bufp->buffer + (n) > bufp->allocated) \ + EXTEND_BUFFER () + +/* Make sure we have one more byte of buffer space and then add C to it. */ +#define BUF_PUSH(c) \ + do { \ + GET_BUFFER_SPACE (1); \ + *b++ = (unsigned char) (c); \ + } while (0) + + +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ +#define BUF_PUSH_2(c1, c2) \ + do { \ + GET_BUFFER_SPACE (2); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + } while (0) + + +/* As with BUF_PUSH_2, except for three bytes. */ +#define BUF_PUSH_3(c1, c2, c3) \ + do { \ + GET_BUFFER_SPACE (3); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + *b++ = (unsigned char) (c3); \ + } while (0) + + +/* Store a jump with opcode OP at LOC to location TO. We store a + relative address offset by the three bytes the jump itself occupies. */ +#define STORE_JUMP(op, loc, to) \ + store_op1 (op, loc, (to) - (loc) - 3) + +/* Likewise, for a two-argument jump. */ +#define STORE_JUMP2(op, loc, to, arg) \ + store_op2 (op, loc, (to) - (loc) - 3, arg) + +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP(op, loc, to) \ + insert_op1 (op, loc, (to) - (loc) - 3, b) + +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP2(op, loc, to, arg) \ + insert_op2 (op, loc, (to) - (loc) - 3, arg, b) + + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +#define MAX_BUF_SIZE (1L << 16) + + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +#define EXTEND_BUFFER() \ + do { \ + unsigned char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ + if (bufp->buffer == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_alt_jump) \ + fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ + } while (0) + + +/* Since we have one byte reserved for the register number argument to + {start,stop}_memory, the maximum number of groups we can report + things about is what fits in that byte. */ +#define MAX_REGNUM 255 + +/* But patterns can have more than `MAX_REGNUM' registers. We just + ignore the excess. */ +typedef unsigned regnum_t; + + +/* Macros for the compile stack. */ + +/* Since offsets can go either forwards or backwards, this type needs to + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ +typedef int pattern_offset_t; + +typedef struct +{ + pattern_offset_t begalt_offset; + pattern_offset_t fixup_alt_jump; + pattern_offset_t inner_group_offset; + pattern_offset_t laststart_offset; + regnum_t regnum; +} compile_stack_elt_t; + + +typedef struct +{ + compile_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} compile_stack_type; + + +#define INIT_COMPILE_STACK_SIZE 32 + +#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) + +/* The next available element. */ +#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) + + +/* Set the bit for character C in a list. */ +#define SET_LIST_BIT(c) \ + (b[((unsigned char) (c)) / BYTEWIDTH] \ + |= 1 << (((unsigned char) c) % BYTEWIDTH)) + + +/* Get the next unsigned number in the uncompiled pattern. */ +#define GET_UNSIGNED_NUMBER(num) \ + { if (p != pend) \ + { \ + PATFETCH (c); \ + while (ISDIGIT (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ + } + +#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +#define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) + +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. + Returns one of error codes defined in `regex.h', or zero for success. + + Assumes the `allocated' (and perhaps `buffer') and `translate' + fields are set in BUFP on entry. + + If it succeeds, results are put in BUFP (if it returns an error, the + contents of BUFP are undefined): + `buffer' is the compiled pattern; + `syntax' is set to SYNTAX; + `used' is set to the length of the compiled pattern; + `fastmap_accurate' is zero; + `re_nsub' is the number of subexpressions in PATTERN; + `not_bol' and `not_eol' are zero; + + The `fastmap' and `newline_anchor' fields are neither + examined nor set. */ + +static reg_errcode_t +regex_compile (pattern, size, syntax, bufp) + const char *pattern; + int size; + reg_syntax_t syntax; + struct re_pattern_buffer *bufp; +{ + /* We fetch characters from PATTERN here. Even though PATTERN is + `char *' (i.e., signed), we declare these variables as unsigned, so + they can be reliably used as array indices. */ + register unsigned char c, c1; + + /* A random tempory spot in PATTERN. */ + const char *p1; + + /* Points to the end of the buffer, where we should append. */ + register unsigned char *b; + + /* Keeps track of unclosed groups. */ + compile_stack_type compile_stack; + + /* Points to the current (ending) position in the pattern. */ + const char *p = pattern; + const char *pend = pattern + size; + + /* How to translate the characters in the pattern. */ + char *translate = bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell if a new exact-match + character can be added to that command or if the character requires + a new `exactn' command. */ + unsigned char *pending_exact = 0; + + /* Address of start of the most recently finished expression. + This tells, e.g., postfix * where to find the start of its + operand. Reset at the beginning of groups and alternatives. */ + unsigned char *laststart = 0; + + /* Address of beginning of regexp, or inside of last group. */ + unsigned char *begalt; + + /* Place in the uncompiled pattern (i.e., the {) to + which to go back if the interval is invalid. */ + const char *beg_interval; + + /* Address of the place where a forward jump should go to the end of + the containing expression. Each alternative of an `or' -- except the + last -- ends with a forward jump of this sort. */ + unsigned char *fixup_alt_jump = 0; + + /* Counts open-groups as they are encountered. Remembered for the + matching close-group on the compile stack, so the same register + number is put in the stop_memory as the start_memory. */ + regnum_t regnum = 0; + +#ifdef DEBUG + DEBUG_PRINT1 ("\nCompiling pattern: "); + if (debug) + { + unsigned debug_count; + + for (debug_count = 0; debug_count < size; debug_count++) + printchar (pattern[debug_count]); + putchar ('\n'); + } +#endif /* DEBUG */ + + /* Initialize the compile stack. */ + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); + if (compile_stack.stack == NULL) + return REG_ESPACE; + + compile_stack.size = INIT_COMPILE_STACK_SIZE; + compile_stack.avail = 0; + + /* Initialize the pattern buffer. */ + bufp->syntax = syntax; + bufp->fastmap_accurate = 0; + bufp->not_bol = bufp->not_eol = 0; + + /* Set `used' to zero, so that if we return an error, the pattern + printer (for debugging) will think there's no pattern. We reset it + at the end. */ + bufp->used = 0; + + /* Always count groups, whether or not bufp->no_sub is set. */ + bufp->re_nsub = 0; + +#if !defined (emacs) && !defined (SYNTAX_TABLE) + /* Initialize the syntax table. */ + init_syntax_once (); +#endif + + if (bufp->allocated == 0) + { + if (bufp->buffer) + { /* 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. */ + RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); + } + else + { /* Caller did not allocate a buffer. Do it for them. */ + bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); + } + if (!bufp->buffer) return REG_ESPACE; + + bufp->allocated = INIT_BUF_SIZE; + } + + begalt = b = bufp->buffer; + + /* Loop through the uncompiled pattern until we're at the end. */ + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '^': + { + if ( /* If at start of pattern, it's an operator. */ + p == pattern + 1 + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's come before. */ + || at_begline_loc_p (pattern, p, syntax)) + BUF_PUSH (begline); + else + goto normal_char; + } + break; + + + case '$': + { + if ( /* If at end of pattern, it's an operator. */ + p == pend + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's next. */ + || at_endline_loc_p (p, pend, syntax)) + BUF_PUSH (endline); + else + goto normal_char; + } + break; + + + case '+': + case '?': + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern... */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + return REG_BADRPT; + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + + { + /* Are we optimizing this jump? */ + boolean keep_string_p = false; + + /* 1 means zero (many) matches is allowed. */ + char zero_times_ok = 0, many_times_ok = 0; + + /* If there is a sequence of repetition chars, collapse it + down to just one (the right one). We can't combine + interval operators with these because of, e.g., `a{2}*', + which should only match an even number of `a's. */ + + for (;;) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + + if (p == pend) + break; + + PATFETCH (c); + + if (c == '*' + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) + ; + + else if (syntax & RE_BK_PLUS_QM && c == '\\') + { + if (p == pend) return REG_EESCAPE; + + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + + c = c1; + } + else + { + PATUNFETCH; + break; + } + + /* If we get here, we found another repeat character. */ + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { /* More than one repetition is allowed, so put in at the + end a backward relative jump from `b' to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). + + But if we are at the `*' in the exact sequence `.*\n', + insert an unconditional jump backwards to the ., + instead of the beginning of the loop. This way we only + push a failure point once, instead of every time + through the loop. */ + assert (p - 1 > pattern); + + /* Allocate the space for the jump. */ + GET_BUFFER_SPACE (3); + + /* We know we are not at the first character of the pattern, + because laststart was nonzero. And we've already + incremented `p', by the way, to be the character after + the `*'. Do we have to do something analogous here + for null bytes, because of RE_DOT_NOT_NULL? */ + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') + && zero_times_ok + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') + && !(syntax & RE_DOT_NEWLINE)) + { /* We have .*\n. */ + STORE_JUMP (jump, b, laststart); + keep_string_p = true; + } + else + /* Anything else. */ + STORE_JUMP (maybe_pop_jump, b, laststart - 3); + + /* We've added more stuff to the buffer. */ + b += 3; + } + + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump + : on_failure_jump, + laststart, b + 3); + pending_exact = 0; + b += 3; + + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); + b += 3; + } + } + break; + + + case '.': + laststart = b; + BUF_PUSH (anychar); + break; + + + case '[': + { + boolean had_char_class = false; + + if (p == pend) return REG_EBRACK; + + /* Ensure that we have enough space to push a charset: the + opcode, the length count, and the bitset; 34 bytes in all. */ + GET_BUFFER_SPACE (34); + + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* Push the number of bytes in the bitmap. */ + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + + /* Clear the whole map. */ + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-2] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + SET_LIST_BIT ('\n'); + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) return REG_EBRACK; + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) return REG_EESCAPE; + + PATFETCH (c1); + SET_LIST_BIT (c1); + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + return REG_ERANGE; + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret + = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) return ret; + } + + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + + ret = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) return ret; + } + + /* See if we're at the beginning of a possible character + class. */ + + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) return REG_EBRACK; + + for (;;) + { + PATFETCH (c); + if (c == ':' || c == ']' || p == pend + || c1 == CHAR_CLASS_MAX_LENGTH) + break; + str[c1++] = c; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and:`]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') + { + int ch; + boolean is_alnum = STREQ (str, "alnum"); + boolean is_alpha = STREQ (str, "alpha"); + boolean is_blank = STREQ (str, "blank"); + boolean is_cntrl = STREQ (str, "cntrl"); + boolean is_digit = STREQ (str, "digit"); + boolean is_graph = STREQ (str, "graph"); + boolean is_lower = STREQ (str, "lower"); + boolean is_print = STREQ (str, "print"); + boolean is_punct = STREQ (str, "punct"); + boolean is_space = STREQ (str, "space"); + boolean is_upper = STREQ (str, "upper"); + boolean is_xdigit = STREQ (str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) return REG_ECTYPE; + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) return REG_EBRACK; + + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) + { + if ( (is_alnum && ISALNUM (ch)) + || (is_alpha && ISALPHA (ch)) + || (is_blank && ISBLANK (ch)) + || (is_cntrl && ISCNTRL (ch)) + || (is_digit && ISDIGIT (ch)) + || (is_graph && ISGRAPH (ch)) + || (is_lower && ISLOWER (ch)) + || (is_print && ISPRINT (ch)) + || (is_punct && ISPUNCT (ch)) + || (is_space && ISSPACE (ch)) + || (is_upper && ISUPPER (ch)) + || (is_xdigit && ISXDIGIT (ch))) + SET_LIST_BIT (ch); + } + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + had_char_class = false; + } + } + else + { + had_char_class = false; + SET_LIST_BIT (c); + } + } + + /* Discard any (non)matching list bytes that are all 0 at the + end of the map. Decrease the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; + } + break; + + + case '(': + if (syntax & RE_NO_BK_PARENS) + goto handle_open; + else + goto normal_char; + + + case ')': + if (syntax & RE_NO_BK_PARENS) + goto handle_close; + else + goto normal_char; + + + case '\n': + if (syntax & RE_NEWLINE_ALT) + goto handle_alt; + else + goto normal_char; + + + case '|': + if (syntax & RE_NO_BK_VBAR) + goto handle_alt; + else + goto normal_char; + + + case '{': + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) + goto handle_interval; + else + goto normal_char; + + + case '\\': + if (p == pend) return REG_EESCAPE; + + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW (c); + + switch (c) + { + case '(': + if (syntax & RE_NO_BK_PARENS) + goto normal_backslash; + + handle_open: + bufp->re_nsub++; + regnum++; + + if (COMPILE_STACK_FULL) + { + RETALLOC (compile_stack.stack, compile_stack.size << 1, + compile_stack_elt_t); + if (compile_stack.stack == NULL) return REG_ESPACE; + + compile_stack.size <<= 1; + } + + /* These are the values to restore when we hit end of this + group. They are all relative offsets, so that if the + whole pattern moves because of realloc, they will still + be valid. */ + COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; + COMPILE_STACK_TOP.fixup_alt_jump + = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; + COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; + COMPILE_STACK_TOP.regnum = regnum; + + /* We will eventually replace the 0 with the number of + groups inner to this one. But do not push a + start_memory for groups beyond the last one we can + represent in the compiled pattern. */ + if (regnum <= MAX_REGNUM) + { + COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; + BUF_PUSH_3 (start_memory, regnum, 0); + } + + compile_stack.avail++; + + fixup_alt_jump = 0; + laststart = 0; + begalt = b; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + break; + + + case ')': + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; + + if (COMPILE_STACK_EMPTY) + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_backslash; + else + return REG_ERPAREN; + + handle_close: + if (fixup_alt_jump) + { /* Push a dummy failure point at the end of the + alternative for a possible future + `pop_failure_jump' to pop. See comments at + `push_dummy_failure' in `re_match_2'. */ + BUF_PUSH (push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); + } + + /* See similar code for backslashed left paren above. */ + if (COMPILE_STACK_EMPTY) + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_char; + else + return REG_ERPAREN; + + /* Since we just checked for an empty stack above, this + ``can't happen''. */ + assert (compile_stack.avail != 0); + { + /* We don't just want to restore into `regnum', because + later groups should continue to be numbered higher, + as in `(ab)c(de)' -- the second group is #2. */ + regnum_t this_group_regnum; + + compile_stack.avail--; + begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; + fixup_alt_jump + = COMPILE_STACK_TOP.fixup_alt_jump + ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 + : 0; + laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; + this_group_regnum = COMPILE_STACK_TOP.regnum; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + + /* We're at the end of the group, so now we know how many + groups were inside this one. */ + if (this_group_regnum <= MAX_REGNUM) + { + unsigned char *inner_group_loc + = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; + + *inner_group_loc = regnum - this_group_regnum; + BUF_PUSH_3 (stop_memory, this_group_regnum, + regnum - this_group_regnum); + } + } + break; + + + case '|': /* `\|'. */ + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) + goto normal_backslash; + handle_alt: + if (syntax & RE_LIMITED_OPS) + goto normal_char; + + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (on_failure_jump, begalt, b + 6); + pending_exact = 0; + b += 3; + + /* The alternative before this one has a jump after it + which gets executed if it gets matched. Adjust that + jump so it will jump to this alternative's analogous + jump (put in below, which in turn will jump to the next + (if any) alternative's such jump, etc.). The last such + jump jumps to the correct final destination. A picture: + _____ _____ + | | | | + | v | v + a | b | c + + If we are at `b', then fixup_alt_jump right now points to a + three-byte space after `a'. We'll put in the jump, set + fixup_alt_jump to right after `b', and leave behind three + bytes which we'll fill in when we get to after `c'. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + /* Mark and leave space for a jump after this alternative, + to be filled in later either by next alternative or + when know we're at the end of a series of alternatives. */ + fixup_alt_jump = b; + GET_BUFFER_SPACE (3); + b += 3; + + laststart = 0; + begalt = b; + break; + + + case '{': + /* If \{ is a literal. */ + if (!(syntax & RE_INTERVALS) + /* If we're at `\{' and it's not the open-interval + operator. */ + || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + || (p - 2 == pattern && p == pend)) + goto normal_backslash; + + handle_interval: + { + /* If got here, then the syntax allows intervals. */ + + /* At least (most) this many matches must be made. */ + int lower_bound = -1, upper_bound = -1; + + beg_interval = p - 1; + + if (p == pend) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_EBRACE; + } + + GET_UNSIGNED_NUMBER (lower_bound); + + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) upper_bound = RE_DUP_MAX; + } + else + /* Interval such as `{1}' => match exactly once. */ + upper_bound = lower_bound; + + if (lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_BADBR; + } + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (c != '\\') return REG_EBRACE; + + PATFETCH (c); + } + + if (c != '}') + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_BADBR; + } + + /* We just parsed a valid interval. */ + + /* If it's invalid to have no preceding re. */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + return REG_BADRPT; + else if (syntax & RE_CONTEXT_INDEP_OPS) + laststart = b; + else + goto unfetch_interval; + } + + /* If the upper bound is zero, don't want to succeed at + all; jump from `laststart' to `b + 3', which will be + the end of the buffer after we insert the jump. */ + if (upper_bound == 0) + { + GET_BUFFER_SPACE (3); + INSERT_JUMP (jump, laststart, b + 3); + b += 3; + } + + /* Otherwise, we have a nontrivial interval. When + we're all done, the pattern will look like: + set_number_at <jump count> <upper bound> + set_number_at <succeed_n count> <lower bound> + succeed_n <after jump addr> <succed_n count> + <body of loop> + jump_n <succeed_n addr> <jump count> + (The upper bound and `jump_n' are omitted if + `upper_bound' is 1, though.) */ + else + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned nbytes = 10 + (upper_bound > 1) * 10; + + GET_BUFFER_SPACE (nbytes); + + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + INSERT_JUMP2 (succeed_n, laststart, + b + 5 + (upper_bound > 1) * 5, + lower_bound); + b += 5; + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + insert_op2 (set_number_at, laststart, 5, lower_bound, b); + b += 5; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + STORE_JUMP2 (jump_n, b, laststart + 5, + upper_bound - 1); + b += 5; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + insert_op2 (set_number_at, laststart, b - laststart, + upper_bound - 1, b); + b += 5; + } + } + pending_exact = 0; + beg_interval = NULL; + } + break; + + unfetch_interval: + /* If an invalid interval, match the characters as literals. */ + assert (beg_interval); + p = beg_interval; + beg_interval = NULL; + + /* normal_char and normal_backslash need `c'. */ + PATFETCH (c); + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (p > pattern && p[-1] == '\\') + goto normal_backslash; + } + goto normal_char; + +#ifdef emacs + /* There is no way to specify the before_dot and after_dot + operators. rms says this is ok. --karl */ + case '=': + BUF_PUSH (at_dot); + break; + + case 's': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); + break; +#endif /* emacs */ + + + case 'w': + laststart = b; + BUF_PUSH (wordchar); + break; + + + case 'W': + laststart = b; + BUF_PUSH (notwordchar); + break; + + + case '<': + BUF_PUSH (wordbeg); + break; + + case '>': + BUF_PUSH (wordend); + break; + + case 'b': + BUF_PUSH (wordbound); + break; + + case 'B': + BUF_PUSH (notwordbound); + break; + + case '`': + BUF_PUSH (begbuf); + break; + + case '\'': + BUF_PUSH (endbuf); + 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) + goto normal_char; + + c1 = c - '0'; + + if (c1 > regnum) + return REG_ESUBREG; + + /* Can't back reference to a subexpression if inside of it. */ + if (group_in_compile_stack (compile_stack, c1)) + goto normal_char; + + laststart = b; + BUF_PUSH_2 (duplicate, c1); + break; + + + case '+': + case '?': + if (syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backslash; + + default: + normal_backslash: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + c = TRANSLATE (c); + goto normal_char; + } + break; + + + default: + /* Expects the character in `c'. */ + normal_char: + /* If no exactn currently being built. */ + if (!pending_exact + + /* If last exactn not at current position. */ + || pending_exact + *pending_exact + 1 != b + + /* We have only one byte following the exactn for the count. */ + || *pending_exact == (1 << BYTEWIDTH) - 1 + + /* If followed by a repetition operator. */ + || *p == '*' || *p == '^' + || ((syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((syntax & RE_INTERVALS) + && ((syntax & RE_NO_BK_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + /* Start building a new exactn. */ + + laststart = b; + + BUF_PUSH_2 (exactn, 0); + pending_exact = b - 1; + } + + BUF_PUSH (c); + (*pending_exact)++; + break; + } /* switch (c) */ + } /* while p != pend */ + + + /* Through the pattern now. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + if (!COMPILE_STACK_EMPTY) + return REG_EPAREN; + + free (compile_stack.stack); + + /* We have succeeded; set the length of the buffer. */ + bufp->used = b - bufp->buffer; + +#ifdef DEBUG + if (debug) + { + DEBUG_PRINT1 ("\nCompiled pattern: "); + print_compiled_pattern (bufp); + } +#endif /* DEBUG */ + + return REG_NOERROR; +} /* regex_compile */ + +/* Subroutines for `regex_compile'. */ + +/* Store OP at LOC followed by two-byte integer parameter ARG. */ + +static void +store_op1 (op, loc, arg) + re_opcode_t op; + unsigned char *loc; + int arg; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg); +} + + +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +store_op2 (op, loc, arg1, arg2) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg1); + STORE_NUMBER (loc + 3, arg2); +} + + +/* Copy the bytes from LOC to END to open up three bytes of space at LOC + for OP followed by two-byte integer parameter ARG. */ + +static void +insert_op1 (op, loc, arg, end) + re_opcode_t op; + unsigned char *loc; + int arg; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 3; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op1 (op, loc, arg); +} + + +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +insert_op2 (op, loc, arg1, arg2, end) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 5; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op2 (op, loc, arg1, arg2); +} + + +/* P points to just after a ^ in PATTERN. Return true if that ^ comes + after an alternative or a begin-subexpression. We assume there is at + least one character before the ^. */ + +static boolean +at_begline_loc_p (pattern, p, syntax) + const char *pattern, *p; + reg_syntax_t syntax; +{ + const char *prev = p - 2; + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; + + return + /* After a subexpression? */ + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) + /* After an alternative? */ + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); +} + + +/* The dual of at_begline_loc_p. This one is for $. We assume there is + at least one character after the $, i.e., `P < PEND'. */ + +static boolean +at_endline_loc_p (p, pend, syntax) + const char *p, *pend; + int syntax; +{ + const char *next = p; + boolean next_backslash = *next == '\\'; + const char *next_next = p + 1 < pend ? p + 1 : NULL; + + return + /* Before a subexpression? */ + (syntax & RE_NO_BK_PARENS ? *next == ')' + : next_backslash && next_next && *next_next == ')') + /* Before an alternative? */ + || (syntax & RE_NO_BK_VBAR ? *next == '|' + : next_backslash && next_next && *next_next == '|'); +} + + +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and + false if it's not. */ + +static boolean +group_in_compile_stack (compile_stack, regnum) + compile_stack_type compile_stack; + regnum_t regnum; +{ + int this_element; + + for (this_element = compile_stack.avail - 1; + this_element >= 0; + this_element--) + if (compile_stack.stack[this_element].regnum == regnum) + return true; + + return false; +} + + +/* Read the ending character of a range (in a bracket expression) from the + uncompiled pattern *P_PTR (which ends at PEND). We assume the + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) + Then we set the translation of all bits between the starting and + ending characters (inclusive) in the compiled pattern B. + + Return an error code. + + We use these short variable names so we can use the same macros as + `regex_compile' itself. */ + +static reg_errcode_t +compile_range (p_ptr, pend, translate, syntax, b) + const char **p_ptr, *pend; + char *translate; + reg_syntax_t syntax; + unsigned char *b; +{ + unsigned this_char; + + const char *p = *p_ptr; + int range_start, range_end; + + if (p == pend) + return REG_ERANGE; + + /* Even though the pattern is a signed `char *', we need to fetch + with unsigned char *'s; if the high bit of the pattern character + is set, the range endpoints will be negative if we fetch using a + signed char *. + + We also want to fetch the endpoints without translating them; the + appropriate translation is done in the bit-setting loop below. */ + range_start = ((unsigned char *) p)[-2]; + range_end = ((unsigned char *) p)[0]; + + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + /* If the start is after the end, the range is empty. */ + if (range_start > range_end) + return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + + /* Here we see why `this_char' has to be larger than an `unsigned + char' -- the range is inclusive, so if `range_end' == 0xff + (assuming 8-bit characters), we would otherwise go into an infinite + loop, since all characters <= 0xff. */ + for (this_char = range_start; this_char <= range_end; this_char++) + { + SET_LIST_BIT (TRANSLATE (this_char)); + } + + return REG_NOERROR; +} + +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +#ifndef INIT_FAILURE_ALLOC +#define INIT_FAILURE_ALLOC 5 +#endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_SPACE each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ +int re_max_failures = 2000; + +typedef const unsigned char *fail_stack_elt_t; + +typedef struct +{ + fail_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} fail_stack_type; + +#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) + + +/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ + +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (fail_stack_elt_t *) \ + REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE requires `destination' be declared. */ + +#define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ + ? 0 \ + : ((fail_stack).stack = (fail_stack_elt_t *) \ + REGEX_REALLOCATE ((fail_stack).stack, \ + (fail_stack).size * sizeof (fail_stack_elt_t), \ + ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push PATTERN_OP on FAIL_STACK. + + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +#define PUSH_PATTERN_OP(pattern_op, fail_stack) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (fail_stack)) \ + ? 0 \ + : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ + 1)) + +/* This pushes an item onto the failure stack. Must be a four-byte + value. Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_ITEM(item) \ + fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item + +/* The complement operation. Assumes `fail_stack' is nonempty. */ +#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +#ifdef DEBUG +#define DEBUG_PUSH PUSH_FAILURE_ITEM +#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () +#else +#define DEBUG_PUSH(item) +#define DEBUG_POP(item_addr) +#endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be + declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + int this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + PUSH_FAILURE_ITEM (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + PUSH_FAILURE_ITEM (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ + PUSH_FAILURE_ITEM (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ + PUSH_FAILURE_ITEM (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_ITEM (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_ITEM (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +/* This is the number of items that are pushed and popped on the stack + for each register. */ +#define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +#ifdef DEBUG +#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +#else +#define NUM_NONREG_ITEMS 4 +#endif + +/* We push at most this many items on the stack. */ +#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +#define NUM_FAILURE_ITEMS \ + ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ + +#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ + int this_reg; \ + const unsigned char *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_ITEM (); \ + if (string_temp != NULL) \ + str = (const char *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (unsigned char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ + \ + low_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ + \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ + \ + regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + } \ + \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible + characters can start a string that matches the pattern. This fastmap + is used by re_search to skip quickly over impossible starting points. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as BUFP->fastmap. + + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in + the pattern buffer. + + Returns 0 if we succeed, -2 if an internal error. */ + +int +re_compile_fastmap (bufp) + struct re_pattern_buffer *bufp; +{ + int j, k; + fail_stack_type fail_stack; +#ifndef REGEX_MALLOC + char *destination; +#endif + /* We don't push any register information onto the failure stack. */ + unsigned num_regs = 0; + + register char *fastmap = bufp->fastmap; + unsigned char *pattern = bufp->buffer; + unsigned long size = bufp->used; + const unsigned char *p = pattern; + register unsigned char *pend = pattern + size; + + /* Assume that each path through the pattern can be null until + proven otherwise. We set this false at the bottom of switch + statement, to which we get only if a particular path doesn't + match the empty string. */ + boolean path_can_be_null = true; + + /* We aren't doing a `succeed_n' to begin with. */ + boolean succeed_n_p = false; + + assert (fastmap != NULL && p != NULL); + + INIT_FAIL_STACK (); + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ + bufp->fastmap_accurate = 1; /* It will be when we're done. */ + bufp->can_be_null = 0; + + while (p != pend || !FAIL_STACK_EMPTY ()) + { + if (p == pend) + { + bufp->can_be_null |= path_can_be_null; + + /* Reset for next path. */ + path_can_be_null = true; + + p = fail_stack.stack[--fail_stack.avail]; + } + + /* We should never be about to go beyond the end of the pattern. */ + assert (p < pend); + +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + + /* I guess the idea here is to simply not bother with a fastmap + if a backreference is used, since it's too hard to figure out + the fastmap for the corresponding group. Setting + `can_be_null' stops `re_search_2' from using the fastmap, so + that is all we do. */ + case duplicate: + bufp->can_be_null = 1; + return 0; + + + /* Following are the cases which match a character. These end + with `break'. */ + + case exactn: + fastmap[p[1]] = 1; + break; + + + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + fastmap[j] = 1; + break; + + + case charset_not: + /* Chars beyond end of map must be allowed. */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + fastmap[j] = 1; + break; + + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; + + + case anychar: + /* `.' matches anything ... */ + for (j = 0; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + /* ... except perhaps newline. */ + if (!(bufp->syntax & RE_DOT_NEWLINE)) + fastmap['\n'] = 0; + + /* Return if we have already set `can_be_null'; if we have, + then the fastmap is irrelevant. Something's wrong here. */ + else if (bufp->can_be_null) + return 0; + + /* Otherwise, have to check alternative paths. */ + break; + + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + /* All cases after this match the empty string. These end with + `continue'. */ + + + case before_dot: + case at_dot: + case after_dot: + continue; +#endif /* not emacs */ + + + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case push_dummy_failure: + continue; + + + case jump_n: + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + + /* Jump backward implies we just went through the body of a + loop and matched nothing. Opcode jumped to should be + `on_failure_jump' or `succeed_n'. Just treat it like an + ordinary jump. For a * loop, it has pushed its failure + point already; if so, discard that as redundant. */ + if ((re_opcode_t) *p != on_failure_jump + && (re_opcode_t) *p != succeed_n) + continue; + + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + + /* If what's on the stack is where we are now, pop it. */ + if (!FAIL_STACK_EMPTY () + && fail_stack.stack[fail_stack.avail - 1] == p) + fail_stack.avail--; + + continue; + + + case on_failure_jump: + case on_failure_keep_string_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + + /* For some patterns, e.g., `(a?)?', `p+j' here points to the + end of the pattern. We don't want to push such a point, + since when we restore it above, entering the switch will + increment `p' past the end of the pattern. We don't need + to push such a point since we obviously won't find any more + fastmap entries beyond `pend'. Such a pattern can match + the null string, though. */ + if (p + j < pend) + { + if (!PUSH_PATTERN_OP (p + j, fail_stack)) + return -2; + } + else + bufp->can_be_null = 1; + + if (succeed_n_p) + { + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + succeed_n_p = false; + } + + continue; + + + case succeed_n: + /* Get to the number of times to succeed. */ + p += 2; + + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 4; + succeed_n_p = true; /* Spaghetti code alert. */ + goto handle_on_failure_jump; + } + continue; + + + case set_number_at: + p += 4; + continue; + + + case start_memory: + case stop_memory: + p += 2; + continue; + + + default: + abort (); /* We have listed all the cases. */ + } /* switch *p++ */ + + /* Getting here means we have found the possible starting + characters for one path of the pattern -- and that the empty + string does not match. We need not follow this path further. + Instead, look at the next alternative (remembered on the + stack), or quit if no more. The test at the top of the loop + does these things. */ + path_can_be_null = false; + p = pend; + } /* while p */ + + /* Set `can_be_null' for the last path (also the first path, if the + pattern is empty). */ + bufp->can_be_null |= path_can_be_null; + return 0; +} /* re_compile_fastmap */ + +/* 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; + } +} + +/* Searching routines. */ + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search (bufp, string, size, startpos, range, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, startpos, range; + struct re_registers *regs; +{ + return re_search_2 (bufp, NULL, 0, string, size, startpos, range, + regs, size); +} + + +/* Using the compiled pattern in BUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. + + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. + + RANGE is how far to scan while trying to match. RANGE = 0 means try + only at STARTPOS; in general, the last start tried is STARTPOS + + RANGE. + + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire BUFP->buffer and its contained + subexpressions. + + Do not consider matching one past the index STOP in the virtual + concatenation of STRING1 and STRING2. + + We return either the position in the strings at which the match was + found, -1 if no match, or -2 if error (such as failure + stack overflow). */ + +int +re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int startpos; + int range; + struct re_registers *regs; + int stop; +{ + int val; + register char *fastmap = bufp->fastmap; + register char *translate = bufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; + + /* Check for out-of-range STARTPOS. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up RANGE if it might eventually take us outside + the virtual concatenation of STRING1 and STRING2. */ + if (endpos < -1) + range = -1 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) + { + if (startpos > 0) + return -1; + else + range = 1; + } + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + + /* Loop through the string, looking for a place to start matching. */ + for (;;) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot be the start of a match. If the pattern can match the + null string, however, we don't need to skip characters; we want + the first null string. */ + if (fastmap && startpos < total_size && !bufp->can_be_null) + { + if (range > 0) /* Searching forwards. */ + { + register const char *d; + register int lim = 0; + int irange = range; + + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; + + /* Written out as an if-else to avoid testing `translate' + inside the loop. */ + if (translate) + while (range > lim + && !fastmap[(unsigned char) + translate[(unsigned char) *d++]]) + range--; + else + while (range > lim && !fastmap[(unsigned char) *d++]) + range--; + + startpos += irange - range; + } + else /* Searching backwards. */ + { + register char c = (size1 == 0 || startpos >= size1 + ? string2[startpos - size1] + : string1[startpos]); + + if (!fastmap[(unsigned char) TRANSLATE (c)]) + goto advance; + } + } + + /* If can't match the null string, and that's all we have left, fail. */ + if (range >= 0 && startpos == total_size && fastmap + && !bufp->can_be_null) + return -1; + + val = re_match_2 (bufp, string1, size1, string2, size2, + startpos, regs, stop); + if (val >= 0) + return startpos; + + if (val == -2) + return -2; + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } + return -1; +} /* re_search_2 */ + +/* Declarations and macros for re_match_2. */ + +static int bcmp_translate (); +static boolean alt_match_null_string_p (), + common_op_match_null_string_p (), + group_match_null_string_p (); + +/* Structure for per-register (a.k.a. per-group) information. + This must not be longer than one word, because we push this value + onto the failure stack. Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ +typedef union +{ + fail_stack_elt_t word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +#define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} register_info_type; + +#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +#define IS_ACTIVE(R) ((R).bits.is_active) +#define MATCHED_SOMETHING(R) ((R).bits.matched_something) +#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +#define SET_REGS_MATCHED() \ + do \ + { \ + unsigned r; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + while (0) + + +/* This converts PTR, a pointer into one of the search strings `string1' + and `string2' into an offset from the beginning of that string. */ +#define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1) + +/* Registers are set to a sentinel when they haven't yet matched. */ +#define REG_UNSET_VALUE ((char *) -1) +#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + + +/* Macros for dealing with the split strings in re_match_2. */ + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ +#define PREFETCH() \ + while (d == dend) \ + { \ + /* End of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + + +/* Test if at very beginning or at very end of the virtual concatenation + of `string1' and `string2'. If only one string, it's `string2'. */ +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END(d) ((d) == end2) + + +/* Test if D points to a character which is word-constituent. We have + two special cases to check for: if past the end of string1, look at + the first character in string2; and if before the beginning of + string2, look at the last character in string1. */ +#define WORDCHAR_P(d) \ + (SYNTAX ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + == Sword) + +/* Test if the character before D and the one at D differ with respect + to being word-constituent. */ +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) + + +/* Free everything we malloc. */ +#ifdef REGEX_MALLOC +#define FREE_VAR(var) if (var) free (var); var = NULL +#define FREE_VARIABLES() \ + do { \ + FREE_VAR (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + } while (0) +#else /* not REGEX_MALLOC */ +/* Some MIPS systems (at least) want this to free alloca'd storage. */ +#define FREE_VARIABLES() alloca (0) +#endif /* not REGEX_MALLOC */ + + +/* These values must meet several constraints. They must not be valid + register values; since we have a limit of 255 registers (because + we use only one byte in the pattern for the register number), we can + use numbers larger than 255. They must differ by 1, because of + NUM_FAILURE_ITEMS above. And the value for the lowest register must + be larger than the value for the highest register, so we do not try + to actually save any registers when none are active. */ +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) + +/* Matching routines. */ + +#ifndef emacs /* Emacs never uses this. */ +/* re_match is like re_match_2 except it takes only a single string. */ + +int +re_match (bufp, string, size, pos, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, pos; + struct re_registers *regs; + { + return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size); +} +#endif /* not emacs */ + + +/* re_match_2 matches the compiled pattern in BUFP against the + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 + and SIZE2, respectively). We start matching at POS, and stop + matching at STOP. + + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we + store offsets for the substring each group matched in REGS. See the + documentation for exactly how many groups we fill. + + We return -1 if no match, -2 if an internal error (such as the + failure stack overflowing). Otherwise, we return the length of the + matched substring. */ + +int +re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int pos; + struct re_registers *regs; + int stop; +{ + /* General temporaries. */ + int mcnt; + unsigned char *p1; + + /* Just past the end of the corresponding string. */ + const char *end1, *end2; + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + const char *end_match_1, *end_match_2; + + /* Where we are in the data, and the end of the current string. */ + const char *d, *dend; + + /* Where we are in the pattern, and the end of the pattern. */ + unsigned char *p = bufp->buffer; + register unsigned char *pend = p + bufp->used; + + /* We use this to map every character in the string. */ + char *translate = bufp->translate; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to + the subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where + to resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is + a ``dummy''; if a failure happens and the failure point is a dummy, + it gets discarded and the next next one is tried. */ + fail_stack_type fail_stack; +#ifdef DEBUG + static unsigned failure_id = 0; + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; +#endif + + /* We fill all the registers internally, independent of what we + return, for use in backreferences. The number here includes + an element for register zero. */ + unsigned num_regs = bufp->re_nsub + 1; + + /* The currently active registers. */ + unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG; + unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG; + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ + const char **regstart, **regend; + + /* If a group that's operated upon by a repetition operator fails to + match anything, then the register for its start will need to be + restored because it will have been set to wherever in the string we + are when we last see its open-group operator. Similarly for a + register's end. */ + const char **old_regstart, **old_regend; + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ + register_info_type *reg_info; + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + unsigned best_regs_set = false; + const char **best_regstart, **best_regend; + + /* Logically, this is `best_regend[0]'. But we don't want to have to + allocate space for that if we're not allocating space for anything + else (see below). Also, we never need info about register 0 for + any of the other register vectors, and it seems rather a kludge to + treat `best_regend' differently than the rest. So we keep track of + the end of the best match so far in a separate variable. We + initialize this to NULL so that when we backtrack the first time + and need to test it, it's not garbage. */ + const char *match_end = NULL; + + /* Used when we pop values we don't care about. */ + const char **reg_dummy; + register_info_type *reg_info_dummy; + +#ifdef DEBUG + /* Counts the total number of registers pushed. */ + unsigned num_regs_pushed = 0; +#endif + + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + + INIT_FAIL_STACK (); + + /* Do not bother to initialize all the register variables if there are + no groups in the pattern, as it takes a fair amount of time. If + there are groups, we include space for register 0 (the whole + pattern), even though we never use it, since it simplifies the + array indexing. We should fix this. */ + if (bufp->re_nsub) + { + regstart = REGEX_TALLOC (num_regs, const char *); + regend = REGEX_TALLOC (num_regs, const char *); + old_regstart = REGEX_TALLOC (num_regs, const char *); + old_regend = REGEX_TALLOC (num_regs, const char *); + best_regstart = REGEX_TALLOC (num_regs, const char *); + best_regend = REGEX_TALLOC (num_regs, const char *); + reg_info = REGEX_TALLOC (num_regs, register_info_type); + reg_dummy = REGEX_TALLOC (num_regs, const char *); + reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); + + if (!(regstart && regend && old_regstart && old_regend && reg_info + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) + { + FREE_VARIABLES (); + return -2; + } + } +#ifdef REGEX_MALLOC + else + { + /* We must initialize all our variables to NULL, so that + `FREE_VARIABLES' doesn't try to free them. */ + regstart = regend = old_regstart = old_regend = best_regstart + = best_regend = reg_dummy = NULL; + reg_info = reg_info_dummy = (register_info_type *) NULL; + } +#endif /* REGEX_MALLOC */ + + /* The starting position is bogus. */ + if (pos < 0 || pos > size1 + size2) + { + FREE_VARIABLES (); + return -1; + } + + /* Initialize subexpression text positions to -1 to mark ones that no + start_memory/stop_memory has been seen for. Also initialize the + register information struct. */ + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = regend[mcnt] + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; + + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + /* We move `string1' into `string2' if the latter's empty -- but not if + `string1' is null. */ + if (size2 == 0 && string1 != NULL) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ + if (stop <= size1) + { + end_match_1 = string1 + stop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + stop - size1; + } + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. `d' + is advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal `string2'. */ + if (size1 > 0 && pos <= size1) + { + d = string1 + pos; + dend = end_match_1; + } + else + { + d = string2 + pos - size1; + dend = end_match_2; + } + + DEBUG_PRINT1 ("The compiled pattern is: "); + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); + DEBUG_PRINT1 ("The string to match is: `"); + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); + DEBUG_PRINT1 ("'\n"); + + /* This loops over pattern commands. It exits by returning from the + function if the match is complete, or it drops through if the match + fails at this starting point in the input data. */ + for (;;) + { + DEBUG_PRINT2 ("\n0x%x: ", p); + + if (p == pend) + { /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); + + /* If we haven't matched the entire string, and we want the + longest match, try backtracking. */ + if (d != end_match_2) + { + DEBUG_PRINT1 ("backtracking.\n"); + + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ + boolean same_str_p = (FIRST_STRING_P (match_end) + == MATCHING_IN_FIRST_STRING); + + /* If exceeds best match so far, save it. */ + if (!best_regs_set + || (same_str_p && d > match_end) + || (!same_str_p && !MATCHING_IN_FIRST_STRING)) + { + best_regs_set = true; + match_end = d; + + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + + /* If no failure points, don't restore garbage. */ + else if (best_regs_set) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } /* d != end_match_2 */ + + DEBUG_PRINT1 ("Accepting match.\n"); + + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) + { + /* Have the register data arrays been allocated? */ + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ + regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->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 (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + } + } + else + assert (bufp->regs_allocated == REGS_FIXED); + + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; + regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1 + : d - string2 + size1); + } + + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ + for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++) + { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { + regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]); + } + } + + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + } /* regs && !bufp->no_sub */ + + FREE_VARIABLES (); + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); + + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + + return mcnt; + } + + /* Otherwise match next pattern command. */ +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case no_op: + DEBUG_PRINT1 ("EXECUTING no_op.\n"); + break; + + + /* Match the next n pattern characters exactly. The following + byte in the pattern defines n, and the n bytes after that + are the characters to match. */ + case exactn: + mcnt = *p++; + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); + + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH (); + if (translate[(unsigned char) *d++] != (char) *p++) + goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH (); + if (*d++ != (char) *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED (); + break; + + + /* Match any character except possibly a newline or a null. */ + case anychar: + DEBUG_PRINT1 ("EXECUTING anychar.\n"); + + PREFETCH (); + + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) + goto fail; + + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%d'.\n", *d); + d++; + break; + + + case charset: + case charset_not: + { + register unsigned char c; + boolean not = (re_opcode_t) *(p - 1) == charset_not; + + DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + + PREFETCH (); + c = TRANSLATE (*d); /* The character to match. */ + + /* Cast to `unsigned' instead of `unsigned char' in case the + bit list is a full 32 bytes long. */ + if (c < (unsigned) (*p * BYTEWIDTH) + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; + + SET_REGS_MATCHED (); + d++; + break; + } + + + /* The beginning of a group is represented by start_memory. + The arguments are the register number in the next byte, and the + number of groups inner to this one in the next. The text + matched within the group is recorded (in the internal + registers data structure) under the register number. */ + case start_memory: + DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); + + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = group_match_null_string_p (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + DEBUG_PRINT2 (" old_regstart: %d\n", + POINTER_TO_OFFSET (old_regstart[*p])); + + regstart[*p] = d; + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); + + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* This is the new highest active register. */ + highest_active_reg = *p; + + /* If nothing was active before, this is the new lowest active + register. */ + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *p; + + /* Move past the register number and inner group count. */ + p += 2; + break; + + + /* The stop_memory opcode represents the end of a group. Its + arguments are the same as start_memory's: the register + number, and the number of inner groups. */ + case stop_memory: + DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); + + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + DEBUG_PRINT2 (" old_regend: %d\n", + POINTER_TO_OFFSET (old_regend[*p])); + + regend[*p] = d; + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); + + /* This register isn't active anymore. */ + IS_ACTIVE (reg_info[*p]) = 0; + + /* If this was the only register active, nothing is active + anymore. */ + if (lowest_active_reg == highest_active_reg) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + { /* We must scan for the new highest active register, since + it isn't necessarily one less than now: consider + (a(b)c(d(e)f)g). When group 3 ends, after the f), the + new highest active register is 1. */ + unsigned char r = *p - 1; + while (r > 0 && !IS_ACTIVE (reg_info[r])) + r--; + + /* If we end up at register zero, that means that we saved + the registers as the result of an `on_failure_jump', not + a `start_memory', and we jumped to past the innermost + `stop_memory'. For example, in ((.)*) we save + registers 1 and 2 as a result of the *, but when we pop + back to the second ), we are at the stop_memory 1. + Thus, nothing is active. */ + if (r == 0) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + highest_active_reg = r; + } + + /* If just failed to match something this time around with a + group that's operated on by a repetition operator, try to + force exit from the ``loop'', and restore the register + information for this group that we had before trying this + last match. */ + if ((!MATCHED_SOMETHING (reg_info[*p]) + || (re_opcode_t) p[-3] == start_memory) + && (p + 2) < pend) + { + boolean is_a_jump_n = false; + + p1 = p + 2; + mcnt = 0; + switch ((re_opcode_t) *p1++) + { + case jump_n: + is_a_jump_n = true; + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (is_a_jump_n) + p1 += 2; + break; + + default: + /* do nothing */ ; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump right before the start_memory + corresponding to this stop_memory, exit from the loop + by forcing a failure after pushing on the stack the + on_failure_jump's jump in the pattern, and d. */ + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump + && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) + { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) + { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < *p + *(p + 1); r++) + { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if ((int) old_regend[r] >= (int) regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); + + goto fail; + } + } + + /* Move past the register number and the inner group count. */ + p += 2; + break; + + + /* \<digit> has been turned into a `duplicate' command which is + followed by the numeric value of <digit> as the register number. */ + case duplicate: + { + register const char *d2, *dend2; + int regno = *p++; /* Get which register to match against. */ + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); + + /* Can't back reference a group which we've never matched. */ + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) + goto fail; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((FIRST_STRING_P (regstart[regno]) + == FIRST_STRING_P (regend[regno])) + ? regend[regno] : end_match_1); + for (;;) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + + /* End of string1 => advance to string2. */ + d2 = string2; + dend2 = regend[regno]; + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH (); + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? bcmp_translate (d, d2, mcnt, translate) + : bcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + } + } + break; + + + /* begline matches the empty string at the beginning of the string + (unless `not_bol' is set in `bufp'), and, if + `newline_anchor' is set, after newlines. */ + case begline: + DEBUG_PRINT1 ("EXECUTING begline.\n"); + + if (AT_STRINGS_BEG (d)) + { + if (!bufp->not_bol) break; + } + else if (d[-1] == '\n' && bufp->newline_anchor) + { + break; + } + /* In all other cases, we fail. */ + goto fail; + + + /* endline is the dual of begline. */ + case endline: + DEBUG_PRINT1 ("EXECUTING endline.\n"); + + if (AT_STRINGS_END (d)) + { + if (!bufp->not_eol) break; + } + + /* We have to ``prefetch'' the next character. */ + else if ((d == end1 ? *string2 : *d) == '\n' + && bufp->newline_anchor) + { + break; + } + goto fail; + + + /* Match at the very beginning of the data. */ + case begbuf: + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); + if (AT_STRINGS_BEG (d)) + break; + goto fail; + + + /* Match at the very end of the data. */ + case endbuf: + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); + if (AT_STRINGS_END (d)) + break; + goto fail; + + + /* on_failure_keep_string_jump is used to optimize `.*\n'. It + pushes NULL as the value for the string on the stack. Then + `pop_failure_point' will keep the current value for the + string, instead of restoring it. To see why, consider + matching `foo\nbar' against `.*\n'. The .* matches the foo; + then the . fails against the \n. But the next thing we want + to do is match the \n against the \n; if we restored the + string value, we would be back at the foo. + + Because this is used only in specific cases, we don't need to + check all the things that `on_failure_jump' does, to make + sure the right things get saved on the stack. Hence we don't + share its code. The only reason to push anything on the + stack at all is that otherwise we would have to change + `anychar's code to do something besides goto fail in this + case; that seems worse than this. */ + case on_failure_keep_string_jump: + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); + + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); + break; + + + /* Uses of on_failure_jump: + + Each alternative starts with an on_failure_jump that points + to the beginning of the next alternative. Each alternative + except the last ends with a jump that in effect jumps past + the rest of the alternatives. (They really jump to the + ending jump of the following alternative, because tensioning + these jumps is a hassle.) + + Repeats start with an on_failure_jump that points past both + the repetition text and either the following jump or + pop_failure_jump back to this on_failure_jump. */ + case on_failure_jump: + on_failure: + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); + + /* If this on_failure_jump comes right before a group (i.e., + the original * applied to a group), save the information + for that group and all inner ones, so that if we fail back + to this point, the group's information will be correct. + For example, in \(a*\)*\1, we need the preceding group, + and in \(\(a*\)b*\)\2, we need the inner group. */ + + /* We can't use `p' to check ahead because we push + a failure point to `p + mcnt' after we do this. */ + p1 = p; + + /* We need to skip no_op's before we look for the + start_memory in case this on_failure_jump is happening as + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 + against aba. */ + while (p1 < pend && (re_opcode_t) *p1 == no_op) + p1++; + + if (p1 < pend && (re_opcode_t) *p1 == start_memory) + { + /* We have a new highest active register now. This will + get reset at the start_memory we are about to get to, + but we will have saved all the registers relevant to + this repetition op, as described above. */ + highest_active_reg = *(p1 + 1) + *(p1 + 2); + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *(p1 + 1); + } + + DEBUG_PRINT1 (":\n"); + PUSH_FAILURE_POINT (p + mcnt, d, -2); + break; + + + /* A smart repeat ends with `maybe_pop_jump'. + We change it to either `pop_failure_jump' or `jump'. */ + case maybe_pop_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); + { + register unsigned char *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. */ + while (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; /* Skip over args, too. */ + + /* If we're at the end of the pattern, we can change. */ + if (p2 == pend) + { + /* Consider what happens when matching ":\(.*\)" + against ":/". I don't really understand this code + yet. */ + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 + (" End of pattern: change to `pop_failure_jump'.\n"); + } + + else if ((re_opcode_t) *p2 == exactn + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) + { + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; + p1 = p + mcnt; + + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ + if ((re_opcode_t) p1[3] == exactn && p1[5] != c) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset + || (re_opcode_t) p1[3] == charset_not) + { + int not = (re_opcode_t) p1[3] == charset_not; + + if (c < (unsigned char) (p1[4] * BYTEWIDTH) + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + /* `not' is equal to 1 if c would match, which means + that we can't change to pop_failure_jump. */ + if (!not) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + } + p -= 2; /* Point at relative address again. */ + if ((re_opcode_t) p[-1] != pop_failure_jump) + { + p[-1] = (unsigned char) jump; + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } + /* Note fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to + its matching on_failure_jump, where the latter will push a + failure point. The pop_failure_jump takes off failure + points put on by this pop_failure_jump's matching + on_failure_jump; we got through the pattern to here from the + matching on_failure_jump, so didn't fail. */ + case pop_failure_jump: + { + /* We need to pass separate storage for the lowest and + highest registers, even though we don't care about the + actual values. Otherwise, we will restore only one + register from the stack, since lowest will == highest in + `pop_failure_point'. */ + unsigned dummy_low_reg, dummy_high_reg; + unsigned char *pdummy; + const char *sdummy; + + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); + POP_FAILURE_POINT (sdummy, pdummy, + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } + /* Note fall through. */ + + + /* Unconditionally jump (without popping any failure points). */ + case jump: + unconditional_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); + p += mcnt; /* Do the jump. */ + DEBUG_PRINT2 ("(to 0x%x).\n", p); + break; + + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); + goto unconditional_jump; + + + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at pop_failure_jump. We will end up at + pop_failure_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for pop_failure_jump to pop. */ + case dummy_failure_jump: + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); + /* It doesn't matter what we push for the string here. What + the code at `fail' tests is the value for the pattern. */ + PUSH_FAILURE_POINT (0, 0, -2); + goto unconditional_jump; + + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `pop_failure_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT (0, 0, -2); + break; + + /* Have to succeed matching what follows at least n times. + After that, handle like `on_failure_jump'. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); + + assert (mcnt >= 0); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) + { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR (p, mcnt); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt); + } + else if (mcnt == 0) + { + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); + p[2] = (unsigned char) no_op; + p[3] = (unsigned char) no_op; + goto on_failure; + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); + + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER (p + 2, mcnt); + goto unconditional_jump; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + break; + + case set_number_at: + { + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); + STORE_NUMBER (p1, mcnt); + break; + } + + case wordbound: + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + break; + goto fail; + + case notwordbound: + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + goto fail; + break; + + case wordbeg: + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); + if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + break; + goto fail; + + case wordend: + DEBUG_PRINT1 ("EXECUTING wordend.\n"); + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) + && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) + break; + goto fail; + +#ifdef emacs +#ifdef emacs19 + case before_dot: + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) >= point) + goto fail; + break; + + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) != point) + goto fail; + break; + + case after_dot: + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) <= point) + goto fail; + break; +#else /* not emacs19 */ + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point) + goto fail; + break; +#endif /* not emacs19 */ + + case syntaxspec: + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchsyntax; + + case wordchar: + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); + mcnt = (int) Sword; + matchsyntax: + PREFETCH (); + if (SYNTAX (*d++) != (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + + case notsyntaxspec: + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchnotsyntax; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); + mcnt = (int) Sword; + matchnotsyntax: + PREFETCH (); + if (SYNTAX (*d++) == (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + +#else /* not emacs */ + case wordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); + PREFETCH (); + if (!WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); + PREFETCH (); + if (WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; +#endif /* not emacs */ + + default: + abort (); + } + continue; /* Successfully executed one pattern command; keep going. */ + + + /* We goto here if a matching operation fails. */ + fail: + if (!FAIL_STACK_EMPTY ()) + { /* A restart point is known. Restore to that state. */ + DEBUG_PRINT1 ("\nFAIL:\n"); + POP_FAILURE_POINT (d, p, + lowest_active_reg, highest_active_reg, + regstart, regend, reg_info); + + /* If this failure point is a dummy, try the next one. */ + if (!p) + goto fail; + + /* If we failed to the end of the pattern, don't examine *p. */ + assert (p <= pend); + if (p < pend) + { + boolean is_a_jump_n = false; + + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + switch ((re_opcode_t) *p) + { + case jump_n: + is_a_jump_n = true; + case maybe_pop_jump: + case pop_failure_jump: + case jump: + p1 = p + 1; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) + || (!is_a_jump_n + && (re_opcode_t) *p1 == on_failure_jump)) + goto fail; + break; + default: + /* do nothing */ ; + } + } + + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else + break; /* Matching at this starting point really fails. */ + } /* for (;;) */ + + if (best_regs_set) + goto restore_best_regs; + + FREE_VARIABLES (); + + return -1; /* Failure to match. */ +} /* re_match_2 */ + +/* Subroutine definitions for re_match_2. */ + + +/* We are passed P pointing to a register number after a start_memory. + + Return true if the pattern up to the corresponding stop_memory can + match the empty string, and false otherwise. + + If we find the matching stop_memory, sets P to point to one past its number. + Otherwise, sets P to an undefined byte less than or equal to END. + + We don't handle duplicates properly (yet). */ + +static boolean +group_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + /* Point to after the args to the start_memory. */ + unsigned char *p1 = *p + 2; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and return true or + false, as appropriate, when we get to one that can't, or to the + matching stop_memory. */ + + switch ((re_opcode_t) *p1) + { + /* Could be either a loop or a series of alternatives. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + /* If the next operation is not a jump backwards in the + pattern. */ + + if (mcnt >= 0) + { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': + + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c + + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ + + + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ + + while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) + { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ + + if (!alt_match_null_string_p (p1, p1 + mcnt - 3, + reg_info)) + return false; + + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; + + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((re_opcode_t) *p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) + { + /* Get to the beginning of the n-th alternative. */ + p1 -= 3; + break; + } + } + + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - 2); + + if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) + return false; + + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ + break; + + + case stop_memory: + assert (p1[1] == **p); + *p = p1 + 2; + return true; + + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return false; +} /* group_match_null_string_p */ + + +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: + It expects P to be the first byte of a single alternative and END one + byte past the last. The alternative can contain groups. */ + +static boolean +alt_match_null_string_p (p, end, reg_info) + unsigned char *p, *end; + register_info_type *reg_info; +{ + int mcnt; + unsigned char *p1 = p; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and break when we get + to one that can't. */ + + switch ((re_opcode_t) *p1) + { + /* It's a loop. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + break; + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return true; +} /* alt_match_null_string_p */ + + +/* Deals with the ops common to group_match_null_string_p and + alt_match_null_string_p. + + Sets P to one after the op and its arguments, if any. */ + +static boolean +common_op_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + boolean ret; + int reg_no; + unsigned char *p1 = *p; + + switch ((re_opcode_t) *p1++) + { + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbeg: + case wordend: + case wordbound: + case notwordbound: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + break; + + case start_memory: + reg_no = *p1; + assert (reg_no > 0 && reg_no <= MAX_REGNUM); + ret = group_match_null_string_p (&p1, end, reg_info); + + /* Have to set this here in case we're checking a group which + contains a group and a back reference to it. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; + + if (!ret) + return false; + break; + + /* If this is an optimized succeed_n for zero times, make the jump. */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (mcnt >= 0) + p1 += mcnt; + else + return false; + break; + + case succeed_n: + /* Get to the number of times to succeed. */ + p1 += 2; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt == 0) + { + p1 -= 4; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + } + else + return false; + break; + + case duplicate: + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) + return false; + break; + + case set_number_at: + p1 += 4; + + default: + /* All other opcodes mean we cannot match the empty string. */ + return false; + } + + *p = p1; + return true; +} /* common_op_match_null_string_p */ + + +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN + bytes; nonzero otherwise. */ + +static int +bcmp_translate (s1, s2, len, translate) + unsigned char *s1, *s2; + register int len; + char *translate; +{ + register unsigned char *p1 = s1, *p2 = s2; + while (len) + { + if (translate[*p1++] != translate[*p2++]) return 1; + len--; + } + return 0; +} + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length SIZE) 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. + + We call regex_compile to do the actual compilation. */ + +const char * +re_compile_pattern (pattern, length, bufp) + const char *pattern; + int length; + struct re_pattern_buffer *bufp; +{ + reg_errcode_t ret; + + /* GNU code is written to assume at least RE_NREGS registers will be set + (and at least one extra will be -1). */ + bufp->regs_allocated = REGS_UNALLOCATED; + + /* 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. */ + bufp->no_sub = 0; + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = regex_compile (pattern, length, re_syntax_options, bufp); + + return re_error_msg[(int) ret]; +} + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them if this is an Emacs or POSIX compilation. */ + +#if !defined (emacs) && !defined (_POSIX_SOURCE) + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +re_comp (s) + const char *s; +{ + reg_errcode_t ret; + + if (!s) + { + if (!re_comp_buf.buffer) + return "No previous regular expression"; + return 0; + } + + if (!re_comp_buf.buffer) + { + re_comp_buf.buffer = (unsigned char *) malloc (200); + if (re_comp_buf.buffer == NULL) + return "Memory exhausted"; + re_comp_buf.allocated = 200; + + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + if (re_comp_buf.fastmap == NULL) + return "Memory exhausted"; + } + + /* 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 = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + + /* Yes, we're discarding `const' here. */ + return (char *) re_error_msg[(int) ret]; +} + + +int +re_exec (s) + const char *s; +{ + const int len = strlen (s); + return + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); +} +#endif /* not emacs and not _POSIX_SOURCE */ + +/* POSIX.2 functions. Don't define these for Emacs. */ + +#ifndef emacs + +/* 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' and `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 *preg; + const char *pattern; + int cflags; +{ + reg_errcode_t ret; + unsigned syntax + = (cflags & REG_EXTENDED) ? + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; + + /* regex_compile will allocate the space for the compiled pattern. */ + preg->buffer = 0; + preg->allocated = 0; + + /* Don't bother to use a fastmap when searching. This simplifies the + REG_NEWLINE case: if we used a fastmap, we'd have to put all the + characters after newlines into the fastmap. This way, we just try + every character. */ + preg->fastmap = 0; + + if (cflags & REG_ICASE) + { + unsigned i; + + preg->translate = (char *) malloc (CHAR_SET_SIZE); + if (preg->translate == NULL) + return (int) REG_ESPACE; + + /* Map uppercase characters to corresponding lowercase ones. */ + for (i = 0; i < CHAR_SET_SIZE; i++) + preg->translate[i] = ISUPPER (i) ? tolower (i) : i; + } + else + preg->translate = NULL; + + /* 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); + + /* POSIX says a null character in the pattern terminates it, so we + can use strlen here in compiling the pattern. */ + ret = regex_compile (pattern, strlen (pattern), syntax, preg); + + /* 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; + + return (int) ret; +} + + +/* 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 *preg; + const char *string; + size_t nmatch; + regmatch_t pmatch[]; + int eflags; +{ + int ret; + struct re_registers regs; + regex_t private_preg; + int len = strlen (string); + boolean want_reg_info = !preg->no_sub && nmatch > 0; + + private_preg = *preg; + + private_preg.not_bol = !!(eflags & REG_NOTBOL); + private_preg.not_eol = !!(eflags & REG_NOTEOL); + + /* The user has told us exactly how many registers to return + information about, via `nmatch'. We have to pass that on to the + matching routines. */ + private_preg.regs_allocated = REGS_FIXED; + + if (want_reg_info) + { + regs.num_regs = nmatch; + regs.start = TALLOC (nmatch, regoff_t); + regs.end = TALLOC (nmatch, regoff_t); + if (regs.start == NULL || regs.end == NULL) + return (int) REG_NOMATCH; + } + + /* Perform the searching operation. */ + ret = re_search (&private_preg, string, len, + /* start: */ 0, /* range: */ len, + want_reg_info ? ®s : (struct re_registers *) 0); + + /* Copy the register information to the POSIX structure. */ + if (want_reg_info) + { + if (ret >= 0) + { + unsigned r; + + for (r = 0; r < nmatch; r++) + { + pmatch[r].rm_so = regs.start[r]; + pmatch[r].rm_eo = regs.end[r]; + } + } + + /* If we needed the temporary register info, free the space now. */ + free (regs.start); + free (regs.end); + } + + /* We want zero return to mean success, unlike `re_search'. */ + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; +} + + +/* 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 *preg; + char *errbuf; + size_t errbuf_size; +{ + const char *msg; + size_t msg_size; + + if (errcode < 0 + || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[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 = re_error_msg[errcode]; + + /* POSIX doesn't require that we do anything in this case, but why + not be nice. */ + if (! msg) + msg = "Success"; + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (errbuf_size != 0) + { + if (msg_size > errbuf_size) + { + strncpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; + } + else + strcpy (errbuf, msg); + } + + return msg_size; +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (preg) + regex_t *preg; +{ + if (preg->buffer != NULL) + free (preg->buffer); + preg->buffer = NULL; + + preg->allocated = 0; + preg->used = 0; + + if (preg->fastmap != NULL) + free (preg->fastmap); + preg->fastmap = NULL; + preg->fastmap_accurate = 0; + + if (preg->translate != NULL) + free (preg->translate); + preg->translate = NULL; +} + +#endif /* not emacs */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/libregex/regex.h b/gnu/lib/libregex/regex.h new file mode 100644 index 00000000000..408dd210348 --- /dev/null +++ b/gnu/lib/libregex/regex.h @@ -0,0 +1,490 @@ +/* Definitions for data structures and routines for the regular + expression library, version 0.12. + + Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef __REGEXP_LIBRARY_H__ +#define __REGEXP_LIBRARY_H__ + +/* POSIX says that <sys/types.h> must be included (by the caller) before + <regex.h>. */ + +#ifdef VMS +/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it + should be there. */ +#include <stddef.h> +#endif + + +/* 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 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 (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) + +/* 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. */ +extern 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_UNMATCHED_RIGHT_PAREN_ORD) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS) + +#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) + +/* 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) + +/* 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_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS + replaces RE_CONTEXT_INDEP_OPS 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 +#define RE_DUP_MAX ((1 << 15) - 1) + + +/* 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) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ + 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, /* Not implemented. */ + 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. */ + +struct re_pattern_buffer +{ +/* [[[begin 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 allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long 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. */ + char *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; + +/* [[[end pattern_buffer]]] */ +}; + +typedef struct re_pattern_buffer regex_t; + + +/* search.c (search_buffer) in Emacs needs this one opcode value. It is + defined both in `regex.c' and here. */ +#define RE_EXACTN_VALUE 1 + +/* 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. */ + +/* To avoid duplicating every routine declaration -- once with a + prototype (if we are ANSI), and once without (if we aren't) -- we + use the following macro to declare argument types. This + unfortunately clutters up the declarations a bit, but I think it's + worth it. */ + +#if __STDC__ + +#define _RE_ARGS(args) args + +#else /* not __STDC__ */ + +#define _RE_ARGS(args) () + +#endif /* not __STDC__ */ + +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the `re_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax _RE_ARGS ((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. */ +extern const char *re_compile_pattern + _RE_ARGS ((const char *pattern, int 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. */ +extern int re_compile_fastmap _RE_ARGS ((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). */ +extern int re_search + _RE_ARGS ((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. */ +extern int re_search_2 + _RE_ARGS ((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. */ +extern int re_match + _RE_ARGS ((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'. */ +extern int re_match_2 + _RE_ARGS ((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. */ +extern void re_set_registers + _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends)); + +/* 4.2 bsd compatibility. */ +extern char *re_comp _RE_ARGS ((const char *)); +extern int re_exec _RE_ARGS ((const char *)); + +/* POSIX compatibility. */ +extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags)); +extern int regexec + _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags)); +extern size_t regerror + _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf, + size_t errbuf_size)); +extern void regfree _RE_ARGS ((regex_t *preg)); + +#endif /* not __REGEXP_LIBRARY_H__ */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/regex-0.12/AUTHORS b/gnu/lib/regex-0.12/AUTHORS new file mode 100644 index 00000000000..058be996a27 --- /dev/null +++ b/gnu/lib/regex-0.12/AUTHORS @@ -0,0 +1,10 @@ +Richard Stallman -- original version and continuing revisions of + regex.c and regex.h, and original version of the documentation. + +Karl Berry and Kathryn Hargreaves -- extensive modifications to above, + and all test files. + +Jim Blandy -- original version of re_set_registers, revisions to regex.c. + +Joe Arceneaux, David MacKenzie, Mike Haertel, Charles Hannum, and +probably others -- revisions to regex.c. diff --git a/gnu/lib/regex-0.12/COPYING b/gnu/lib/regex-0.12/COPYING new file mode 100644 index 00000000000..a43ea2126fb --- /dev/null +++ b/gnu/lib/regex-0.12/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gnu/lib/regex-0.12/ChangeLog b/gnu/lib/regex-0.12/ChangeLog new file mode 100644 index 00000000000..ef919d276a7 --- /dev/null +++ b/gnu/lib/regex-0.12/ChangeLog @@ -0,0 +1,3030 @@ +Fri Apr 2 17:31:59 1993 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * Released version 0.12. + + * regex.c (regerror): If errcode is zero, that's not a valid + error code, according to POSIX, but return "Success." + + * regex.c (regerror): Remember to actually fetch the message + from re_error_msg. + + * regex.c (regex_compile): Don't use the trick for ".*\n" on + ".+\n". Since the latter involves laying an extra choice + point, the backward jump isn't adjusted properly. + +Thu Mar 25 21:35:18 1993 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * regex.c (regex_compile): In the handle_open and handle_close + sections, clear pending_exact to zero. + +Tue Mar 9 12:03:07 1993 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu) + + * regex.c (re_search_2): In the loop which searches forward + using fastmap, don't forget to cast the character from the + string to an unsigned before using it as an index into the + translate map. + +Thu Jan 14 15:41:46 1993 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu) + + * regex.h: Never define const; let the callers do it. + configure.in: Don't define USING_AUTOCONF. + +Wed Jan 6 20:49:29 1993 Jim Blandy (jimb@geech.gnu.ai.mit.edu) + + * regex.c (regerror): Abort if ERRCODE is out of range. + +Sun Dec 20 16:19:10 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * configure.in: Arrange to #define USING_AUTOCONF. + * regex.h: If USING_AUTOCONF is #defined, don't mess with + `const' at all; autoconf has taken care of it. + +Mon Dec 14 21:40:39 1992 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu) + + * regex.h (RE_SYNTAX_AWK): Fix typo. From Arnold Robbins. + +Sun Dec 13 20:35:39 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * regex.c (compile_range): Fetch the range start and end by + casting the pattern pointer to an `unsigned char *' before + fetching through it. + +Sat Dec 12 09:41:01 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * regex.c: Undo change of 12/7/92; it's better for Emacs to + #define HAVE_CONFIG_H. + +Fri Dec 11 22:00:34 1992 Jim Meyering (meyering@hal.gnu.ai.mit.edu) + + * regex.c: Define and use isascii-protected ctype.h macros. + +Fri Dec 11 05:10:38 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu) + + * regex.c (re_match_2): Undo Karl's November 10th change; it + keeps the group in :\(.*\) from matching :/ properly. + +Mon Dec 7 19:44:56 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu) + + * regex.c: #include config.h if either HAVE_CONFIG_H or emacs + is #defined. + +Tue Dec 1 13:33:17 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * regex.c [HAVE_CONFIG_H]: Include config.h. + +Wed Nov 25 23:46:02 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * regex.c (regcomp): Add parens around bitwise & for clarity. + Initialize preg->allocated to prevent segv. + +Tue Nov 24 09:22:29 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu) + + * regex.c: Use HAVE_STRING_H, not USG. + * configure.in: Check for string.h, not USG. + +Fri Nov 20 06:33:24 1992 Karl Berry (karl@cs.umb.edu) + + * regex.c (SIGN_EXTEND_CHAR) [VMS]: Back out of this change, + since Roland Roberts now says it was a localism. + +Mon Nov 16 07:01:36 1992 Karl Berry (karl@cs.umb.edu) + + * regex.h (const) [!HAVE_CONST]: Test another cpp symbol (from + Autoconf) before zapping const. + +Sun Nov 15 05:36:42 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu) + + * regex.c, regex.h: Changes for VMS from Roland B Roberts + <roberts@nsrl31.nsrl.rochester.edu>. + +Thu Nov 12 11:31:15 1992 Karl Berry (karl@cs.umb.edu) + + * Makefile.in (distfiles): Include INSTALL. + +Tue Nov 10 09:29:23 1992 Karl Berry (karl@cs.umb.edu) + + * regex.c (re_match_2): At maybe_pop_jump, if at end of string + and pattern, just quit the matching loop. + + * regex.c (LETTER_P): Rename to `WORDCHAR_P'. + + * regex.c (AT_STRINGS_{BEG,END}): Take `d' as an arg; change + callers. + + * regex.c (re_match_2) [!emacs]: In wordchar and notwordchar + cases, advance d. + +Wed Nov 4 15:43:58 1992 Karl Berry (karl@hal.gnu.ai.mit.edu) + + * regex.h (const) [!__STDC__]: Don't define if it's already defined. + +Sat Oct 17 19:28:19 1992 Karl Berry (karl@cs.umb.edu) + + * regex.c (bcmp, bcopy, bzero): Only #define if they are not + already #defined. + + * configure.in: Use AC_CONST. + +Thu Oct 15 08:39:06 1992 Karl Berry (karl@cs.umb.edu) + + * regex.h (const) [!const]: Conditionalize. + +Fri Oct 2 13:31:42 1992 Karl Berry (karl@cs.umb.edu) + + * regex.h (RE_SYNTAX_ED): New definition. + +Sun Sep 20 12:53:39 1992 Karl Berry (karl@cs.umb.edu) + + * regex.[ch]: remove traces of `longest_p' -- dumb idea to put + this into the pattern buffer, as it means parallelism loses. + + * Makefile.in (config.status): use sh to run configure --no-create. + + * Makefile.in (realclean): OK, don't remove configure. + +Sat Sep 19 09:05:08 1992 Karl Berry (karl@hayley) + + * regex.c (PUSH_FAILURE_POINT, POP_FAILURE_POINT) [DEBUG]: keep + track of how many failure points we push and pop. + (re_match_2) [DEBUG]: declare variables for that, and print results. + (DEBUG_PRINT4): new macro. + + * regex.h (re_pattern_buffer): new field `longest_p' (to + eliminate backtracking if the user doesn't need it). + * regex.c (re_compile_pattern): initialize it (to 1). + (re_search_2): set it to zero if register information is not needed. + (re_match_2): if it's set, don't backtrack. + + * regex.c (re_search_2): update fastmap only after checking that + the pattern is anchored. + + * regex.c (re_match_2): do more debugging at maybe_pop_jump. + + * regex.c (re_search_2): cast result of TRANSLATE for use in + array subscript. + +Thu Sep 17 19:47:16 1992 Karl Berry (karl@geech.gnu.ai.mit.edu) + + * Version 0.11. + +Wed Sep 16 08:17:10 1992 Karl Berry (karl@hayley) + + * regex.c (INIT_FAIL_STACK): rewrite as statements instead of a + complicated comma expr, to avoid compiler warnings (and also + simplify). + (re_compile_fastmap, re_match_2): change callers. + + * regex.c (POP_FAILURE_POINT): cast pop of regstart and regend + to avoid compiler warnings. + + * regex.h (RE_NEWLINE_ORDINARY): remove this syntax bit, and + remove uses. + * regex.c (at_{beg,end}line_loc_p): go the last mile: remove + the RE_NEWLINE_ORDINARY case which made the ^ in \n^ be an anchor. + +Tue Sep 15 09:55:29 1992 Karl Berry (karl@hayley) + + * regex.c (at_begline_loc_p): new fn. + (at_endline_loc_p): simplify at_endline_op_p. + (regex_compile): in ^/$ cases, call the above. + + * regex.c (POP_FAILURE_POINT): rewrite the fn as a macro again, + as lord's profiling indicates the function is 20% of the time. + (re_match_2): callers changed. + + * configure.in (AC_MEMORY_H): remove, since we never use memcpy et al. + +Mon Sep 14 17:49:27 1992 Karl Berry (karl@hayley) + + * Makefile.in (makeargs): include MFLAGS. + +Sun Sep 13 07:41:45 1992 Karl Berry (karl@hayley) + + * regex.c (regex_compile): in \1..\9 case, make it always + invalid to use \<digit> if there is no preceding <digit>th subexpr. + * regex.h (RE_NO_MISSING_BK_REF): remove this syntax bit. + + * regex.c (regex_compile): remove support for invalid empty groups. + * regex.h (RE_NO_EMPTY_GROUPS): remove this syntax bit. + + * regex.c (FREE_VARIABLES) [!REGEX_MALLOC]: define as alloca (0), + to reclaim memory. + + * regex.h (RE_SYNTAX_POSIX_SED): don't bother with this. + +Sat Sep 12 13:37:21 1992 Karl Berry (karl@hayley) + + * README: incorporate emacs.diff. + + * regex.h (_RE_ARGS) [!__STDC__]: define as empty parens. + + * configure.in: add AC_ALLOCA. + + * Put test files in subdir test, documentation in subdir doc. + Adjust Makefile.in and configure.in accordingly. + +Thu Sep 10 10:29:11 1992 Karl Berry (karl@hayley) + + * regex.h (RE_SYNTAX_{POSIX_,}SED): new definitions. + +Wed Sep 9 06:27:09 1992 Karl Berry (karl@hayley) + + * Version 0.10. + +Tue Sep 8 07:32:30 1992 Karl Berry (karl@hayley) + + * xregex.texinfo: put the day of month into the date. + + * Makefile.in (realclean): remove Texinfo-generated files. + (distclean): remove empty sorted index files. + (clean): remove dvi files, etc. + + * configure.in: test for more Unix variants. + + * fileregex.c: new file. + Makefile.in (fileregex): new target. + + * iregex.c (main): move variable decls to smallest scope. + + * regex.c (FREE_VARIABLES): free reg_{,info_}dummy. + (re_match_2): check that the allocation for those two succeeded. + + * regex.c (FREE_VAR): replace FREE_NONNULL with this. + (FREE_VARIABLES): call it. + (re_match_2) [REGEX_MALLOC]: initialize all our vars to NULL. + + * tregress.c (do_match): generalize simple_match. + (SIMPLE_NONMATCH): new macro. + (SIMPLE_MATCH): change from routine. + + * Makefile.in (regex.texinfo): make file readonly, so we don't + edit it by mistake. + + * many files (re_default_syntax): rename to `re_syntax_options'; + call re_set_syntax instead of assigning to the variable where + possible. + +Mon Sep 7 10:12:16 1992 Karl Berry (karl@hayley) + + * syntax.skel: don't use prototypes. + + * {configure,Makefile}.in: new files. + + * regex.c: include <string.h> `#if USG || STDC_HEADERS'; remove + obsolete test for `POSIX', and test for BSRTING. + Include <strings.h> if we are not USG or STDC_HEADERS. + Do not include <unistd.h>. What did we ever need that for? + + * regex.h (RE_NO_EMPTY_ALTS): remove this. + (RE_SYNTAX_AWK): remove from here, too. + * regex.c (regex_compile): remove the check. + * xregex.texinfo (Alternation Operator): update. + * other.c (test_others): remove tests for this. + + * regex.h (RE_DUP_MAX): undefine if already defined. + + * regex.h: (RE_SYNTAX_POSIX*): redo to allow more operators, and + define new syntaxes with the minimal set. + + * syntax.skel (main): used sscanf instead of scanf. + + * regex.h (RE_SYNTAX_*GREP): new definitions from mike. + + * regex.c (regex_compile): initialize the upper bound of + intervals at the beginning of the interval, not the end. + (From pclink@qld.tne.oz.au.) + + * regex.c (handle_bar): rename to `handle_alt', for consistency. + + * regex.c ({store,insert}_{op1,op2}): new routines (except the last). + ({STORE,INSERT}_JUMP{,2}): macros to replace the old routines, + which took arguments in different orders, and were generally weird. + + * regex.c (PAT_PUSH*): rename to `BUF_PUSH*' -- we're not + appending info to the pattern! + +Sun Sep 6 11:26:49 1992 Karl Berry (karl@hayley) + + * regex.c (regex_compile): delete the variable + `following_left_brace', since we never use it. + + * regex.c (print_compiled_pattern): don't print the fastmap if + it's null. + + * regex.c (re_compile_fastmap): handle + `on_failure_keep_string_jump' like `on_failure_jump'. + + * regex.c (re_match_2): in `charset{,_not' case, cast the bit + count to unsigned, not unsigned char, in case we have a full + 32-byte bit list. + + * tregress.c (simple_match): remove. + (simple_test): rename as `simple_match'. + (simple_compile): print the error string if the compile failed. + + * regex.c (DO_RANGE): rewrite as a function, `compile_range', so + we can debug it. Change pattern characters to unsigned char + *'s, and change the range variable to an unsigned. + (regex_compile): change calls. + +Sat Sep 5 17:40:49 1992 Karl Berry (karl@hayley) + + * regex.h (_RE_ARGS): new macro to put in argument lists (if + ANSI) or omit them (if K&R); don't declare routines twice. + + * many files (obscure_syntax): rename to `re_default_syntax'. + +Fri Sep 4 09:06:53 1992 Karl Berry (karl@hayley) + + * GNUmakefile (extraclean): new target. + (realclean): delete the info files. + +Wed Sep 2 08:14:42 1992 Karl Berry (karl@hayley) + + * regex.h: doc fix. + +Sun Aug 23 06:53:15 1992 Karl Berry (karl@hayley) + + * regex.[ch] (re_comp): no const in the return type (from djm). + +Fri Aug 14 07:25:46 1992 Karl Berry (karl@hayley) + + * regex.c (DO_RANGE): declare variables as unsigned chars, not + signed chars (from jimb). + +Wed Jul 29 18:33:53 1992 Karl Berry (karl@claude.cs.umb.edu) + + * Version 0.9. + + * GNUmakefile (distclean): do not remove regex.texinfo. + (realclean): remove it here. + + * tregress.c (simple_test): initialize buf.buffer. + +Sun Jul 26 08:59:38 1992 Karl Berry (karl@hayley) + + * regex.c (push_dummy_failure): new opcode and corresponding + case in the various routines. Pushed at the end of + alternatives. + + * regex.c (jump_past_next_alt): rename to `jump_past_alt', for + brevity. + (no_pop_jump): rename to `jump'. + + * regex.c (regex_compile) [DEBUG]: terminate printing of pattern + with a newline. + + * NEWS: new file. + + * tregress.c (simple_{compile,match,test}): routines to simplify all + these little tests. + + * tregress.c: test for matching as much as possible. + +Fri Jul 10 06:53:32 1992 Karl Berry (karl@hayley) + + * Version 0.8. + +Wed Jul 8 06:39:31 1992 Karl Berry (karl@hayley) + + * regex.c (SIGN_EXTEND_CHAR): #undef any previous definition, as + ours should always work properly. + +Mon Jul 6 07:10:50 1992 Karl Berry (karl@hayley) + + * iregex.c (main) [DEBUG]: conditionalize the call to + print_compiled_pattern. + + * iregex.c (main): initialize buf.buffer to NULL. + * tregress (test_regress): likewise. + + * regex.c (alloca) [sparc]: #if on HAVE_ALLOCA_H instead. + + * tregress.c (test_regress): didn't have jla's test quite right. + +Sat Jul 4 09:02:12 1992 Karl Berry (karl@hayley) + + * regex.c (re_match_2): only REGEX_ALLOCATE all the register + vectors if the pattern actually has registers. + (match_end): new variable to avoid having to use best_regend[0]. + + * regex.c (IS_IN_FIRST_STRING): rename to FIRST_STRING_P. + + * regex.c: doc fixes. + + * tregess.c (test_regress): new fastmap test forwarded by rms. + + * tregress.c (test_regress): initialize the fastmap field. + + * tregress.c (test_regress): new test from jla that aborted + in re_search_2. + +Fri Jul 3 09:10:05 1992 Karl Berry (karl@hayley) + + * tregress.c (test_regress): add tests for translating charsets, + from kaoru. + + * GNUmakefile (common): add alloca.o. + * alloca.c: new file, copied from bison. + + * other.c (test_others): remove var `buf', since it's no longer used. + + * Below changes from ro@TechFak.Uni-Bielefeld.DE. + + * tregress.c (test_regress): initialize buf.allocated. + + * regex.c (re_compile_fastmap): initialize `succeed_n_p'. + + * GNUmakefile (regex): depend on $(common). + +Wed Jul 1 07:12:46 1992 Karl Berry (karl@hayley) + + * Version 0.7. + + * regex.c: doc fixes. + +Mon Jun 29 08:09:47 1992 Karl Berry (karl@fosse) + + * regex.c (pop_failure_point): change string vars to + `const char *' from `unsigned char *'. + + * regex.c: consolidate debugging stuff. + (print_partial_compiled_pattern): avoid enum clash. + +Mon Jun 29 07:50:27 1992 Karl Berry (karl@hayley) + + * xmalloc.c: new file. + * GNUmakefile (common): add it. + + * iregex.c (print_regs): new routine (from jimb). + (main): call it. + +Sat Jun 27 10:50:59 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu) + + * xregex.c (re_match_2): When we have accepted a match and + restored d from best_regend[0], we need to set dend + appropriately as well. + +Sun Jun 28 08:48:41 1992 Karl Berry (karl@hayley) + + * tregress.c: rename from regress.c. + + * regex.c (print_compiled_pattern): improve charset case to ease + byte-counting. + Also, don't distinguish between Emacs and non-Emacs + {not,}wordchar opcodes. + + * regex.c (print_fastmap): move here. + * test.c: from here. + * regex.c (print_{{partial,}compiled_pattern,double_string}): + rename from ..._printer. Change calls here and in test.c. + + * regex.c: create from xregex.c and regexinc.c for once and for + all, and change the debug fns to be extern, instead of static. + * GNUmakefile: remove traces of xregex.c. + * test.c: put in externs, instead of including regexinc.c. + + * xregex.c: move interactive main program and scanstring to iregex.c. + * iregex.c: new file. + * upcase.c, printchar.c: new files. + + * various doc fixes and other cosmetic changes throughout. + + * regexinc.c (compiled_pattern_printer): change variable name, + for consistency. + (partial_compiled_pattern_printer): print other info about the + compiled pattern, besides just the opcodes. + * xregex.c (regex_compile) [DEBUG]: print the compiled pattern + when we're done. + + * xregex.c (re_compile_fastmap): in the duplicate case, set + `can_be_null' and return. + Also, set `bufp->can_be_null' according to a new variable, + `path_can_be_null'. + Also, rewrite main while loop to not test `p != NULL', since + we never set it that way. + Also, eliminate special `can_be_null' value for the endline case. + (re_search_2): don't test for the special value. + * regex.h (struct re_pattern_buffer): remove the definition. + +Sat Jun 27 15:00:40 1992 Karl Berry (karl@hayley) + + * xregex.c (re_compile_fastmap): remove the `RE_' from + `REG_RE_MATCH_NULL_AT_END'. + Also, assert the fastmap in the pattern buffer is non-null. + Also, reset `succeed_n_p' after we've + paid attention to it, instead of every time through the loop. + Also, in the `anychar' case, only clear fastmap['\n'] if the + syntax says to, and don't return prematurely. + Also, rearrange cases in some semblance of a rational order. + * regex.h (REG_RE_MATCH_NULL_AT_END): remove the `RE_' from the name. + + * other.c: take bug reports from here. + * regress.c: new file for them. + * GNUmakefile (test): add it. + * main.c (main): new possible test. + * test.h (test_type): new value in enum. + +Thu Jun 25 17:37:43 1992 Karl Berry (karl@hayley) + + * xregex.c (scanstring) [test]: new function from jimb to allow some + escapes. + (main) [test]: call it (on the string, not the pattern). + + * xregex.c (main): make return type `int'. + +Wed Jun 24 10:43:03 1992 Karl Berry (karl@hayley) + + * xregex.c (pattern_offset_t): change to `int', for the benefit + of patterns which compile to more than 2^15 bytes. + + * xregex.c (GET_BUFFER_SPACE): remove spurious braces. + + * xregex.texinfo (Using Registers): put in a stub to ``document'' + the new function. + * regex.h (re_set_registers) [!__STDC__]: declare. + * xregex.c (re_set_registers): declare K&R style (also move to a + different place in the file). + +Mon Jun 8 18:03:28 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu) + + * regex.h (RE_NREGS): Doc fix. + + * xregex.c (re_set_registers): New function. + * regex.h (re_set_registers): Declaration for new function. + +Fri Jun 5 06:55:18 1992 Karl Berry (karl@hayley) + + * main.c (main): `return 0' instead of `exit (0)'. (From Paul Eggert) + + * regexinc.c (SIGN_EXTEND_CHAR): cast to unsigned char. + (extract_number, EXTRACT_NUMBER): don't bother to cast here. + +Tue Jun 2 07:37:53 1992 Karl Berry (karl@hayley) + + * Version 0.6. + + * Change copyrights to `1985, 89, ...'. + + * regex.h (REG_RE_MATCH_NULL_AT_END): new macro. + * xregex.c (re_compile_fastmap): initialize `can_be_null' to + `p==pend', instead of in the test at the top of the loop (as + it was, it was always being set). + Also, set `can_be_null'=1 if we would jump to the end of the + pattern in the `on_failure_jump' cases. + (re_search_2): check if `can_be_null' is 1, not nonzero. This + was the original test in rms' regex; why did we change this? + + * xregex.c (re_compile_fastmap): rename `is_a_succeed_n' to + `succeed_n_p'. + +Sat May 30 08:09:08 1992 Karl Berry (karl@hayley) + + * xregex.c (re_compile_pattern): declare `regnum' as `unsigned', + not `regnum_t', for the benefit of those patterns with more + than 255 groups. + + * xregex.c: rename `failure_stack' to `fail_stack', for brevity; + likewise for `match_nothing' to `match_null'. + + * regexinc.c (REGEX_REALLOCATE): take both the new and old + sizes, and copy only the old bytes. + * xregex.c (DOUBLE_FAILURE_STACK): pass both old and new. + * This change from Thorsten Ohl. + +Fri May 29 11:45:22 1992 Karl Berry (karl@hayley) + + * regexinc.c (SIGN_EXTEND_CHAR): define as `(signed char) c' + instead of relying on __CHAR_UNSIGNED__, to work with + compilers other than GCC. From Per Bothner. + + * main.c (main): change return type to `int'. + +Mon May 18 06:37:08 1992 Karl Berry (karl@hayley) + + * regex.h (RE_SYNTAX_AWK): typo in RE_RE_UNMATCHED... + +Fri May 15 10:44:46 1992 Karl Berry (karl@hayley) + + * Version 0.5. + +Sun May 3 13:54:00 1992 Karl Berry (karl@hayley) + + * regex.h (struct re_pattern_buffer): now it's just `regs_allocated'. + (REGS_UNALLOCATED, REGS_REALLOCATE, REGS_FIXED): new constants. + * xregex.c (regexec, re_compile_pattern): set the field appropriately. + (re_match_2): and use it. bufp can't be const any more. + +Fri May 1 15:43:09 1992 Karl Berry (karl@hayley) + + * regexinc.c: unconditionally include <sys/types.h>, first. + + * regex.h (struct re_pattern_buffer): rename + `caller_allocated_regs' to `regs_allocated_p'. + * xregex.c (re_compile_pattern): same change here. + (regexec): and here. + (re_match_2): reallocate registers if necessary. + +Fri Apr 10 07:46:50 1992 Karl Berry (karl@hayley) + + * regex.h (RE_SYNTAX{_POSIX,}_AWK): new definitions from Arnold. + +Sun Mar 15 07:34:30 1992 Karl Berry (karl at hayley) + + * GNUmakefile (dist): versionize regex.{c,h,texinfo}. + +Tue Mar 10 07:05:38 1992 Karl Berry (karl at hayley) + + * Version 0.4. + + * xregex.c (PUSH_FAILURE_POINT): always increment the failure id. + (DEBUG_STATEMENT) [DEBUG]: execute the statement even if `debug'==0. + + * xregex.c (pop_failure_point): if the saved string location is + null, keep the current value. + (re_match_2): at fail, test for a dummy failure point by + checking the restored pattern value, not string value. + (re_match_2): new case, `on_failure_keep_string_jump'. + (regex_compile): output this opcode in the .*\n case. + * regexinc.c (re_opcode_t): define the opcode. + (partial_compiled_pattern_pattern): add the new case. + +Mon Mar 9 09:09:27 1992 Karl Berry (karl at hayley) + + * xregex.c (regex_compile): optimize .*\n to output an + unconditional jump to the ., instead of pushing failure points + each time through the loop. + + * xregex.c (DOUBLE_FAILURE_STACK): compute the maximum size + ourselves (and correctly); change callers. + +Sun Mar 8 17:07:46 1992 Karl Berry (karl at hayley) + + * xregex.c (failure_stack_elt_t): change to `const char *', to + avoid warnings. + + * regex.h (re_set_syntax): declare this. + + * xregex.c (pop_failure_point) [DEBUG]: conditionally pass the + original strings and sizes; change callers. + +Thu Mar 5 16:35:35 1992 Karl Berry (karl at claude.cs.umb.edu) + + * xregex.c (regnum_t): new type for register/group numbers. + (compile_stack_elt_t, regex_compile): use it. + + * xregex.c (regexec): declare len as `int' to match re_search. + + * xregex.c (re_match_2): don't declare p1 twice. + + * xregex.c: change `while (1)' to `for (;;)' to avoid silly + compiler warnings. + + * regex.h [__STDC__]: use #if, not #ifdef. + + * regexinc.c (REGEX_REALLOCATE): cast the result of alloca to + (char *), to avoid warnings. + + * xregex.c (regerror): declare variable as const. + + * xregex.c (re_compile_pattern, re_comp): define as returning a const + char *. + * regex.h (re_compile_pattern, re_comp): likewise. + +Thu Mar 5 15:57:56 1992 Karl Berry (karl@hal) + + * xregex.c (regcomp): declare `syntax' as unsigned. + + * xregex.c (re_match_2): try to avoid compiler warnings about + unsigned comparisons. + + * GNUmakefile (test-xlc): new target. + + * regex.h (reg_errcode_t): remove trailing comma from definition. + * regexinc.c (re_opcode_t): likewise. + +Thu Mar 5 06:56:07 1992 Karl Berry (karl at hayley) + + * GNUmakefile (dist): add version numbers automatically. + (versionfiles): new variable. + (regex.{c,texinfo}): don't add version numbers here. + * regex.h: put in placeholder instead of the version number. + +Fri Feb 28 07:11:33 1992 Karl Berry (karl at hayley) + + * xregex.c (re_error_msg): declare const, since it is. + +Sun Feb 23 05:41:57 1992 Karl Berry (karl at fosse) + + * xregex.c (PAT_PUSH{,_2,_3}, ...): cast args to avoid warnings. + (regex_compile, regexec): return REG_NOERROR, instead + of 0, on success. + (boolean): define as char, and #define false and true. + * regexinc.c (STREQ): cast the result. + +Sun Feb 23 07:45:38 1992 Karl Berry (karl at hayley) + + * GNUmakefile (test-cc, test-hc, test-pcc): new targets. + + * regex.inc (extract_number, extract_number_and_incr) [DEBUG]: + only define if we are debugging. + + * xregex.c [_AIX]: do #pragma alloca first if necessary. + * regexinc.c [_AIX]: remove the #pragma from here. + + * regex.h (reg_syntax_t): declare as unsigned, and redo the enum + as #define's again. Some compilers do stupid things with enums. + +Thu Feb 20 07:19:47 1992 Karl Berry (karl at hayley) + + * Version 0.3. + + * xregex.c, regex.h (newline_anchor_match_p): rename to + `newline_anchor'; dumb idea to change the name. + +Tue Feb 18 07:09:02 1992 Karl Berry (karl at hayley) + + * regexinc.c: go back to original, i.e., don't include + <string.h> or define strchr. + * xregex.c (regexec): don't bother with adding characters after + newlines to the fastmap; instead, just don't use a fastmap. + * xregex.c (regcomp): set the buffer and fastmap fields to zero. + + * xregex.texinfo (GNU r.e. compiling): have to initialize more + than two fields. + + * regex.h (struct re_pattern_buffer): rename `newline_anchor' to + `newline_anchor_match_p', as we're back to two cases. + * xregex.c (regcomp, re_compile_pattern, re_comp): change + accordingly. + (re_match_2): at begline and endline, POSIX is not a special + case anymore; just check newline_anchor_match_p. + +Thu Feb 13 16:29:33 1992 Karl Berry (karl at hayley) + + * xregex.c (*empty_string*): rename to *null_string*, for brevity. + +Wed Feb 12 06:36:22 1992 Karl Berry (karl at hayley) + + * xregex.c (re_compile_fastmap): at endline, don't set fastmap['\n']. + (re_match_2): rewrite the begline/endline cases to take account + of the new field newline_anchor. + +Tue Feb 11 14:34:55 1992 Karl Berry (karl at hayley) + + * regexinc.c [!USG etc.]: include <strings.h> and define strchr + as index. + + * xregex.c (re_search_2): when searching backwards, declare `c' + as a char and use casts when using it as an array subscript. + + * xregex.c (regcomp): if REG_NEWLINE, set + RE_HAT_LISTS_NOT_NEWLINE. Set the `newline_anchor' field + appropriately. + (regex_compile): compile [^...] as matching a \n according to + the syntax bit. + (regexec): if doing REG_NEWLINE stuff, compile a fastmap and add + characters after any \n's to the newline. + * regex.h (RE_HAT_LISTS_NOT_NEWLINE): new syntax bit. + (struct re_pattern_buffer): rename `posix_newline' to + `newline_anchor', define constants for its values. + +Mon Feb 10 07:22:50 1992 Karl Berry (karl at hayley) + + * xregex.c (re_compile_fastmap): combine the code at the top and + bottom of the loop, as it's essentially identical. + +Sun Feb 9 10:02:19 1992 Karl Berry (karl at hayley) + + * xregex.texinfo (POSIX Translate Tables): remove this, as it + doesn't match the spec. + + * xregex.c (re_compile_fastmap): if we finish off a path, go + back to the top (to set can_be_null) instead of returning + immediately. + + * xregex.texinfo: changes from bob. + +Sat Feb 1 07:03:25 1992 Karl Berry (karl at hayley) + + * xregex.c (re_search_2): doc fix (from rms). + +Fri Jan 31 09:52:04 1992 Karl Berry (karl at hayley) + + * xregex.texinfo (GNU Searching): clarify the range arg. + + * xregex.c (re_match_2, at_endline_op_p): add extra parens to + get rid of GCC 2's (silly, IMHO) warning about && within ||. + + * xregex.c (common_op_match_empty_string_p): use + MATCH_NOTHING_UNSET_VALUE, not -1. + +Thu Jan 16 08:43:02 1992 Karl Berry (karl at hayley) + + * xregex.c (SET_REGS_MATCHED): only set the registers from + lowest to highest. + + * regexinc.c (MIN): new macro. + * xregex.c (re_match_2): only check min (num_regs, + regs->num_regs) when we set the returned regs. + + * xregex.c (re_match_2): set registers after the first + num_regs to -1 before we return. + +Tue Jan 14 16:01:42 1992 Karl Berry (karl at hayley) + + * xregex.c (re_match_2): initialize max (RE_NREGS, re_nsub + 1) + registers (from rms). + + * xregex.c, regex.h: don't abbreviate `19xx' to `xx'. + + * regexinc.c [!emacs]: include <sys/types.h> before <unistd.h>. + (from ro@thp.Uni-Koeln.DE). + +Thu Jan 9 07:23:00 1992 Karl Berry (karl at hayley) + + * xregex.c (*unmatchable): rename to `match_empty_string_p'. + (CAN_MATCH_NOTHING): rename to `REG_MATCH_EMPTY_STRING_P'. + + * regexinc.c (malloc, realloc): remove prototypes, as they can + cause clashes (from rms). + +Mon Jan 6 12:43:24 1992 Karl Berry (karl at claude.cs.umb.edu) + + * Version 0.2. + +Sun Jan 5 10:50:38 1992 Karl Berry (karl at hayley) + + * xregex.texinfo: bring more or less up-to-date. + * GNUmakefile (regex.texinfo): generate from regex.h and + xregex.texinfo. + * include.awk: new file. + + * xregex.c: change all calls to the fn extract_number_and_incr + to the macro. + + * xregex.c (re_match_2) [emacs]: in at_dot, use PTR_CHAR_POS + 1, + instead of bf_* and sl_*. Cast d to unsigned char *, to match + the declaration in Emacs' buffer.h. + [emacs19]: in before_dot, at_dot, and after_dot, likewise. + + * regexinc.c: unconditionally include <sys/types.h>. + + * regexinc.c (alloca) [!alloca]: Emacs config files sometimes + define this, so don't define it if it's already defined. + +Sun Jan 5 06:06:53 1992 Karl Berry (karl at fosse) + + * xregex.c (re_comp): fix type conflicts with regex_compile (we + haven't been compiling this). + + * regexinc.c (SIGN_EXTEND_CHAR): use `__CHAR_UNSIGNED__', not + `CHAR_UNSIGNED'. + + * regexinc.c (NULL) [!NULL]: define it (as zero). + + * regexinc.c (extract_number): remove the temporaries. + +Sun Jan 5 07:50:14 1992 Karl Berry (karl at hayley) + + * regex.h (regerror) [!__STDC__]: return a size_t, not a size_t *. + + * xregex.c (PUSH_FAILURE_POINT, ...): declare `destination' as + `char *' instead of `void *', to match alloca declaration. + + * xregex.c (regerror): use `size_t' for the intermediate values + as well as the return type. + + * xregex.c (regexec): cast the result of malloc. + + * xregex.c (regexec): don't initialize `private_preg' in the + declaration, as old C compilers can't do that. + + * xregex.c (main) [test]: declare printchar void. + + * xregex.c (assert) [!DEBUG]: define this to do nothing, and + remove #ifdef DEBUG's from around asserts. + + * xregex.c (re_match_2): remove error message when not debugging. + +Sat Jan 4 09:45:29 1992 Karl Berry (karl at hayley) + + * other.c: test the bizarre duplicate case in re_compile_fastmap + that I just noticed. + + * test.c (general_test): don't test registers beyond the end of + correct_regs, as well as regs. + + * xregex.c (regex_compile): at handle_close, don't assign to + *inner_group_loc if we didn't push a start_memory (because the + group number was too big). In fact, don't push or pop the + inner_group_offset in that case. + + * regex.c: rename to xregex.c, since it's not the whole thing. + * regex.texinfo: likewise. + * GNUmakefile: change to match. + + * regex.c [DEBUG]: only include <stdio.h> if debugging. + + * regexinc.c (SIGN_EXTEND_CHAR) [CHAR_UNSIGNED]: if it's already + defined, don't redefine it. + + * regex.c: define _GNU_SOURCE at the beginning. + * regexinc.c (isblank) [!isblank]: define it. + (isgraph) [!isgraph]: change conditional to this, and remove the + sequent stuff. + + * regex.c (regex_compile): add `blank' character class. + + * regex.c (regex_compile): don't use a uchar variable to loop + through all characters. + + * regex.c (regex_compile): at '[', improve logic for checking + that we have enough space for the charset. + + * regex.h (struct re_pattern_buffer): declare translate as char + * again. We only use it as an array subscript once, I think. + + * regex.c (TRANSLATE): new macro to cast the data character + before subscripting. + (num_internal_regs): rename to `num_regs'. + +Fri Jan 3 07:58:01 1992 Karl Berry (karl at hayley) + + * regex.h (struct re_pattern_buffer): declare `allocated' and + `used' as unsigned long, since these are never negative. + + * regex.c (compile_stack_element): rename to compile_stack_elt_t. + (failure_stack_element): similarly. + + * regexinc.c (TALLOC, RETALLOC): new macros to simplify + allocation of arrays. + + * regex.h (re_*) [__STDC__]: don't declare string args unsigned + char *; that makes them incompatible with string constants. + (struct re_pattern_buffer): declare the pattern and translate + table as unsigned char *. + * regex.c (most routines): use unsigned char vs. char consistently. + + * regex.h (re_compile_pattern): do not declare the length arg as + const. + * regex.c (re_compile_pattern): likewise. + + * regex.c (POINTER_TO_REG): rename to `POINTER_TO_OFFSET'. + + * regex.h (re_registers): declare `start' and `end' as + `regoff_t', instead of `int'. + + * regex.c (regexec): if either of the malloc's for the register + information fail, return failure. + + * regex.h (RE_NREGS): define this again, as 30 (from jla). + (RE_ALLOCATE_REGISTERS): remove this. + (RE_SYNTAX_*): remove it from definitions. + (re_pattern_buffer): remove `return_default_num_regs', add + `caller_allocated_regs'. + * regex.c (re_compile_pattern): clear no_sub and + caller_allocated_regs in the pattern. + (regcomp): set caller_allocated_regs. + (re_match_2): do all register allocation at the end of the + match; implement new semantics. + + * regex.c (MAX_REGNUM): new macro. + (regex_compile): at handle_open and handle_close, if the group + number is too large, don't push the start/stop memory. + +Thu Jan 2 07:56:10 1992 Karl Berry (karl at hayley) + + * regex.c (re_match_2): if the back reference is to a group that + never matched, then goto fail, not really_fail. Also, don't + test if the pattern can match the empty string. Why did we + ever do that? + (really_fail): this label no longer needed. + + * regexinc.c [STDC_HEADERS]: use only this to test if we should + include <stdlib.h>. + + * regex.c (DO_RANGE, regex_compile): translate in all cases + except the single character after a \. + + * regex.h (RE_AWK_CLASS_HACK): rename to + RE_BACKSLASH_ESCAPE_IN_LISTS. + * regex.c (regex_compile): change use. + + * regex.c (re_compile_fastmap): do not translate the characters + again; we already translated them at compilation. (From ylo@ngs.fi.) + + * regex.c (re_match_2): in case for at_dot, invert sense of + comparison and find the character number properly. (From + worley@compass.com.) + (re_match_2) [emacs]: remove the cases for before_dot and + after_dot, since there's no way to specify them, and the code + is wrong (judging from this change). + +Wed Jan 1 09:13:38 1992 Karl Berry (karl at hayley) + + * psx-{interf,basic,extend}.c, other.c: set `t' as the first + thing, so that if we run them in sucession, general_test's + kludge to see if we're doing POSIX tests works. + + * test.h (test_type): add `all_test'. + * main.c: add case for `all_test'. + + * regexinc.c (partial_compiled_pattern_printer, + double_string_printer): don't print anything if we're passed null. + + * regex.c (PUSH_FAILURE_POINT): do not scan for the highest and + lowest active registers. + (re_match_2): compute lowest/highest active regs at start_memory and + stop_memory. + (NO_{LOW,HIGH}EST_ACTIVE_REG): new sentinel values. + (pop_failure_point): return the lowest/highest active reg values + popped; change calls. + + * regex.c [DEBUG]: include <assert.h>. + (various routines) [DEBUG]: change conditionals to assertions. + + * regex.c (DEBUG_STATEMENT): new macro. + (PUSH_FAILURE_POINT): use it to increment num_regs_pushed. + (re_match_2) [DEBUG]: only declare num_regs_pushed if DEBUG. + + * regex.c (*can_match_nothing): rename to *unmatchable. + + * regex.c (re_match_2): at stop_memory, adjust argument reading. + + * regex.h (re_pattern_buffer): declare `can_be_null' as a 2-bit + bit field. + + * regex.h (re_pattern_buffer): declare `buffer' unsigned char *; + no, dumb idea. The pattern can have signed number. + + * regex.c (re_match_2): in maybe_pop_jump case, skip over the + right number of args to the group operators, and don't do + anything with endline if posix_newline is not set. + + * regex.c, regexinc.c (all the things we just changed): go back + to putting the inner group count after the start_memory, + because we need it in the on_failure_jump case in re_match_2. + But leave it after the stop_memory also, since we need it + there in re_match_2, and we don't have any way of getting back + to the start_memory. + + * regexinc.c (partial_compiled_pattern_printer): adjust argument + reading for start/stop_memory. + * regex.c (re_compile_fastmap, group_can_match_nothing): likewise. + +Tue Dec 31 10:15:08 1991 Karl Berry (karl at hayley) + + * regex.c (bits list routines): remove these. + (re_match_2): get the number of inner groups from the pattern, + instead of keeping track of it at start and stop_memory. + Put the count after the stop_memory, not after the + start_memory. + (compile_stack_element): remove `fixup_inner_group' member, + since we now put it in when we can compute it. + (regex_compile): at handle_open, don't push the inner group + offset, and at handle_close, don't pop it. + + * regex.c (level routines): remove these, and their uses in + regex_compile. This was another manifestation of having to find + $'s that were endlines. + + * regex.c (regexec): this does searching, not matching (a + well-disguised part of the standard). So rewrite to use + `re_search' instead of `re_match'. + * psx-interf.c (test_regexec): add tests to, uh, match. + + * regex.h (RE_TIGHT_ALT): remove this; nobody uses it. + * regex.c: remove the code that was supposed to implement it. + + * other.c (test_others): ^ and $ never match newline characters; + RE_CONTEXT_INVALID_OPS doesn't affect anchors. + + * psx-interf.c (test_regerror): update for new error messages. + + * psx-extend.c: it's now ok to have an alternative be just a $, + so remove all the tests which supposed that was invalid. + +Wed Dec 25 09:00:05 1991 Karl Berry (karl at hayley) + + * regex.c (regex_compile): in handle_open, don't skip over ^ and + $ when checking for an empty group. POSIX has changed the + grammar. + * psx-extend.c (test_posix_extended): thus, move (^$) tests to + valid section. + + * regexinc.c (boolean): move from here to test.h and regex.c. + * test files: declare verbose, omit_register_tests, and + test_should_match as boolean. + + * psx-interf.c (test_posix_c_interface): remove the `c_'. + * main.c: likewise. + + * psx-basic.c (test_posix_basic): ^ ($) is an anchor after + (before) an open (close) group. + + * regex.c (re_match_2): in endline, correct precedence of + posix_newline condition. + +Tue Dec 24 06:45:11 1991 Karl Berry (karl at hayley) + + * test.h: incorporate private-tst.h. + * test files: include test.h, not private-tst.h. + + * test.c (general_test): set posix_newline to zero if we are + doing POSIX tests (unfortunately, it's difficult to call + regcomp in this case, which is what we should really be doing). + + * regex.h (reg_syntax_t): make this an enumeration type which + defines the syntax bits; renames re_syntax_t. + + * regex.c (at_endline_op_p): don't preincrement p; then if it's + not an empty string op, we lose. + + * regex.h (reg_errcode_t): new enumeration type of the error + codes. + * regex.c (regex_compile): return that type. + + * regex.c (regex_compile): in [, initialize + just_had_a_char_class to false; somehow I had changed this to + true. + + * regex.h (RE_NO_CONSECUTIVE_REPEATS): remove this, since we + don't use it, and POSIX doesn't require this behavior anymore. + * regex.c (regex_compile): remove it from here. + + * regex.c (regex_compile): remove the no_op insertions for + verify_and_adjust_endlines, since that doesn't exist anymore. + + * regex.c (regex_compile) [DEBUG]: use printchar to print the + pattern, so unprintable bytes will print properly. + + * regex.c: move re_error_msg back. + * test.c (general_test): print the compile error if the pattern + was invalid. + +Mon Dec 23 08:54:53 1991 Karl Berry (karl at hayley) + + * regexinc.c: move re_error_msg here. + + * regex.c (re_error_msg): the ``message'' for success must be + NULL, to keep the interface to re_compile_pattern the same. + (regerror): if the msg is null, use "Success". + + * rename most test files for consistency. Change Makefile + correspondingly. + + * test.c (most routines): add casts to (unsigned char *) when we + call re_{match,search}{,_2}. + +Sun Dec 22 09:26:06 1991 Karl Berry (karl at hayley) + + * regex.c (re_match_2): declare string args as unsigned char * + again; don't declare non-pointer args const; declare the + pattern buffer const. + (re_match): likewise. + (re_search_2, re_search): likewise, except don't declare the + pattern const, since we make a fastmap. + * regex.h [__STDC__]: change prototypes. + + * regex.c (regex_compile): return an error code, not a string. + (re_err_list): new table to map from error codes to string. + (re_compile_pattern): return an element of re_err_list. + (regcomp): don't test all the strings. + (regerror): just use the list. + (put_in_buffer): remove this. + + * regex.c (equivalent_failure_points): remove this. + + * regex.c (re_match_2): don't copy the string arguments into + non-const pointers. We never alter the data. + + * regex.c (re_match_2): move assignment to `is_a_jump_n' out of + the main loop. Just initialize it right before we do + something with it. + + * regex.[ch] (re_match_2): don't declare the int parameters const. + +Sat Dec 21 08:52:20 1991 Karl Berry (karl at hayley) + + * regex.h (re_syntax_t): new type; declare to be unsigned + (previously we used int, but since we do bit operations on + this, unsigned is better, according to H&S). + (obscure_syntax, re_pattern_buffer): use that type. + * regex.c (re_set_syntax, regex_compile): likewise. + + * regex.h (re_pattern_buffer): new field `posix_newline'. + * regex.c (re_comp, re_compile_pattern): set to zero. + (regcomp): set to REG_NEWLINE. + * regex.h (RE_HAT_LISTS_NOT_NEWLINE): remove this (we can just + check `posix_newline' instead.) + + * regex.c (op_list_type, op_list, add_op): remove these. + (verify_and_adjust_endlines): remove this. + (pattern_offset_list_type, *pattern_offset* routines): and these. + These things all implemented the nonleading/nontrailing position + code, which was very long, had a few remaining problems, and + is no longer needed. So... + + * regexinc.c (STREQ): new macro to abbreviate strcmp(,)==0, for + brevity. Change various places in regex.c to use it. + + * regex{,inc}.c (enum regexpcode): change to a typedef + re_opcode_t, for brevity. + + * regex.h (re_syntax_table) [SYNTAX_TABLE]: remove this; it + should only be in regex.c, I think, since we don't define it + in this case. Maybe it should be conditional on !SYNTAX_TABLE? + + * regexinc.c (partial_compiled_pattern_printer): simplify and + distinguish the emacs/not-emacs (not)wordchar cases. + +Fri Dec 20 08:11:38 1991 Karl Berry (karl at hayley) + + * regexinc.c (regexpcode) [emacs]: only define the Emacs opcodes + if we are ifdef emacs. + + * regex.c (BUF_PUSH*): rename to PAT_PUSH*. + + * regex.c (regex_compile): in $ case, go back to essentially the + original code for deciding endline op vs. normal char. + (at_endline_op_p): new routine. + * regex.h (RE_ANCHORS_ONLY_AT_ENDS, RE_CONTEXT_INVALID_ANCHORS, + RE_REPEATED_ANCHORS_AWAY, RE_NO_ANCHOR_AT_NEWLINE): remove + these. POSIX has simplified the rules for anchors in draft + 11.2. + (RE_NEWLINE_ORDINARY): new syntax bit. + (RE_CONTEXT_INDEP_ANCHORS): change description to be compatible + with POSIX. + * regex.texinfo (Syntax Bits): remove the descriptions. + +Mon Dec 16 08:12:40 1991 Karl Berry (karl at hayley) + + * regex.c (re_match_2): in jump_past_next_alt, unconditionally + goto no_pop. The only register we were finding was one which + enclosed the whole alternative expression, not one around an + individual alternative. So we were never doing what we + thought we were doing, and this way makes (|a) against the + empty string fail. + + * regex.c (regex_compile): remove `highest_ever_regnum', and + don't restore regnum from the stack; just put it into a + temporary to put into the stop_memory. Otherwise, groups + aren't numbered consecutively. + + * regex.c (is_in_compile_stack): rename to + `group_in_compile_stack'; remove unnecessary test for the + stack being empty. + + * regex.c (re_match_2): in on_failure_jump, skip no_op's before + checking for the start_memory, in case we were called from + succeed_n. + +Sun Dec 15 16:20:48 1991 Karl Berry (karl at hayley) + + * regex.c (regex_compile): in duplicate case, use + highest_ever_regnum instead of regnum, since the latter is + reverted at stop_memory. + + * regex.c (re_match_2): in on_failure_jump, if the * applied to + a group, save the information for that group and all inner + groups (by making it active), even though we're not inside it + yet. + +Sat Dec 14 09:50:59 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_ITEM, POP_FAILURE_ITEM): new macros. + Use them instead of copying the stack manipulating a zillion + times. + + * regex.c (PUSH_FAILURE_POINT, pop_failure_point) [DEBUG]: save + and restore a unique identification value for each failure point. + + * regexinc.c (partial_compiled_pattern_printer): don't print an + extra / after duplicate commands. + + * regex.c (regex_compile): in back-reference case, allow a back + reference to register `regnum'. Otherwise, even `\(\)\1' + fails, since regnum is 1 at the back-reference. + + * regex.c (re_match_2): in fail, don't examine the pattern if we + restored to pend. + + * test_private.h: rename to private_tst.h. Change includes. + + * regex.c (extend_bits_list): compute existing size for realloc + in bytes, not blocks. + + * regex.c (re_match_2): in jump_past_next_alt, the for loop was + missing its (empty) statement. Even so, some register tests + still fail, although in a different way than in the previous change. + +Fri Dec 13 15:55:08 1991 Karl Berry (karl at hayley) + + * regex.c (re_match_2): in jump_past_next_alt, unconditionally + goto no_pop, since we weren't properly detecting if the + alternative matched something anyway. No, we need to not jump + to keep the register values correct; just change to not look at + register zero and not test RE_NO_EMPTY_ALTS (which is a + compile-time thing). + + * regex.c (SET_REGS_MATCHED): start the loop at 1, since we never + care about register zero until the very end. (I think.) + + * regex.c (PUSH_FAILURE_POINT, pop_failure_point): go back to + pushing and popping the active registers, instead of only doing + the registers before a group: (fooq|fo|o)*qbar against fooqbar + fails, since we restore back into the middle of group 1, yet it + isn't active, because the previous restore clobbered the active flag. + +Thu Dec 12 17:25:36 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_POINT): do not call + `equivalent_failure_points' after all; it causes the registers + to be ``wrong'' (according to POSIX), and an infinite loop on + `((a*)*)*' against `ab'. + + * regex.c (re_compile_fastmap): don't push `pend' on the failure + stack. + +Tue Dec 10 10:30:03 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_POINT): if pushing same failure point that + is on the top of the stack, fail. + (equivalent_failure_points): new routine. + + * regex.c (re_match_2): add debug statements for every opcode we + execute. + + * regex.c (regex_compile/handle_close): restore + `fixup_inner_group_count' and `regnum' from the stack. + +Mon Dec 9 13:51:15 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_POINT): declare `this_reg' as int, so + unsigned arithmetic doesn't happen when we don't want to save + the registers. + +Tue Dec 3 08:11:10 1991 Karl Berry (karl at hayley) + + * regex.c (extend_bits_list): divide size by bits/block. + + * regex.c (init_bits_list): remove redundant assignmen to + `bits_list_ptr'. + + * regexinc.c (partial_compiled_pattern_printer): don't do *p++ + twice in the same expr. + + * regex.c (re_match_2): at on_failure_jump, use the correct + pattern positions for getting the stuff following the start_memory. + + * regex.c (struct register_info): remove the bits_list for the + inner groups; make that a separate variable. + +Mon Dec 2 10:42:07 1991 Karl Berry (karl at hayley) + + * regex.c (PUSH_FAILURE_POINT): don't pass `failure_stack' as an + arg; change callers. + + * regex.c (PUSH_FAILURE_POINT): print items in order they are + pushed. + (pop_failure_point): likewise. + + * regex.c (main): prompt for the pattern and string. + + * regex.c (FREE_VARIABLES) [!REGEX_MALLOC]: declare as nothing; + remove #ifdefs from around calls. + + * regex.c (extract_number, extract_number_and_incr): declare static. + + * regex.c: remove the canned main program. + * main.c: new file. + * Makefile (COMMON): add main.o. + +Tue Sep 24 06:26:51 1991 Kathy Hargreaves (kathy at fosse) + + * regex.c (re_match_2): Made `pend' and `dend' not register variables. + Only set string2 to string1 if string1 isn't null. + Send address of p, d, regstart, regend, and reg_info to + pop_failure_point. + Put in more debug statements. + + * regex.c [debug]: Added global variable. + (DEBUG_*PRINT*): Only print if `debug' is true. + (DEBUG_DOUBLE_STRING_PRINTER): Changed DEBUG_STRING_PRINTER's + name to this. + Changed some comments. + (PUSH_FAILURE_POINT): Moved and added some debugging statements. + Was saving regstart on the stack twice instead of saving both + regstart and regend; remedied this. + [NUM_REGS_ITEMS]: Changed from 3 to 4, as now save lowest and + highest active registers instead of highest used one. + [NUM_NON_REG_ITEMS]: Changed name of NUM_OTHER_ITEMS to this. + (NUM_FAILURE_ITEMS): Use active registers instead of number 0 + through highest used one. + (re_match_2): Have pop_failure_point put things in the variables. + (pop_failure_point): Have it do what the fail case in re_match_2 + did with the failure stack, instead of throwing away the stuff + popped off. re_match_2 can ignore results when it doesn't + need them. + + +Thu Sep 5 13:23:28 1991 Kathy Hargreaves (kathy at fosse) + + * regex.c (banner): Changed copyright years to be separate. + + * regex.c [CHAR_UNSIGNED]: Put __ at both ends of this name. + [DEBUG, debug_count, *debug_p, DEBUG_PRINT_1, DEBUG_PRINT_2, + DEBUG_COMPILED_PATTERN_PRINTER ,DEBUG_STRING_PRINTER]: + defined these for debugging. + (extract_number): Added this (debuggable) routine version of + the macro EXTRACT_NUMBER. Ditto for EXTRACT_NUMBER_AND_INCR. + (re_compile_pattern): Set return_default_num_regs if the + syntax bit RE_ALLOCATE_REGISTERS is set. + [REGEX_MALLOC]: Renamed USE_ALLOCA to this. + (BUF_POP): Got rid of this, as don't ever use it. + (regex_compile): Made the type of `pattern' not be register. + If DEBUG, print the pattern to compile. + (re_match_2): If had a `$' in the pattern before a `^' then + don't record the `^' as an anchor. + Put (enum regexpcode) before references to b, as suggested + [RE_NO_BK_BRACES]: Changed RE_NO_BK_CURLY_BRACES to this. + (remove_pattern_offset): Removed this unused routine. + (PUSH_FAILURE_POINT): Changed to only save active registers. + Put in debugging statements. + (re_compile_fastmap): Made `pattern' not a register variable. + Use routine for extracting numbers instead of macro. + (re_match_2): Made `p', `mcnt' and `mcnt2' not register variables. + Added `num_regs_pushed' for debugging. + Only malloc registers if the syntax bit RE_ALLOCATE_REGISTERS is set. + Put in debug statements. + Put the macro NOTE_INNER_GROUP's code inline, as it was the + only called in one place. + For debugging, extract numbers using routines instead of macros. + In case fail: only restore pushed active registers, and added + debugging statements. + (pop_failure_point): Test for underfull stack. + (group_can_match_nothing, common_op_can_match_nothing): For + debugging, extract numbers using routines instead of macros. + (regexec): Changed formal parameters to not be prototypes. + Don't initialize `regs' or `private_preg' in their declarations. + +Tue Jul 23 18:38:36 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h [RE_CONTEX_INDEP_OPS]: Moved the anchor stuff out of + this bit. + [RE_UNMATCHED_RIGHT_PAREN_ORD]: Defined this bit. + [RE_CONTEXT_INVALID_ANCHORS]: Defined this bit. + [RE_CONTEXT_INDEP_ANCHORS]: Defined this bit. + Added RE_CONTEXT_INDEP_ANCHORS to all syntaxes which had + RE_CONTEXT_INDEP_OPS. + Took RE_ANCHORS_ONLY_AT_ENDS out of the POSIX basic syntax. + Added RE_UNMATCHED_RIGHT_PAREN_ORD to the POSIX extended + syntax. + Took RE_REPEATED_ANCHORS_AWAY out of the POSIX extended syntax. + Defined REG_NOERROR (which will probably have to go away again). + Changed the type `off_t' to `regoff_t'. + + * regex.c: Changed some commments. + (regex_compile): Added variable `had_an_endline' to keep track + of if hit a `$' since the beginning of the pattern or the last + alternative (if any). + Changed RE_CONTEXT_INVALID_OPS and RE_CONTEXT_INDEP_OPS to + RE_CONTEXT_INVALID_ANCHORS and RE_CONTEXT_INDEP_ANCHORS where + appropriate. + Put a `no_op' in the pattern if a repeat is only zero or one + times; in this case and if it is many times (whereupon a jump + backwards is pushed instead), keep track of the operator for + verify_and_adjust_endlines. + If RE_UNMATCHED_RIGHT_PAREN is set, make an unmatched + close-group operator match `)'. + Changed all error exits to exit (1). + (remove_pattern_offset): Added this routine, but don't use it. + (verify_and_adjust_endlines): At top of routine, if initialize + routines run out of memory, return true after setting + enough_memory false. + At end of endline, et al. case, don't set *p to no_op. + Repetition operators also set the level and active groups' + match statuses, unless RE_REPEATED_ANCHORS_AWAY is set. + (get_group_match_status): Put a return in front of call to get_bit. + (re_compile_fastmap): Changed is_a_succeed_n to a boolean. + If at end of pattern, then if the failure stack isn't empty, + go back to the failure point. + In *jump* case, only pop the stack if what's on top of it is + where we've just jumped to. + (re_search_2): Return -2 instead of val if val is -2. + (group_can_match_nothing, alternative_can_match_nothing, + common_op_can-match_nothing): Now pass in reg_info for the + `duplicate' case. + (re_match_2): Don't skip over the next alternative also if + empty alternatives aren't allowed. + In fail case, if failed to a backwards jump that's part of a + repetition loop, pop the current failure point and use the + next one. + (pop_failure_point): Check that there's as many register items + on the failure stack as the stack says there are. + (common_op_can_match_nothing): Added variables `ret' and + `reg_no' so can set reg_info for the group encountered. + Also break without doing anything if hit a no_op or the other + kinds of `endline's. + If not done already, set reg_info in start_memory case. + Put in no_pop_jump for an optimized succeed_n of zero repetitions. + In succeed_n case, if the number isn't zero, then return false. + Added `duplicate' case. + +Sat Jul 13 11:27:38 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (REG_NOERROR): Added this error code definition. + + * regex.c: Took some redundant parens out of macros. + (enum regexpcode): Added jump_past_next_alt. + Wrapped some macros in `do..while (0)'. + Changed some comments. + (regex_compile): Use `fixup_alt_jump' instead of `fixup_jump'. + Use `maybe_pop_jump' instead of `maybe_pop_failure_jump'. + Use `jump_past_next_alt' instead of `no_pop_jump' when at the + end of an alternative. + (re_match_2): Used REGEX_ALLOCATE for the registers stuff. + In stop_memory case: Add more boolean tests to see if the + group is in a loop. + Added jump_past_next_alt case, which doesn't jump over the + next alternative if the last one didn't match anything. + Unfortunately, to make this work with, e.g., `(a+?*|b)*' + against `bb', I also had to pop the alternative's failure + point, which in turn broke backtracking! + In fail case: Detect a dummy failure point by looking at + failure_stack.avail - 2, not stack[-2]. + (pop_failure_point): Only pop if the stack isn't empty; don't + give an error if it is. (Not sure yet this is correct.) + (group_can_match_nothing): Make it return a boolean instead of int. + Make it take an argument indicating the end of where it should look. + If find a group that can match nothing, set the pointer + argument to past the group in the pattern. + Took out cases which can share with alternative_can_match_nothing + and call common_op_can_match_nothing. + Took ++ out of switch, so could call common_op_can_match_nothing. + Wrote lots more for on_failure_jump case to handle alternatives. + Main loop now doesn't look for matching stop_memory, but + rather the argument END; return true if hit the matching + stop_memory; this way can call itself for inner groups. + (alternative_can_match_nothing): Added for alternatives. + (common_op_can_match_nothing): Added for previous two routines' + common operators. + (regerror): Returns a message saying there's no error if gets + sent REG_NOERROR. + +Wed Jul 3 10:43:15 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c: Removed unnecessary enclosing parens from several macros. + Put `do..while (0)' around a few. + Corrected some comments. + (INIT_FAILURE_STACK_SIZE): Deleted in favor of using + INIT_FAILURE_ALLOC. + (INIT_FAILURE_STACK, DOUBLE_FAILURE_STACK, PUSH_PATTERN_OP, + PUSH_FAILURE_POINT): Made routines of the same name (but with all + lowercase letters) into these macros, so could use `alloca' + when USE_ALLOCA is defined. The reason is stated below for + bits lists. Deleted analogous routines. + (re_compile_fastmap): Added variable void *destination for + PUSH_PATTERN_OP. + (re_match_2): Added variable void *destination for REGEX_REALLOCATE. + Used the failure stack macros in place of the routines. + Detected a dummy failure point by inspecting the failure stack's + (avail - 2)th element, not failure_stack.stack[-2]. This bug + arose when used the failure stack macros instead of the routines. + + * regex.c [USE_ALLOCA]: Put this conditional around previous + alloca stuff and defined these to work differently depending + on whether or not USE_ALLOCA is defined: + (REGEX_ALLOCATE): Uses either `alloca' or `malloc'. + (REGEX_REALLOCATE): Uses either `alloca' or `realloc'. + (INIT_BITS_LIST, EXTEND_BITS_LIST, SET_BIT_TO_VALUE): Defined + macro versions of routines with the same name (only with all + lowercase letters) so could use `alloc' in re_match_2. This + is to prevent core leaks when C-g is used in Emacs and to make + things faster and avoid storage fragmentation. These things + have to be macros because the results of `alloca' go away with + the routine by which it's called. + (BITS_BLOCK_SIZE, BITS_BLOCK, BITS_MASK): Moved to above the + above-mentioned macros instead of before the routines defined + below regex_compile. + (set_bit_to_value): Compacted some code. + (reg_info_type): Changed inner_groups field to be bits_list_type + so could be arbitrarily long and thus handle arbitrary nesting. + (NOTE_INNER_GROUP): Put `do...while (0)' around it so could + use as a statement. + Changed code to use bits lists. + Added variable void *destination for REGEX_REALLOCATE (whose call + is several levels in). + Changed variable name of `this_bit' to `this_reg'. + (FREE_VARIABLES): Only define and use if USE_ALLOCA is defined. + (re_match_2): Use REGEX_ALLOCATE instead of malloc. + Instead of setting INNER_GROUPS of reg_info to zero, have to + use INIT_BITS_LIST and return -2 (and free variables if + USE_ALLOCA isn't defined) if it fails. + +Fri Jun 28 13:45:07 1991 Karl Berry (karl at hayley) + + * regex.c (re_match_2): set value of `dend' when we restore `d'. + + * regex.c: remove declaration of alloca. + + * regex.c (MISSING_ISGRAPH): rename to `ISGRAPH_MISSING'. + + * regex.h [_POSIX_SOURCE]: remove these conditionals; always + define POSIX stuff. + * regex.c (_POSIX_SOURCE): change conditionals to use `POSIX' + instead. + +Sat Jun 1 16:56:50 1991 Kathy Hargreaves (kathy at hayley) + + * regex.*: Changed RE_CONTEXTUAL_* to RE_CONTEXT_*, + RE_TIGHT_VBAR to RE_TIGHT_ALT, RE_NEWLINE_OR to + RE_NEWLINE_ALT, and RE_DOT_MATCHES_NEWLINE to RE_DOT_NEWLINE. + +Wed May 29 09:24:11 1991 Karl Berry (karl at hayley) + + * regex.texinfo (POSIX Pattern Buffers): cross-reference the + correct node name (Match-beginning-of-line, not ..._line). + (Syntax Bits): put @code around all syntax bits. + +Sat May 18 16:29:58 1991 Karl Berry (karl at hayley) + + * regex.c (global): add casts to keep broken compilers from + complaining about malloc and realloc calls. + + * regex.c (isgraph) [MISSING_ISGRAPH]: change test to this, + instead of `#ifndef isgraph', since broken compilers can't + have both a macro and a symbol by the same name. + + * regex.c (re_comp, re_exec) [_POSIX_SOURCE]: do not define. + (regcomp, regfree, regexec, regerror) [_POSIX_SOURCE && !emacs]: + only define in this case. + +Mon May 6 17:37:04 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (re_search, re_search_2): Changed BUFFER to not be const. + + * regex.c (re_compile_pattern): `^' is in a leading position if + it precedes a newline. + (various routines): Added or changed header comments. + (double_pattern_offsets_list): Changed name from + `extend_pattern_offsets_list'. + (adjust_pattern_offsets_list): Changed return value from + unsigned to void. + (verify_and_adjust_endlines): Now returns `true' and `false' + instead of 1 and 0. + `$' is in a leading position if it follows a newline. + (set_bit_to_value, get_bit_value): Exit with error if POSITION < 0 + so now calling routines don't have to. + (init_failure_stack, inspect_failure_stack_top, + pop_failure_stack_top, push_pattern_op, double_failure_stack): + Now return value unsigned instead of boolean. + (re_search, re_search_2): Changed BUFP to not be const. + (re_search_2): Added variable const `private_bufp' to send to + re_match_2. + (push_failure_point): Made return value unsigned instead of boolean. + +Sat May 4 15:32:22 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (re_compile_fastmap): Added extern for this. + Changed some comments. + + * regex.c (re_compile_pattern): In case handle_bar: put invalid + pattern test before levels matching stuff. + Changed some commments. + Added optimizing test for detecting an empty alternative that + ends with a trailing '$' at the end of the pattern. + (re_compile_fastmap): Moved failure_stack stuff to before this + so could use it. Made its stack dynamic. + Made it return an int so that it could return -2 if its stack + couldn't be allocated. + Added to header comment (about the return values). + (init_failure_stack): Wrote so both re_match_2 and + re_compile_fastmap could use it similar stacks. + (double_failure_stack): Added for above reasons. + (push_pattern_op): Wrote for re_compile_fastmap. + (re_search_2): Now return -2 if re_compile_fastmap does. + (re_match_2): Made regstart and regend type failure_stack_element*. + (push_failure_point): Made pattern_place and string_place type + failure_stack_element*. + Call double_failure_stack now. + Return true instead of 1. + +Wed May 1 12:57:21 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c (remove_intervening_anchors): Avoid erroneously making + ops into no_op's by making them no_op only when they're beglines. + (verify_and_adjust_endlines): Don't make '$' a normal character + if it's before a newline. + Look for the endline op in *p, not p[1]. + (failure_stack_element): Added this declaration. + (failure_stack_type): Added this declaration. + (INIT_FAILURE_STACK_SIZE, FAILURE_STACK_EMPTY, + FAILURE_STACK_PTR_EMPTY, REMAINING_AVAIL_SLOTS): Added for + failure stack. + (FAILURE_ITEM_SIZE, PUSH_FAILURE_POINT): Deleted. + (FREE_VARIABLES): Now free failure_stack.stack instead of stackb. + (re_match_2): deleted variables `initial_stack', `stackb', + `stackp', and `stacke' and added `failure_stack' to replace them. + Replaced calls to PUSH_FAILURE_POINT with those to + push_failure_point. + (push_failure_point): Added for re_match_2. + (pop_failure_point): Rewrote to use a failure_stack_type of stack. + (can_match_nothing): Moved definition to below re_match_2. + (bcmp_translate): Moved definition to below re_match_2. + +Mon Apr 29 14:20:54 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c (enum regexpcode): Added codes endline_before_newline + and repeated_endline_before_newline so could detect these + types of endlines in the intermediate stages of a compiled + pattern. + (INIT_FAILURE_ALLOC): Renamed NFAILURES to this and set it to 5. + (BUF_PUSH): Put `do {...} while 0' around this. + (BUF_PUSH_2): Defined this to cut down on expansion of EXTEND_BUFFER. + (regex_compile): Changed some comments. + Now push endline_before_newline if find a `$' before a newline + in the pattern. + If a `$' might turn into an ordinary character, set laststart + to point to it. + In '^' case, if syntax bit RE_TIGHT_VBAR is set, then for `^' + to be in a leading position, it must be first in the pattern. + Don't have to check in one of the else clauses that it's not set. + If RE_CONTEXTUAL_INDEP_OPS isn't set but RE_ANCHORS_ONLY_AT_ENDS + is, make '^' a normal character if it isn't first in the pattern. + Can only detect at the end if a '$' after an alternation op is a + trailing one, so can't immediately detect empty alternatives + if a '$' follows a vbar. + Added a picture of the ``success jumps'' in alternatives. + Have to set bufp->used before calling verify_and_adjust_endlines. + Also do it before returning all error strings. + (remove_intervening_anchors): Now replaces the anchor with + repeated_endline_before_newline if it's an endline_before_newline. + (verify_and_adjust_endlines): Deleted SYNTAX parameter (could + use bufp's) and added GROUP_FORWARD_MATCH_STATUS so could + detect back references referring to empty groups. + Added variable `bend' to point past the end of the pattern buffer. + Added variable `previous_p' so wouldn't have to reinspect the + pattern buffer to see what op we just looked at. + Added endline_before_newline and repeated_endline_before_newline + cases. + When checking if in a trailing position, added case where '$' + has to be at the pattern's end if either of the syntax bits + RE_ANCHORS_ONLY_AT_ENDS or RE_TIGHT_VBAR are set. + Since `endline' can have the intermediate form `endline_in_repeat', + have to change it to `endline' if RE_REPEATED_ANCHORS_AWAY + isn't set. + Now disallow empty alternatives with trailing endlines in them + if RE_NO_EMPTY_ALTS is set. + Now don't make '$' an ordinary character if it precedes a newline. + Don't make it an ordinary character if it's before a newline. + Back references now affect the level matching something only if + they refer to nonempty groups. + (can_match_nothing): Now increment p1 in the switch, which + changes many of the cases, but makes the code more like what + it was derived from. + Adjust the return statement to reflect above. + (struct register_info): Made `can_match_nothing' field an int + instead of a bit so could have -1 in it if never set. + (MAX_FAILURE_ITEMS): Changed name from MAX_NUM_FAILURE_ITEMS. + (FAILURE_ITEM_SIZE): Defined how much space a failure items uses. + (PUSH_FAILURE_POINT): Changed variable `last_used_reg's name + to `highest_used_reg'. + Added variable `num_stack_items' and changed `len's name to + `stack_length'. + Test failure stack limit in terms of number of items in it, not + in terms of its length. rms' fix tested length against number + of items, which was a misunderstanding. + Use `realloc' instead of `alloca' to extend the failure stack. + Use shifts instead of multiplying by 2. + (FREE_VARIABLES): Free `stackb' instead of `initial_stack', as + might may have been reallocated. + (re_match_2): When mallocing `initial_stack', now multiply + the number of items wanted (what was there before) by + FAILURE_ITEM_SIZE. + (pop_failure_point): Need this procedure form of the macro of + the same name for debugging, so left it in and deleted the + macro. + (recomp): Don't free the pattern buffer's translate field. + +Mon Apr 15 09:47:47 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_DUP_MAX): Moved to outside of #ifdef _POSIX_SOURCE. + * regex.c (#include <sys/types.h>): Removed #ifdef _POSIX_SOURCE + condition. + (malloc, realloc): Made return type void* #ifdef __STDC__. + (enum regexpcode): Added endline_in_repeat for the compiler's + use; this never ends up on the final compiled pattern. + (INIT_PATTERN_OFFSETS_LIST_SIZE): Initial size for + pattern_offsets_list_type. + (pattern_offset_type): Type for pattern offsets. + (pattern_offsets_list_type): Type for keeping a list of + pattern offsets. + (anchor_list_type): Changed to above type. + (PATTERN_OFFSETS_LIST_PTR_FULL): Tests if a pattern offsets + list is full. + (ANCHOR_LIST_PTR_FULL): Changed to above. + (BIT_BLOCK_SIZE): Changed to BITS_BLOCK_SIZE and moved to + above bits list routines below regex_compile. + (op_list_type): Defined to be pattern_offsets_list_type. + (compile_stack_type): Changed offsets to be + pattern_offset_type instead of unsigned. + (pointer): Changed the name of all structure fields from this + to `avail'. + (COMPILE_STACK_FULL): Changed so the stack is full if `avail' + is equal to `size' instead of `size' - 1. + (GET_BUFFER_SPACE): Changed `>=' to `>' in the while statement. + (regex_compile): Added variable `enough_memory' so could check + that routine that verifies '$' positions could return an + allocation error. + (group_count): Deleted this variable, as `regnum' already does + this work. + (op_list): Added this variable to keep track of operations + needed for verifying '$' positions. + (anchor_list): Now initialize using routine + `init_pattern_offsets_list'. + Consolidated the three bits_list initializations. + In case '$': Instead of trying to go past constructs which can + follow '$', merely detect the special case where it has to be + at the pattern's end, fix up any fixup jumps if necessary, + record the anchor if necessary and add an `endline' (and + possibly two `no-op's) to the pattern; will call a routine at + the end to verify if it's in a valid position or not. + (init_pattern_offsets_list): Added to initialize pattern + offsets lists. + (extend_anchor_list): Renamed this extend_pattern_offsets_list + and renamed parameters and internal variables appropriately. + (add_pattern_offset): Added this routine which both + record_anchor_position and add_op call. + (adjust_pattern_offsets_list): Add this routine to adjust by + some increment all the pattern offsets a list of such after a + given position. + (record_anchor_position): Now send in offset instead of + calculating it and just call add_pattern_offset. + (adjust_anchor_list): Replaced by above routine. + (remove_intervening_anchors): If the anchor is an `endline' + then replace it with `endline_in_repeat' instead of `no_op'. + (add_op): Added this routine to call in regex_compile + wherever push something relevant to verifying '$' positions. + (verify_and_adjust_endlines): Added routine to (1) verify that + '$'s in a pattern buffer (represented by `endline') were in + valid positions and (2) whether or not they were anchors. + (BITS_BLOCK_SIZE): Renamed BIT_BLOCK_SIZE and moved to right + above bits list routines. + (BITS_BLOCK): Defines which array element of a bits list the + bit corresponding to a given position is in. + (BITS_MASK): Has a 1 where the bit (in a bit list array element) + for a given position is. + +Mon Apr 1 12:09:06 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c (BIT_BLOCK_SIZE): Defined this for using with + bits_list_type, abstracted from level_list_type so could use + for more things than just the level match status. + (regex_compile): Renamed `level_list' variable to + `level_match_status'. + Added variable `group_match_status' of type bits_list_type. + Kept track of whether or not for all groups any of them + matched other than the empty string, so detect if a back + reference in front of a '^' made it nonleading or not. + Do this by setting a match status bit for all active groups + whenever leave a group that matches other than the empty string. + Could detect which groups are active by going through the + stack each time, but or-ing a bits list of active groups with + a bits list of group match status is faster, so make a bits + list of active groups instead. + Have to check that '^' isn't in a leading position before + going to normal_char. + Whenever set level match status of the current level, also set + the match status of all active groups. + Increase the group count and make that group active whenever + open a group. + When close a group, only set the next level down if the + current level matches other than the empty string, and make + the current group inactive. + At a back reference, only set a level's match status if the + group to which the back reference refers matches other than + the empty string. + (init_bits_list): Added to initialize a bits list. + (get_level_value): Deleted this. (Made into + get_level_match_status.) + (extend_bits_list): Added to extend a bits list. (Made this + from deleted routine `extend_level_list'.) + (get_bit): Added to get a bit value from a bits list. (Made + this from deleted routine `get_level_value'.) + (set_bit_to_value): Added to set a bit in a bits list. (Made + this from deleted routine `set_level_value'.) + (get_level_match_status): Added this to get the match status + of a given level. (Made from get_level_value.) + (set_this_level, set_next_lower_level): Made all routines + which set bits extend the bits list if necessary, thus they + now return an unsigned value to indicate whether or not the + reallocation failed. + (increase_level): No longer extends the level list. + (make_group_active): Added to mark as active a given group in + an active groups list. + (make_group_inactive): Added to mark as inactive a given group + in an active groups list. + (set_match_status_of_active_groups): Added to set the match + status of all currently active groups. + (get_group_match_status): Added to get a given group's match status. + (no_levels_match_anything): Removed the paramenter LEVEL. + (PUSH_FAILURE_POINT): Added rms' bug fix and changed RE_NREGS + to num_internal_regs. + +Sun Mar 31 09:04:30 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_ANCHORS_ONLY_AT_ENDS): Added syntax so could + constrain '^' and '$' to only be anchors if at the beginning + and end of the pattern. + (RE_SYNTAX_POSIX_BASIC): Added the above bit. + + * regex.c (enum regexcode): Changed `unused' to `no_op'. + (this_and_lower_levels_match_nothing): Deleted forward reference. + (regex_compile): case '^': if the syntax bit RE_ANCHORS_ONLY_AT_ENDS + is set, then '^' is only an anchor if at the beginning of the + pattern; only record anchor position if the syntax bit + RE_REPEATED_ANCHORS_AWAY is set; the '^' is a normal char if + the syntax bit RE_ANCHORS_ONLY_AT_END is set and we're not at + the beginning of the pattern (and neither RE_CONTEXTUAL_INDEP_OPS + nor RE_CONTEXTUAL_INDEP_OPS syntax bits are set). + Only adjust the anchor list if the syntax bit + RE_REPEATED_ANCHORS_AWAY is set. + + * regex.c (level_list_type): Use to detect when '^' is + in a leading position. + (regex_compile): Added level_list_type level_list variable in + which we keep track of whether or not a grouping level (in its + current or most recent incarnation) matches anything besides the + empty string. Set the bit for the i-th level when detect it + should match something other than the empty string and the bit + for the (i-1)-th level when leave the i-th group. Clear all + bits for the i-th and higher levels if none of 0--(i - 1)-th's + bits are set when encounter an alternation operator on that + level. If no levels are set when hit a '^', then it is in a + leading position. We keep track of which level we're at by + increasing a variable current_level whenever we encounter an + open-group operator and decreasing it whenever we encounter a + close-group operator. + Have to adjust the anchor list contents whenever insert + something ahead of them (such as on_failure_jump's) in the + pattern. + (adjust_anchor_list): Adjusts the offsets in an anchor list by + a given increment starting at a given start position. + (get_level_value): Returns the bit setting of a given level. + (set_level_value): Sets the bit of a given level to a given value. + (set_this_level): Sets (to 1) the bit of a given level. + (set_next_lower_level): Sets (to 1) the bit of (LEVEL - 1) for a + given LEVEL. + (clear_this_and_higher_levels): Clears the bits for a given + level and any higher levels. + (extend_level_list): Adds sizeof(unsigned) more bits to a level list. + (increase_level): Increases by 1 the value of a given level variable. + (decrease_level): Decreases by 1 the value of a given level variable. + (lower_levels_match_nothing): Checks if any levels lower than + the given one match anything. + (no_levels_match_anything): Checks if any levels match anything. + (re_match_2): At case wordbeg: before looking at d-1, check that + we're not at the string's beginning. + At case wordend: Added some illuminating parentheses. + +Mon Mar 25 13:58:51 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_ANCHOR_AT_NEWLINE): Changed syntax bit name + from RE_ANCHOR_NOT_NEWLINE because an anchor never matches the + newline itself, just the empty string either before or after it. + (RE_REPEATED_ANCHORS_AWAY): Added this syntax bit for ignoring + anchors inside groups which are operated on by repetition + operators. + (RE_DOT_MATCHES_NEWLINE): Added this bit so the match-any-character + operator could match a newline when it's set. + (RE_SYNTAX_POSIX_BASIC): Set RE_DOT_MATCHES_NEWLINE in this. + (RE_SYNTAX_POSIX_EXTENDED): Set RE_DOT_MATCHES_NEWLINE and + RE_REPEATED_ANCHORS_AWAY in this. + (regerror): Changed prototypes to new POSIX spec. + + * regex.c (anchor_list_type): Added so could null out anchors inside + repeated groups. + (ANCHOR_LIST_PTR_FULL): Added for above type. + (compile_stack_element): Changed name from stack_element. + (compile_stack_type): Changed name from compile_stack. + (INIT_COMPILE_STACK_SIZE): Changed name from INIT_STACK_SIZE. + (COMPILE_STACK_EMPTY): Changed name from STACK_EMPTY. + (COMPILE_STACK_FULL): Changed name from STACK_FULL. + (regex_compile): Changed SYNTAX parameter to non-const. + Changed variable name `stack' to `compile_stack'. + If syntax bit RE_REPEATED_ANCHORS_AWAY is set, then naively put + anchors in a list when encounter them and then set them to + `unused' when detect they are within a group operated on by a + repetition operator. Need something more sophisticated than + this, as they should only get set to `unused' if they are in + positions where they would be anchors. Also need a better way to + detect contextually invalid anchors. + Changed some commments. + (is_in_compile_stack): Changed name from `is_in_stack'. + (extend_anchor_list): Added to do anchor stuff. + (record_anchor_position): Added to do anchor stuff. + (remove_intervening_anchors): Added to do anchor stuff. + (re_match_2): Now match a newline with the match-any-character + operator if RE_DOT_MATCHES_NEWLINE is set. + Compacted some code. + (regcomp): Added new POSIX newline information to the header + commment. + If REG_NEWLINE cflag is set, then now unset RE_DOT_MATCHES_NEWLINE + in syntax. + (put_in_buffer): Added to do new POSIX regerror spec. Called + by regerror. + (regerror): Changed to take a pattern buffer, error buffer and + its size, and return type `size_t', the size of the full error + message, and the first ERRBUF_SIZE - 1 characters of the full + error message in the error buffer. + +Wed Feb 27 16:38:33 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (#include <sys/types.h>): Removed this as new POSIX + standard has the user include it. + (RE_SYNTAX_POSIX_BASIC and RE_SYNTAX_POSIX_EXTENDED): Removed + RE_HAT_LISTS_NOT_NEWLINE as new POSIX standard has the cflag + REG_NEWLINE now set this. Similarly, added syntax bit + RE_ANCHOR_NOT_NEWLINE as this is now unset by REG_NEWLINE. + (RE_SYNTAX_POSIX_BASIC): Removed syntax bit + RE_NO_CONSECUTIVE_REPEATS as POSIX now allows them. + + * regex.c (#include <sys/types.h>): Added this as new POSIX + standard has the user include it instead of us putting it in + regex.h. + (extern char *re_syntax_table): Made into an extern so the + user could allocate it. + (DO_RANGE): If don't find a range end, now goto invalid_range_end + instead of unmatched_left_bracket. + (regex_compile): Made variable SYNTAX non-const.???? + Reformatted some code. + (re_compile_fastmap): Moved is_a_succeed_n's declaration to + inner braces. + Compacted some code. + (SET_NEWLINE_FLAG): Removed and put inline. + (regcomp): Made variable `syntax' non-const so can unset + RE_ANCHOR_NOT_NEWLINE syntax bit if cflag RE_NEWLINE is set. + If cflag RE_NEWLINE is set, set the RE_HAT_LISTS_NOT_NEWLINE + syntax bit and unset RE_ANCHOR_NOT_NEWLINE one of `syntax'. + +Wed Feb 20 16:33:38 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_CONSECUTIVE_REPEATS): Changed name from + RE_NO_CONSEC_REPEATS. + (REG_ENESTING): Deleted this POSIX return value, as the stack + is now unbounded. + (struct re_pattern_buffer): Changed some comments. + (re_compile_pattern): Changed a comment. + Deleted check on stack upper bound and corresponding error. + Now when there's no interval contents and it's the end of the + pattern, go to unmatched_left_curly_brace instead of end_of_pattern. + Removed nesting_too_deep error, as the stack is now unbounded. + (regcomp): Removed REG_ENESTING case, as the stack is now unbounded. + (regerror): Removed REG_ENESTING case, as the stack is now unbounded. + + * regex.c (MAX_STACK_SIZE): Deleted because don't need upper + bound on array indexed with an unsigned number. + +Sun Feb 17 15:50:24 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h: Changed and added some comments. + + * regex.c (init_syntax_once): Made `_' a word character. + (re_compile_pattern): Added a comment. + (re_match_2): Redid header comment. + (regexec): With header comment about PMATCH, corrected and + removed details found regex.h, adding a reference. + +Fri Feb 15 09:21:31 1991 Kathy Hargreaves (kathy at hayley) + + * regex.c (DO_RANGE): Removed argument parentheses. + Now get untranslated range start and end characters and set + list bits for the translated (if at all) versions of them and + all characters between them. + (re_match_2): Now use regs->num_regs instead of num_regs_wanted + wherever possible. + (regcomp): Now build case-fold translate table using isupper + and tolower facilities so will work on foreign language characters. + +Sat Feb 9 16:40:03 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_HAT_LISTS_NOT_NEWLINE): Changed syntax bit name + from RE_LISTS_NOT_NEWLINE as it only affects nonmatching lists. + Changed all references to the match-beginning-of-string + operator to match-beginning-of-line operator, as this is what + it does. + (RE_NO_CONSEC_REPEATS): Added this syntax bit. + (RE_SYNTAX_POSIX_BASIC): Added above bit to this. + (REG_PREMATURE_END): Changed name to REG_EEND. + (REG_EXCESS_NESTING): Changed name to REG_ENESTING. + (REG_TOO_BIG): Changed name to REG_ESIZE. + (REG_INVALID_PREV_RE): Deleted this return POSIX value. + Added and changed some comments. + + * regex.c (re_compile_pattern): Now sets the pattern buffer's + `return_default_num_regs' field. + (typedef struct stack_element, stack_type, INIT_STACK_SIZE, + MAX_STACK_SIZE, STACK_EMPTY, STACK_FULL): Added for regex_compile. + (INIT_BUF_SIZE): Changed value from 28 to 32. + (BUF_PUSH): Changed name from BUFPUSH. + (MAX_BUF_SIZE): Added so could use in many places. + (IS_CHAR_CLASS_STRING): Replaced is_char_class with this. + (regex_compile): Added a stack which could grow dynamically + and which has struct elements. + Go back to initializing `zero_times_ok' and `many_time_ok' to + 0 and |=ing them inside the loop. + Now disallow consecutive repetition operators if the syntax + bit RE_NO_CONSEC_REPEATS is set. + Now detect trailing backslash when the compiler is expecting a + `?' or a `+'. + Changed calls to GET_BUFFER_SPACE which asked for 6 to ask for + 3, as that's all they needed. + Now check for trailing backslash inside lists. + Now disallow an empty alternative right before an end-of-line + operator. + Now get buffer space before leaving space for a fixup jump. + Now check if at pattern end when at open-interval operator. + Added some comments. + Now check if non-interval repetition operators follow an + interval one if the syntax bit RE_NO_CONSEC_REPEATS is set. + Now only check if what precedes an interval repetition + operator isn't a regular expression which matches one + character if the syntax bit RE_NO_CONSEC_REPEATS is set. + Now return "Unmatched [ or [^" instead of "Unmatched [". + (is_in_stack): Added to check if a given register number is in + the stack. + (re_match_2): If initial variable allocations fail, return -2, + instead of -1. + Now set reg's `num_regs' field when allocating regs. + Now before allocating them, free regs->start and end if they + aren't NULL and return -2 if either allocation fails. + Now use regs->num_regs instead of num_regs_wanted to control + regs loops. + Now increment past the newline when matching it with an + end-of-line operator. + (recomp): Added to the header comment. + Now return REG_ESUBREG if regex_compile returns "Unmatched [ + or [^" instead of doing so if it returns "Unmatched [". + Now return REG_BADRPT if in addition to returning "Missing + preceding regular expression", regex_compile returns "Invalid + preceding regular expression". + Now return new return value names (see regex.h changes). + (regexec): Added to header comment. + Initialize regs structure. + Now match whole string. + Now always free regs.start and regs.end instead of just when + the string matched. + (regerror): Now return "Regex error: Unmatched [ or [^.\n" + instead of "Regex error: Unmatched [.\n". + Now return "Regex error: Preceding regular expression either + missing or not simple.\n" instead of "Regex error: Missing + preceding regular expression.\n". + Removed REG_INVALID_PREV_RE case (it got subsumed into the + REG_BADRPT case). + +Thu Jan 17 09:52:35 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h: Changed a comment. + + * regex.c: Changed and added large header comments. + (re_compile_pattern): Now if detect that `laststart' for an + interval points to a byte code for a regular expression which + matches more than one character, make it an internal error. + (regerror): Return error message, don't print it. + +Tue Jan 15 15:32:49 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (regcomp return codes): Added GNU ones. + Updated some comments. + + * regex.c (DO_RANGE): Changed `obscure_syntax' to `syntax'. + (regex_compile): Added `following_left_brace' to keep track of + where pseudo interval following a valid interval starts. + Changed some instances that returned "Invalid regular + expression" to instead return error strings coinciding with + POSIX error codes. + Changed some comments. + Now consider only things between `[:' and `:]' to be possible + character class names. + Now a character class expression can't end a pattern; at + least a `]' must close the list. + Now if the syntax bit RE_NO_BK_CURLY_BRACES is set, then a + valid interval must be followed by yet another to get an error + for preceding an interval (in this case, the second one) with + a regular expression that matches more than one character. + Now if what follows a valid interval begins with a open + interval operator but doesn't begin a valid interval, then set + following_left_bracket to it, put it in C and go to + normal_char label. + Added some comments. + Return "Invalid character class name" instead of "Invalid + character class". + (regerror): Return messages for all POSIX error codes except + REG_ECOLLATE and REG_NEWLINE, along with all GNU error codes. + Added `break's after all cases. + (main): Call re_set_syntax instead of setting `obscure_syntax' + directly. + +Sat Jan 12 13:37:59 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (Copyright): Updated date. + (#include <sys/types.h>): Include unconditionally. + (RE_CANNOT_MATCH_NEWLINE): Deleted this syntax bit. + (RE_SYNTAX_POSIX_BASIC, RE_SYNTAX_POSIX_EXTENDED): Removed + setting the RE_ANCHOR_NOT_NEWLINE syntax bit from these. + Changed and added some comments. + (struct re_pattern_buffer): Changed some flags from chars to bits. + Added field `syntax'; holds which syntax pattern was compiled with. + Added bit flag `return_default_num_regs'. + (externs for GNU and Berkeley UNIX routines): Added `const's to + parameter types to be compatible with POSIX. + (#define const): Added to support old C compilers. + + * regex.c (Copyright): Updated date. + (enum regexpcode): Deleted `newline'. + (regex_compile): Renamed re_compile_pattern to this, added a + syntax parameter so it can set the pattern buffer's `syntax' + field. + Made `pattern', and `size' `const's so could pass to POSIX + interface routines; also made `const' whatever interval + variables had to be to make this work. + Changed references to `obscure_syntax' to new parameter `syntax'. + Deleted putting `newline' in buffer when see `\n'. + Consider invalid character classes which have nothing wrong + except the character class name; if so, return character-class error. + (is_char_class): Added routine for regex_compile. + (re_compile_pattern): added a new one which calls + regex_compile with `obscure_syntax' as the actual parameter + for the formal `syntax'. + Gave this the old routine's header comments. + Made `pattern', and `size' `const's so could use POSIX interface + routine parameters. + (re_search, re_search_2, re_match, re_match_2): Changed + `pbufp' to `bufp'. + (re_search_2, re_match_2): Changed `mstop' to `stop'. + (re_search, re_search_2): Made all parameters except `regs' + `const's so could use POSIX interface routines parameters. + (re_search_2): Added private copies of `const' parameters so + could change their values. + (re_match_2): Made all parameters except `regs' `const's so + could use POSIX interface routines parameters. + Changed `size1' and `size2' parameters to `size1_arg' and + `size2_arg' and so could change; added local `size1' and + `size2' and set to these. + Added some comments. + Deleted `newline' case. + `begline' can also possibly match if `d' contains a newline; + if it does, we have to increment d to point past the newline. + Replaced references to `obscure_syntax' with `bufp->syntax'. + (re_comp, re_exec): Made parameter `s' a `const' so could use POSIX + interface routines parameters. + Now call regex_compile, passing `obscure_syntax' via the + `syntax' parameter. + (re_exec): Made local `len' a `const' so could pass to re_search. + (regcomp): Added header comment. + Added local `syntax' to set and pass to regex_compile rather + than setting global `obscure_syntax' and passing it. + Call regex_compile with its `syntax' parameter rather than + re_compile_pattern. + Return REG_ECTYPE if character-class error. + (regexec): Don't initialize `regs' to anything. + Made `private_preg' a nonpointer so could set to what the + constant `preg' points. + Initialize `private_preg's `return_default_num_regs' field to + zero because want to return `nmatch' registers, not however + many there are subexpressions in the pattern. + Also test if `nmatch' > 0 to see if should pass re_match `regs'. + +Tue Jan 8 15:57:17 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (struct re_pattern_buffer): Reworded comment. + + * regex.c (EXTEND_BUFFER): Also reset beg_interval. + (re_search_2): Return val if val = -2. + (NUM_REG_ITEMS): Listed items in comment. + (NUM_OTHER_ITEMS): Defined this for using in > 1 definition. + (MAX_NUM_FAILURE_ITEMS): Replaced `+ 2' with NUM_OTHER_ITEMS. + (NUM_FAILURE_ITEMS): As with definition above and added to + comment. + (PUSH_FAILURE_POINT): Replaced `* 2's with `<< 1's. + (re_match_2): Test with equality with 1 to see pbufp->bol and + pbufp->eol are set. + +Fri Jan 4 15:07:22 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (struct re_pattern_buffer): Reordered some fields. + Updated some comments. + Added not_bol and not_eol fields. + (extern regcomp, regexec, regerror): Added return types. + (extern regfree): Added `extern'. + + * regex.c (min): Deleted unused macro. + (re_match_2): Compacted some code. + Removed call to macro `min' from `for' loop. + Fixed so unused registers get filled with -1's. + Fail if the pattern buffer's `not_bol' field is set and + encounter a `begline'. + Fail if the pattern buffer's `not_eol' field is set and + encounter a `endline'. + Deleted redundant check for empty stack in fail case. + Don't free pattern buffer's components in re_comp. + (regexec): Initialize variable regs. + Added `private_preg' pattern buffer so could set `not_bol' and + `not_eol' fields and hand to re_match. + Deleted naive attempt to detect anchors. + Set private pattern buffer's `not_bol' and `not_eol' fields + according to eflags value. + `nmatch' must also be > 0 for us to bother allocating + registers to send to re_match and filling pmatch + with their results after the call to re_match. + Send private pattern buffer instead of argument to re_match. + If use the registers, always free them and then set them to NULL. + (regerror): Added this Posix routine. + (regfree): Added this Posix routine. + +Tue Jan 1 15:02:45 1991 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NREGS): Deleted this definition, as now the user + can choose how many registers to have. + (REG_NOTBOL, REG_NOTEOL): Defined these Posix eflag bits. + (REG_NOMATCH, REG_BADPAT, REG_ECOLLATE, REG_ECTYPE, + REG_EESCAPE, REG_ESUBREG, REG_EBRACK, REG_EPAREN, REG_EBRACE, + REG_BADBR, REG_ERANGE, REG_ESPACE, REG_BADRPT, REG_ENEWLINE): + Defined these return values for Posix's regcomp and regexec. + Updated some comments. + (struct re_pattern_buffer): Now typedef this as regex_t + instead of the other way around. + (struct re_registers): Added num_regs field. Made start and + end fields pointers to char instead of fixed size arrays. + (regmatch_t): Added this Posix register type. + (regcomp, regexec, regerror, regfree): Added externs for these + Posix routines. + + * regex.c (enum boolean): Typedefed this. + (re_pattern_buffer): Reformatted some comments. + (re_compile_pattern): Updated some comments. + Always push start_memory and its attendant number whenever + encounter a group, not just when its number is less than the + previous maximum number of registers; same for stop_memory. + Get 4 bytes of buffer space instead of 2 when pushing a + set_number_at. + (can_match_nothing): Added this to elaborate on and replace + code in re_match_2. + (reg_info_type): Made can_match_nothing field a bit instead of int. + (MIN): Added for re_match_2. + (re_match_2 macros): Changed all `for' loops which used + RE_NREGS to now use num_internal_regs as upper bounds. + (MAX_NUM_FAILURE_ITEMS): Use num_internal_regs instead of RE_NREGS. + (POP_FAILURE_POINT): Added check for empty stack. + (FREE_VARIABLES): Added this to free (and set to NULL) + variables allocated in re_match_2. + (re_match_2): Rearranged parameters to be in order. + Added variables num_regs_wanted (how many registers the user wants) + and num_internal_regs (how many groups there are). + Allocated initial_stack, regstart, regend, old_regstart, + old_regend, reginfo, best_regstart, and best_regend---all + which used to be fixed size arrays. Free them all and return + -1 if any fail. + Free above variables if starting position pos isn't valid. + Changed all `for' loops which used RE_NREGS to now use + num_internal_regs as upper bounds---except for the loops which + fill regs; then use num_regs_wanted. + Allocate regs if the user has passed it and wants more than 0 + registers filled. + Set regs->start[i] and regs->end[i] to -1 if either + regstart[i] or regend[i] equals -1, not just the first. + Free allocated variables before returning. + Updated some comments. + (regcomp): Return REG_ESPACE, REG_BADPAT, REG_EPAREN when + appropriate. + Free translate array. + (regexec): Added this Posix interface routine. + +Mon Dec 24 14:21:13 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: If _POSIX_SOURCE is defined then #include <sys/types.h>. + Added syntax bit RE_CANNOT_MATCH_NEWLINE. + Defined Posix cflags: REG_EXTENDED, REG_NEWLINE, REG_ICASE, and + REG_NOSUB. + Added fields re_nsub and no_sub to struct re_pattern_buffer. + Typedefed regex_t to be `struct re_pattern_buffer'. + + * regex.c (CHAR_SET_SIZE): Defined this to be 256 and replaced + incidences of this value with this constant. + (re_compile_pattern): Added switch case for `\n' and put + `newline' into the pattern buffer when encounter this. + Increment the pattern_buffer's `re_nsub' field whenever open a + group. + (re_match_2): Match a newline with `newline'---provided the + syntax bit RE_CANNOT_MATCH_NEWLINE isn't set. + (regcomp): Added this Posix interface routine. + (enum test_type): Added interface_test tag. + (main): Added Posix interface test. + +Tue Dec 18 12:58:12 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (struct re_pattern_buffer): reformatted so would fit + in texinfo documentation. + +Thu Nov 29 15:49:16 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_EMPTY_ALTS): Added this bit. + (RE_SYNTAX_POSIX_EXTENDED): Added above bit. + + * regex.c (re_compile_pattern): Disallow empty alternatives only + when RE_NO_EMPTY_ALTS is set, not when RE_CONTEXTUAL_INVALID_OPS is. + Changed RE_NO_BK_CURLY_BRACES to RE_NO_BK_PARENS when testing + for empty groups at label handle_open. + At label handle_bar: disallow empty alternatives if RE_NO_EMPTY_ALTS + is set. + Rewrote some comments. + + (re_compile_fastmap): cleaned up code. + + (re_search_2): Rewrote comment. + + (struct register_info): Added field `inner_groups'; it records + which groups are inside of the current one. + Added field can_match_nothing; it's set if the current group + can match nothing. + Added field ever_match_something; it's set if current group + ever matched something. + + (INNER_GROUPS): Added macro to access inner_groups field of + struct register_info. + + (CAN_MATCH_NOTHING): Added macro to access can_match_nothing + field of struct register_info. + + (EVER_MATCHED_SOMETHING): Added macro to access + ever_matched_something field of struct register_info. + + (NOTE_INNER_GROUP): Defined macro to record that a given group + is inside of all currently active groups. + + (re_match_2): Added variables *p1 and mcnt2 (multipurpose). + Added old_regstart and old_regend arrays to hold previous + register values if they need be restored. + Initialize added fields and variables. + case start_memory: Find out if the group can match nothing. + Save previous register values in old_restart and old_regend. + Record that current group is inside of all currently active + groups. + If the group is inside a loop and it ever matched anything, + restore its registers to values before the last failed match. + Restore the registers for the inner groups, too. + case duplicate: Can back reference to a group that never + matched if it can match nothing. + +Thu Nov 29 11:12:54 1990 Karl Berry (karl at hayley) + + * regex.c (bcopy, ...): define these if either _POSIX_SOURCE or + STDC_HEADERS is defined; same for including <stdlib.h>. + +Sat Oct 6 16:04:55 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (struct re_pattern_buffer): Changed field comments. + + * regex.c (re_compile_pattern): Allow a `$' to precede an + alternation operator (`|' or `\|'). + Disallow `^' and/or `$' in empty groups if the syntax bit + RE_NO_EMPTY_GROUPS is set. + Wait until have parsed a valid `\{...\}' interval expression + before testing RE_CONTEXTUAL_INVALID_OPS to see if it's + invalidated by that. + Don't use RE_NO_BK_CURLY_BRACES to test whether or not a validly + parsed interval expression is invalid if it has no preceding re; + rather, use RE_CONTEXTUAL_INVALID_OPS. + If an interval parses, but there is no preceding regular + expression, yet the syntax bit RE_CONTEXTUAL_INDEP_OPS is set, + then that interval can match the empty regular expression; if + the bit isn't set, then the characters in the interval + expression are parsed as themselves (sans the backslashes). + In unfetch_interval case: Moved PATFETCH to above the test for + RE_NO_BK_CURLY_BRACES being set, which would force a goto + normal_backslash; the code at both normal_backsl and normal_char + expect a character in `c.' + +Sun Sep 30 11:13:48 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Changed some comments to use the terms used in the + documentation. + (RE_CONTEXTUAL_INDEP_OPS): Changed name from `RE_CONTEXT_INDEP_OPS'. + (RE_LISTS_NOT_NEWLINE): Changed name from `RE_HAT_NOT_NEWLINE.' + (RE_ANCHOR_NOT_NEWLINE): Added this syntax bit. + (RE_NO_EMPTY_GROUPS): Added this syntax bit. + (RE_NO_HYPHEN_RANGE_END): Deleted this syntax bit. + (RE_SYNTAX_...): Reformatted. + (RE_SYNTAX_POSIX_BASIC, RE_SYNTAX_EXTENDED): Added syntax bits + RE_ANCHOR_NOT_NEWLINE and RE_NO_EMPTY_GROUPS, and deleted + RE_NO_HYPHEN_RANGE_END. + (RE_SYNTAX_POSIX_EXTENDED): Added syntax bit RE_DOT_NOT_NULL. + + * regex.c (bcopy, bcmp, bzero): Define if _POSIX_SOURCE is defined. + (_POSIX_SOURCE): ifdef this, #include <stdlib.h> + (#ifdef emacs): Changed comment of the #endif for the its #else + clause to be `not emacs', not `emacs.' + (no_pop_jump): Changed name from `jump'. + (pop_failure_jump): Changed name from `finalize_jump.' + (maybe_pop_failure_jump): Changed name from `maybe_finalize_jump'. + (no_pop_jump_n): Changed name from `jump_n.' + (EXTEND_BUFFER): Use shift instead of multiplication to double + buf->allocated. + (DO_RANGE, recompile_pattern): Added macro to set the list bits + for a range. + (re_compile_pattern): Fixed grammar problems in some comments. + Checked that RE_NO_BK_VBAR is set to make `$' valid before a `|' + and not set to make it valid before a `\|'. + Checked that RE_NO_BK_PARENS is set to make `$' valid before a ')' + and not set to make it valid before a `\)'. + Disallow ranges starting with `-', unless the range is the + first item in a list, rather than disallowing ranges which end + with `-'. + Disallow empty groups if the syntax bit RE_NO_EMPTY_GROUPS is set. + Disallow nothing preceding `{' and `\{' if they represent the + open-interval operator and RE_CONTEXTUAL_INVALID_OPS is set. + (register_info_type): typedef-ed this using `struct register_info.' + (SET_REGS_MATCHED): Compacted the code. + (re_match_2): Made it fail if back reference a group which we've + never matched. + Made `^' not match a newline if the syntax bit + RE_ANCHOR_NOT_NEWLINE is set. + (really_fail): Added this label so could force a final fail that + would not try to use the failure stack to recover. + +Sat Aug 25 14:23:01 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_CONTEXTUAL_OPS): Changed name from RE_CONTEXT_OPS. + (global): Rewrote comments and rebroke some syntax #define lines. + + * regex.c (isgraph): Added definition for sequents. + (global): Now refer to character set lists as ``lists.'' + Rewrote comments containing ``\('' or ``\)'' to now refer to + ``groups.'' + (RE_CONTEXTUAL_OPS): Changed name from RE_CONTEXT_OPS. + + (re_compile_pattern): Expanded header comment. + +Sun Jul 15 14:50:25 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_CONTEX_INDEP_OPS): the comment's sense got turned + around when we changed how it read; changed it to be correct. + +Sat Jul 14 16:38:06 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_EMPTY_BK_REF): changed name to + RE_NO_MISSING_BK_REF, as this describes it better. + + * regex.c (re_compile_pattern): changed RE_NO_EMPTY_BK_REF + to RE_NO_MISSING_BK_REF, as above. + +Thu Jul 12 11:45:05 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h (RE_NO_EMPTY_BRACKETS): removed this syntax bit, as + bracket expressions should *never* be empty regardless of the + syntax. Removes this bit from RE_SYNTAX_POSIX_BASIC and + RE_SYNTAX_POSIX_EXTENDED. + + * regex.c (SET_LIST_BIT): in the comment, now refer to character + sets as (non)matching sets, as bracket expressions can now match + other things in addition to characters. + (re_compile_pattern): refer to groups as such instead of `\(...\)' + or somesuch, because groups can now be enclosed in either plain + parens or backslashed ones, depending on the syntax. + In the '[' case, added a boolean just_had_a_char_class to detect + whether or not a character class begins a range (which is invalid). + Restore way of breaking out of a bracket expression to original way. + Add way to detect a range if the last thing in a bracket + expression was a character class. + Took out check for c != ']' at the end of a character class in + the else clause, as it had already been checked in the if part + that also checked the validity of the string. + Set or clear just_had_a_char_class as appropriate. + Added some comments. Changed references to character sets to + ``(non)matching lists.'' + +Sun Jul 1 12:11:29 1990 Karl Berry (karl at hayley) + + * regex.h (BYTEWIDTH): moved back to regex.c. + + * regex.h (re_compile_fastmap): removed declaration; this + shouldn't be advertised. + +Mon May 28 15:27:53 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (ifndef Sword): Made comments more specific. + (global): include <stdio.h> so can write fatal messages on + standard error. Replaced calls to assert with fprintfs to + stderr and exit (1)'s. + (PREFETCH): Reformatted to make more readable. + (AT_STRINGS_BEG): Defined to test if we're at the beginning of + the virtual concatenation of string1 and string2. + (AT_STRINGS_END): Defined to test if at the end of the virtual + concatenation of string1 and string2. + (AT_WORD_BOUNDARY): Defined to test if are at a word boundary. + (IS_A_LETTER(d)): Defined to test if the contents of the pointer D + is a letter. + (re_match_2): Rewrote the wordbound, notwordbound, wordbeg, wordend, + begbuf, and endbuf cases in terms of the above four new macros. + Called SET_REGS_MATCHED in the matchsyntax, matchnotsyntax, + wordchar, and notwordchar cases. + +Mon May 14 14:49:13 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (re_search_2): Fixed RANGE to not ever take STARTPOS + outside of virtual concatenation of STRING1 and STRING2. + Updated header comment as to this. + (re_match_2): Clarified comment about MSTOP in header. + +Sat May 12 15:39:00 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (re_search_2): Checked for out-of-range STARTPOS. + Added comments. + When searching backwards, not only get the character with which + to compare to the fastmap from string2 if the starting position + >= size1, but also if size1 is zero; this is so won't get a + segmentation fault if string1 is null. + Reformatted code at label advance. + +Thu Apr 12 20:26:21 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Added #pragma once and #ifdef...endif __REGEXP_LIBRARY. + (RE_EXACTN_VALUE): Added for search.c to use. + Reworded some comments. + + regex.c: Punctuated some comments correctly. + (NULL): Removed this. + (RE_EXACTN_VALUE): Added for search.c to use. + (<ctype.h>): Moved this include to top of file. + (<assert.h>): Added this include. + (struct regexpcode): Assigned 0 to unused and 1 to exactn + because of RE_EXACTN_VALUE. + Added comment. + (various macros): Lined up backslashes near end of line. + (insert_jump): Cleaned up the header comment. + (re_search): Corrected the header comment. + (re_search_2): Cleaned up and completed the header comment. + (re_max_failures): Updated comment. + (struct register_info): Constructed as bits so as to save space + on the stack when pushing register information. + (IS_ACTIVE): Macro for struct register_info. + (MATCHED_SOMETHING): Macro for struct register_info. + (NUM_REG_ITEMS): How many register information items for each + register we have to push on the stack at each failure. + (MAX_NUM_FAILURE_ITEMS): If push all the registers on failure, + this is how many items we push on the stack. + (PUSH_FAILURE_POINT): Now pushes whether or not the register is + currently active, and whether or not it matched something. + Checks that there's enough space allocated to accomodate all the + items we currently want to push. (Before, a test for an empty + stack sufficed because we always pushed and popped the same + number of items). + Replaced ``2'' with MAX_NUM_FAILURE_POINTS when ``2'' refers + to how many things get pushed on the stack each time. + When copy the stack into the newly allocated storage, now only copy + the area in use. + Clarified comment. + (POP_FAILURE_POINT): Defined to use in places where put number + of registers on the stack into a variable before using it to + decrement the stack, so as to not confuse the compiler. + (IS_IN_FIRST_STRING): Defined to check if a pointer points into + the first string. + (SET_REGS_MATCHED): Changed to use the struct register_info + bits; also set the matched-something bit to false if the + register isn't currently active. (This is a redundant setting.) + (re_match_2): Cleaned up and completed the header comment. + Updated the failure stack comment. + Replaced the ``2'' with MAX_NUM_FAILURE_ITEMS in the static + allocation of initial_stack, because now more than two (now up + to MAX_FAILURE_ITEMS) items get pushed on the failure stack each + time. + Ditto for stackb. + Trashed restart_seg1, regend_seg1, best_regstart_seg1, and + best_regend_seg1 because they could have erroneous information + in them, such as when matching ``a'' (in string1) and ``ab'' (in + string2) with ``(a)*ab''; before using IS_IN_FIRST_STRING to see + whether or not the register starts or ends in string1, + regstart[1] pointed past the end of string1, yet regstart_seg1 + was 0! + Added variable reg_info of type struct register_info to keep + track of currently active registers and whether or not they + currently match anything. + Commented best_regs_set. + Trashed reg_active and reg_matched_something and put the + information they held into reg_info; saves space on the stack. + Replaced NULL with '\000'. + In begline case, compacted the code. + Used assert to exit if had an internal error. + In begbuf case, because now force the string we're working on + into string2 if there aren't two strings, now allow d == string2 + if there is no string1 (and the check for that is size1 == 0!); + also now succeeds if there aren't any strings at all. + (main, ifdef canned): Put test type into a variable so could + change it while debugging. + +Sat Mar 24 12:24:13 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (GET_UNSIGNED_NUMBER): Deleted references to num_fetches. + (re_compile_pattern): Deleted num_fetches because could keep + track of the number of fetches done by saving a pointer into the + pattern. + Added variable beg_interval to be used as a pointer, as above. + Assert that beg_interval points to something when it's used as above. + Initialize succeed_n's to lower_bound because re_compile_fastmap + needs to know it. + (re_compile_fastmap): Deleted unnecessary variable is_a_jump_n. + Added comment. + (re_match_2): Put number of registers on the stack into a + variable before using it to decrement the stack, so as to not + confuse the compiler. + Updated comments. + Used error routine instead of printf and exit. + In exactn case, restored longer code from ``original'' regex.c + which doesn't test translate inside a loop. + + * regex.h: Moved #define NULL and the enum regexpcode definition + and to regex.c. Changed some comments. + + regex.c (global): Updated comments about compiling and for the + re_compile_pattern jump routines. + Added #define NULL and the enum regexpcode definition (from + regex.h). + (enum regexpcode): Added set_number_at to reset the n's of + succeed_n's and jump_n's. + (re_set_syntax): Updated its comment. + (re_compile_pattern): Moved its heading comment to after its macros. + Moved its include statement to the top of the file. + Commented or added to comments of its macros. + In start_memory case: Push laststart value before adding + start_memory and its register number to the buffer, as they + might not get added. + Added code to put a set_number_at before each succeed_n and one + after each jump_n; rewrote code in what seemed a more + straightforward manner to put all these things in the pattern so + the succeed_n's would correctly jump to the set_number_at's of + the matching jump_n's, and so the jump_n's would correctly jump + to after the set_number_at's of the matching succeed_n's. + Initialize succeed_n n's to -1. + (insert_op_2): Added this to insert an operation followed by + two integers. + (re_compile_fastmap): Added set_number_at case. + (re_match_2): Moved heading comment to after macros. + Added mention of REGS to heading comment. + No longer turn a succeed_n with n = 0 into an on_failure_jump, + because n needs to be reset each time through a loop. + Check to see if a succeed_n's n is set by its set_number_at. + Added set_number_at case. + Updated some comments. + (main): Added another main to run posix tests, which is compiled + ifdef both test and canned. (Old main is still compiled ifdef + test only). + +Tue Mar 19 09:22:55 1990 Kathy Hargreaves (kathy at hayley) + + * regex.[hc]: Change all instances of the word ``legal'' to + ``valid'' and all instances of ``illegal'' to ``invalid.'' + +Sun Mar 4 12:11:31 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Added syntax bit RE_NO_EMPTY_RANGES which is set if + an ending range point has to collate higher or equal to the + starting range point. + Added syntax bit RE_NO_HYPHEN_RANGE_END which is set if a hyphen + can't be an ending range point. + Set to two above bits in RE_SYNTAX_POSIX_BASIC and + RE_SYNTAX_POSIX_EXTENDED. + + regex.c: (re_compile_pattern): Don't allow empty ranges if the + RE_NO_EMPTY_RANGES syntax bit is set. + Don't let a hyphen be a range end if the RE_NO_HYPHEN_RANGE_END + syntax bit is set. + (ESTACK_PUSH_2): renamed this PUSH_FAILURE_POINT and made it + push all the used registers on the stack, as well as the number + of the highest numbered register used, and (as before) the two + failure points. + (re_match_2): Fixed up comments. + Added arrays best_regstart[], best_regstart_seg1[], best_regend[], + and best_regend_seg1[] to keep track of the best match so far + whenever reach the end of the pattern but not the end of the + string, and there are still failure points on the stack with + which to backtrack; if so, do the saving and force a fail. + If reach the end of the pattern but not the end of the string, + but there are no more failure points to try, restore the best + match so far, set the registers and return. + Compacted some code. + In stop_memory case, if the subexpression we've just left is in + a loop, push onto the stack the loop's on_failure_jump failure + point along with the current pointer into the string (d). + In finalize_jump case, in addition to popping the failure + points, pop the saved registers. + In the fail case, restore the registers, as well as the failure + points. + +Sun Feb 18 15:08:10 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c: (global): Defined a macro GET_BUFFER_SPACE which + makes sure you have a specified number of buffer bytes + allocated. + Redefined the macro BUFPUSH to use this. + Added comments. + + (re_compile_pattern): Call GET_BUFFER_SPACE before storing or + inserting any jumps. + + (re_match_2): Set d to string1 + pos and dend to end_match_1 + only if string1 isn't null. + Force exit from a loop if it's around empty parentheses. + In stop_memory case, if found some jumps, increment p2 before + extracting address to which to jump. Also, don't need to know + how many more times can jump_n. + In begline case, d must equal string1 or string2, in that order, + only if they are not null. + In maybe_finalize_jump case, skip over start_memorys' and + stop_memorys' register numbers, too. + +Thu Feb 15 15:53:55 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c (BUFPUSH): off by one goof in deciding whether to + EXTEND_BUFFER. + +Wed Jan 24 17:07:46 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Moved definition of NULL to here. + Got rid of ``In other words...'' comment. + Added to some comments. + + regex.c: (re_compile_pattern): Tried to bulletproof some code, + i.e., checked if backward references (e.g., p[-1]) were within + the range of pattern. + + (re_compile_fastmap): Fixed a bug in succeed_n part where was + getting the amount to jump instead of how many times to jump. + + (re_search_2): Changed the name of the variable ``total'' to + ``total_size.'' + Condensed some code. + + (re_match_2): Moved the comment about duplicate from above the + start_memory case to above duplicate case. + + (global): Rewrote some comments. + Added commandline arguments to testing. + +Wed Jan 17 11:47:27 1990 Kathy Hargreaves (kathy at hayley) + + * regex.c: (global): Defined a macro STORE_NUMBER which stores a + number into two contiguous bytes. Also defined STORE_NUMBER_AND_INCR + which does the same thing and then increments the pointer to the + storage place to point after the number. + Defined a macro EXTRACT_NUMBER which extracts a number from two + continguous bytes. Also defined EXTRACT_NUMBER_AND_INCR which + does the same thing and then increments the pointer to the + source to point to after where the number was. + +Tue Jan 16 12:09:19 1990 Kathy Hargreaves (kathy at hayley) + + * regex.h: Incorporated rms' changes. + Defined RE_NO_BK_REFS syntax bit which is set when want to + interpret back reference patterns as literals. + Defined RE_NO_EMPTY_BRACKETS syntax bit which is set when want + empty bracket expressions to be illegal. + Defined RE_CONTEXTUAL_ILLEGAL_OPS syntax bit which is set when want + it to be illegal for *, +, ? and { to be first in an re or come + immediately after a | or a (, and for ^ not to appear in a + nonleading position and $ in a nontrailing position (outside of + bracket expressions, that is). + Defined RE_LIMITED_OPS syntax bit which is set when want +, ? + and | to always be literals instead of ops. + Fixed up the Posix syntax. + Changed the syntax bit comments from saying, e.g., ``0 means...'' + to ``If this bit is set, it means...''. + Changed the syntax bit defines to use shifts instead of integers. + + * regex.c: (global): Incorporated rms' changes. + + (re_compile_pattern): Incorporated rms' changes + Made it illegal for a $ to appear anywhere but inside a bracket + expression or at the end of an re when RE_CONTEXTUAL_ILLEGAL_OPS + is set. Made the same hold for $ except it has to be at the + beginning of an re instead of the end. + Made the re "[]" illegal if RE_NO_EMPTY_BRACKETS is set. + Made it illegal for | to be first or last in an re, or immediately + follow another | or a (. + Added and embellished some comments. + Allowed \{ to be interpreted as a literal if RE_NO_BK_CURLY_BRACES + is set. + Made it illegal for *, +, ?, and { to appear first in an re, or + immediately follow a | or a ( when RE_CONTEXTUAL_ILLEGAL_OPS is set. + Made back references interpreted as literals if RE_NO_BK_REFS is set. + Made recursive intervals either illegal (if RE_NO_BK_CURLY_BRACES + isn't set) or interpreted as literals (if is set), if RE_INTERVALS + is set. + Made it treat +, ? and | as literals if RE_LIMITED_OPS is set. + Cleaned up some code. + +Thu Dec 21 15:31:32 1989 Kathy Hargreaves (kathy at hayley) + + * regex.c: (global): Moved RE_DUP_MAX to regex.h and made it + equal 2^15 - 1 instead of 1000. + Defined NULL to be zero. + Moved the definition of BYTEWIDTH to regex.h. + Made the global variable obscure_syntax nonstatic so the tests in + another file could use it. + + (re_compile_pattern): Defined a maximum length (CHAR_CLASS_MAX_LENGTH) + for character class strings (i.e., what's between the [: and the + :]'s). + Defined a macro SET_LIST_BIT(c) which sets the bit for C in a + character set list. + Took out comments that EXTEND_BUFFER clobbers C. + Made the string "^" match itself, if not RE_CONTEXT_IND_OPS. + Added character classes to bracket expressions. + Change the laststart pointer saved with the start of each + subexpression to point to start_memory instead of after the + following register number. This is because the subexpression + might be in a loop. + Added comments and compacted some code. + Made intervals only work if preceded by an re matching a single + character or a subexpression. + Made back references to nonexistent subexpressions illegal if + using POSIX syntax. + Made intervals work on the last preceding character of a + concatenation of characters, e.g., ab{0,} matches abbb, not abab. + Moved macro PREFETCH to outside the routine. + + (re_compile_fastmap): Added succeed_n to work analogously to + on_failure_jump if n is zero and jump_n to work analogously to + the other backward jumps. + + (re_match_2): Defined macro SET_REGS_MATCHED to set which + current subexpressions had matches within them. + Changed some comments. + Added reg_active and reg_matched_something arrays to keep track + of in which subexpressions currently have matched something. + Defined MATCHING_IN_FIRST_STRING and replaced ``dend == end_match_1'' + with it to make code easier to understand. + Fixed so can apply * and intervals to arbitrarily nested + subexpressions. (Lots of previous bugs here.) + Changed so won't match a newline if syntax bit RE_DOT_NOT_NULL is set. + Made the upcase array nonstatic so the testing file could use it also. + + (main.c): Moved the tests out to another file. + + (tests.c): Moved all the testing stuff here. + +Sat Nov 18 19:30:30 1989 Kathy Hargreaves (kathy at hayley) + + * regex.c: (re_compile_pattern): Defined RE_DUP_MAX, the maximum + number of times an interval can match a pattern. + Added macro GET_UNSIGNED_NUMBER (used to get below): + Added variables lower_bound and upper_bound for upper and lower + bounds of intervals. + Added variable num_fetches so intervals could do backtracking. + Added code to handle '{' and "\{" and intervals. + Added to comments. + + (store_jump_n): (Added) Stores a jump with a number following the + relative address (for intervals). + + (insert_jump_n): (Added) Inserts a jump_n. + + (re_match_2): Defined a macro ESTACK_PUSH_2 for the error stack; + it checks for overflow and reallocates if necessary. + + * regex.h: Added bits (RE_INTERVALS and RE_NO_BK_CURLY_BRACES) + to obscure syntax to indicate whether or not + a syntax handles intervals and recognizes either \{ and + \} or { and } as operators. Also added two syntaxes + RE_SYNTAX_POSIX_BASIC and RE_POSIX_EXTENDED and two command codes + to the enumeration regexpcode; they are succeed_n and jump_n. + +Sat Nov 18 19:30:30 1989 Kathy Hargreaves (kathy at hayley) + + * regex.c: (re_compile_pattern): Defined INIT_BUFF_SIZE to get rid + of repeated constants in code. Tested with value 1. + Renamed PATPUSH as BUFPUSH, since it pushes things onto the + buffer, not the pattern. Also made this macro extend the buffer + if it's full (so could do the following): + Took out code at top of loop that checks to see if buffer is going + to be full after 10 additions (and reallocates if necessary). + + (insert_jump): Rearranged declaration lines so comments would read + better. + + (re_match_2): Compacted exactn code and added more comments. + + (main): Defined macros TEST_MATCH and MATCH_SELF to do + testing; took out loop so could use these instead. + +Tue Oct 24 20:57:18 1989 Kathy Hargreaves (kathy at hayley) + + * regex.c (re_set_syntax): Gave argument `syntax' a type. + (store_jump, insert_jump): made them void functions. + +Local Variables: +mode: indented-text +left-margin: 8 +version-control: never +End: diff --git a/gnu/lib/regex-0.12/INSTALL b/gnu/lib/regex-0.12/INSTALL new file mode 100644 index 00000000000..014e0f728ad --- /dev/null +++ b/gnu/lib/regex-0.12/INSTALL @@ -0,0 +1,117 @@ +This is a generic INSTALL file for utilities distributions. +If this package does not come with, e.g., installable documentation or +data files, please ignore the references to them below. + +To compile this package: + +1. Configure the package for your system. In the directory that this +file is in, type `./configure'. If you're using `csh' on an old +version of System V, you might need to type `sh configure' instead to +prevent `csh' from trying to execute `configure' itself. + +The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation, and +creates the Makefile(s) (one in each subdirectory of the source +directory). In some packages it creates a C header file containing +system-dependent definitions. It also creates a file `config.status' +that you can run in the future to recreate the current configuration. + +Running `configure' takes a minute or two. While it is running, it +prints some messages that tell what it is doing. If you don't want to +see the messages, run `configure' with its standard output redirected +to `/dev/null'; for example, `./configure >/dev/null'. + +To compile the package in a different directory from the one +containing the source code, you must use a version of `make' that +supports the VPATH variable, such as GNU `make'. `cd' to the directory +where you want the object files and executables to go and run +`configure'. `configure' automatically checks for the source code in +the directory that `configure' is in and in `..'. If for some reason +`configure' is not in the source code directory that you are +configuring, then it will report that it can't find the source code. +In that case, run `configure' with the option `--srcdir=DIR', where +DIR is the directory that contains the source code. + +By default, `make install' will install the package's files in +/usr/local/bin, /usr/local/lib, /usr/local/man, etc. You can specify +an installation prefix other than /usr/local by giving `configure' the +option `--prefix=PATH'. Alternately, you can do so by giving a value +for the `prefix' variable when you run `make', e.g., + make prefix=/usr/gnu + +You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If +you give `configure' the option `--exec-prefix=PATH' or set the +`make' variable `exec_prefix' to PATH, the package will use PATH as +the prefix for installing programs and libraries. Data files and +documentation will still use the regular prefix. Normally, all files +are installed using the regular prefix. + +Another `configure' option is useful mainly in `Makefile' rules for +updating `config.status' and `Makefile'. The `--no-create' option +figures out the configuration for your system and records it in +`config.status', without actually configuring the package (creating +`Makefile's and perhaps a configuration header file). Later, you can +run `./config.status' to actually configure the package. You can also +give `config.status' the `--recheck' option, which makes it re-run +`configure' with the same arguments you used before. This option is +useful if you change `configure'. + +Some packages pay attention to `--with-PACKAGE' options to `configure', +where PACKAGE is something like `gnu-libc' or `x' (for the X Window System). +The README should mention any --with- options that the package recognizes. + +`configure' ignores any other arguments that you give it. + +If your system requires unusual options for compilation or linking +that `configure' doesn't know about, you can give `configure' initial +values for some variables by setting them in the environment. In +Bourne-compatible shells, you can do that on the command line like +this: + CC='gcc -traditional' DEFS=-D_POSIX_SOURCE ./configure + +The `make' variables that you might want to override with environment +variables when running `configure' are: + +(For these variables, any value given in the environment overrides the +value that `configure' would choose:) +CC C compiler program. + Default is `cc', or `gcc' if `gcc' is in your PATH. +INSTALL Program to use to install files. + Default is `install' if you have it, `cp' otherwise. + +(For these variables, any value given in the environment is added to +the value that `configure' chooses:) +DEFS Configuration options, in the form `-Dfoo -Dbar ...' + Do not use this variable in packages that create a + configuration header file. +LIBS Libraries to link with, in the form `-lfoo -lbar ...' + +If you need to do unusual things to compile the package, we encourage +you to figure out how `configure' could check whether to do them, and +mail diffs or instructions to the address given in the README so we +can include them in the next release. + +2. Type `make' to compile the package. If you want, you can override +the `make' variables CFLAGS and LDFLAGS like this: + + make CFLAGS=-O2 LDFLAGS=-s + +3. If the package comes with self-tests and you want to run them, +type `make check'. If you're not sure whether there are any, try it; +if `make' responds with something like + make: *** No way to make target `check'. Stop. +then the package does not come with self-tests. + +4. Type `make install' to install programs, data files, and +documentation. + +5. You can remove the program binaries and object files from the +source directory by typing `make clean'. To also remove the +Makefile(s), the header file containing system-dependent definitions +(if the package uses one), and `config.status' (all the files that +`configure' created), type `make distclean'. + +The file `configure.in' is used as a template to create `configure' by +a program called `autoconf'. You will only need it if you want to +regenerate `configure' using a newer version of `autoconf'. diff --git a/gnu/lib/regex-0.12/Makefile b/gnu/lib/regex-0.12/Makefile new file mode 100644 index 00000000000..2072891c4c5 --- /dev/null +++ b/gnu/lib/regex-0.12/Makefile @@ -0,0 +1,11 @@ +# $Header: /cvsroot/src/gnu/lib/regex-0.12/Attic/Makefile,v 1.1 1993/04/08 01:11:28 cgd Exp $ + +LIB= gnuregex +CFLAGS+=-DHAVE_STRING_H=1 +SRCS= regex.c +NOMAN= noman + +afterinstall: + install -c -o root -g wheel -m 444 ${.CURDIR}/regex.h /usr/include + +.include <bsd.lib.mk> diff --git a/gnu/lib/regex-0.12/Makefile.gnu b/gnu/lib/regex-0.12/Makefile.gnu new file mode 100644 index 00000000000..0976aa8bdc4 --- /dev/null +++ b/gnu/lib/regex-0.12/Makefile.gnu @@ -0,0 +1,99 @@ +# Generated automatically from Makefile.in by configure. +# Makefile for regex. +# +# Copyright (C) 1992, 1993 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +version = 0.12 + +# You can define CPPFLAGS on the command line. Aside from system-specific +# flags, you can define: +# -DREGEX_MALLOC to use malloc/realloc/free instead of alloca. +# -DDEBUG to enable the compiled pattern disassembler and execution +# tracing; code runs substantially slower. +# -DEXTRACT_MACROS to use the macros EXTRACT_* (as opposed to +# the corresponding C procedures). If not -DDEBUG, the macros +# are used. +CPPFLAGS = + +# Likewise, you can override CFLAGS to optimize, use -Wall, etc. +CFLAGS = -g + +# Ditto for LDFLAGS and LOADLIBES. +LDFLAGS = +LOADLIBES = + +srcdir = . +VPATH = . + +CC = gcc +DEFS = -DHAVE_STRING_H=1 + +SHELL = /bin/sh + +subdirs = doc test + +default all:: regex.o +.PHONY: default all + +regex.o: regex.c regex.h + $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $< + +clean mostlyclean:: + rm -f *.o + +distclean:: clean + rm -f Makefile config.status + +extraclean:: distclean + rm -f patch* *~* *\#* *.orig *.rej *.bak core a.out + +configure: configure.in + autoconf + +config.status: configure + sh configure --no-create + +Makefile: Makefile.in config.status + sh config.status + +makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' \ +DEFS='$(DEFS)' LDFLAGS='$(LDFLAGS)' LOADLIBES='$(LOADLIBES)' + +default all install \ +mostlyclean clean distclean extraclean realclean \ +TAGS check:: + for d in $(subdirs); do (cd $$d; $(MAKE) $(makeargs) $@); done +.PHONY: install mostlyclean clean distclean extraclean realclean TAGS check + +# Prevent GNU make 3 from overflowing arg limit on system V. +.NOEXPORT: + +distfiles = AUTHORS ChangeLog COPYING INSTALL NEWS README \ + *.in configure regex.c regex.h +distdir = regex-$(version) +distargs = version=$(version) distdir=../$(distdir)/$$d +dist: TAGS configure + @echo "Version numbers in: Makefile.in, ChangeLog, NEWS," + @echo " regex.c, regex.h," + @echo " and doc/xregex.texi (if modified)." + rm -rf $(distdir) + mkdir $(distdir) + ln $(distfiles) $(distdir) + for d in $(subdirs); do (cd $$d; $(MAKE) $(distargs) dist); done + tar czhf $(distdir).tar.Z $(distdir) + rm -rf $(distdir) +.PHONY: dist diff --git a/gnu/lib/regex-0.12/Makefile.in b/gnu/lib/regex-0.12/Makefile.in new file mode 100644 index 00000000000..836e6de0ba5 --- /dev/null +++ b/gnu/lib/regex-0.12/Makefile.in @@ -0,0 +1,98 @@ +# Makefile for regex. +# +# Copyright (C) 1992, 1993 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +version = 0.12 + +# You can define CPPFLAGS on the command line. Aside from system-specific +# flags, you can define: +# -DREGEX_MALLOC to use malloc/realloc/free instead of alloca. +# -DDEBUG to enable the compiled pattern disassembler and execution +# tracing; code runs substantially slower. +# -DEXTRACT_MACROS to use the macros EXTRACT_* (as opposed to +# the corresponding C procedures). If not -DDEBUG, the macros +# are used. +CPPFLAGS = + +# Likewise, you can override CFLAGS to optimize, use -Wall, etc. +CFLAGS = -g + +# Ditto for LDFLAGS and LOADLIBES. +LDFLAGS = +LOADLIBES = + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +DEFS = @DEFS@ + +SHELL = /bin/sh + +subdirs = doc test + +default all:: regex.o +.PHONY: default all + +regex.o: regex.c regex.h + $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $< + +clean mostlyclean:: + rm -f *.o + +distclean:: clean + rm -f Makefile config.status + +extraclean:: distclean + rm -f patch* *~* *\#* *.orig *.rej *.bak core a.out + +configure: configure.in + autoconf + +config.status: configure + sh configure --no-create + +Makefile: Makefile.in config.status + sh config.status + +makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' \ +DEFS='$(DEFS)' LDFLAGS='$(LDFLAGS)' LOADLIBES='$(LOADLIBES)' + +default all install \ +mostlyclean clean distclean extraclean realclean \ +TAGS check:: + for d in $(subdirs); do (cd $$d; $(MAKE) $(makeargs) $@); done +.PHONY: install mostlyclean clean distclean extraclean realclean TAGS check + +# Prevent GNU make 3 from overflowing arg limit on system V. +.NOEXPORT: + +distfiles = AUTHORS ChangeLog COPYING INSTALL NEWS README \ + *.in configure regex.c regex.h +distdir = regex-$(version) +distargs = version=$(version) distdir=../$(distdir)/$$d +dist: TAGS configure + @echo "Version numbers in: Makefile.in, ChangeLog, NEWS," + @echo " regex.c, regex.h," + @echo " and doc/xregex.texi (if modified)." + rm -rf $(distdir) + mkdir $(distdir) + ln $(distfiles) $(distdir) + for d in $(subdirs); do (cd $$d; $(MAKE) $(distargs) dist); done + tar czhf $(distdir).tar.Z $(distdir) + rm -rf $(distdir) +.PHONY: dist diff --git a/gnu/lib/regex-0.12/NEWS b/gnu/lib/regex-0.12/NEWS new file mode 100644 index 00000000000..b3a899b4568 --- /dev/null +++ b/gnu/lib/regex-0.12/NEWS @@ -0,0 +1,62 @@ +Version 0.12 + +* regex.c does not #define bcmp/bcopy/bzero if they already are. + +* regex.h does not redefine `const' if it is already defined, even if + __STDC__ is not defined. + +* RE_SYNTAX_ED added (same as POSIX BRE's). + +* The following bugs have been fixed, among others: + * The pattern \w+ doesn't infinite loop. + * The pattern ".+\n" is compiled correctly. + * Expressions with more than MAX_REGNUM groups are compiled correctly. + +* Patterns that end in a repetition operator (e.g., `*') match + slightly faster if no looping is actually necessary. + +Version 0.11 (17 Sep 92) + +* Back-references to nonexistent subexpressions, as in the r.e. `abc\1', + are always invalid. Previously, they could match the literal digit, + e.g., the stated r.e. might have matched `abc1'. + +* Empty subexpressions are always valid (POSIX leaves this undefined). + +* Simplified rules for ^ and $ being anchors. + +* One minor speedup (rewriting the C procedure `pop_failure_point' as a + macro again). + +* Bug fixes involving: + - Declarations in regex.h and non-ANSI compilers. + - Bracket expressions with characters between 0x80-0xff. + - Memory leak in re_match_2 on systems requiring `alloca (0)' to + free alloca'd storage. + +* Test and documentation files moved into subdirectories. + +Version 0.10 (9 Sep 92) + +* `obscure_syntax' is now called `re_default_syntax'. + +* `re_comp's return type is no longer `const', for compatibility with BSD. + +* POSIX syntaxes now include as much functionality as possible + (consistent with the standard). + +* Compilation conditionals normalized to what the rest of GNU is + migrating towards these days. + +* Bug fixes involving: + - Ranges with characters between 0x80 and 0xff, e.g., [\001-\377]. + - `re_compile_fastmap' and the sequence `.*\n'. + - Intervals with exact counts, e.g., a{5}. + +* Changed distribution to use a standard Makefile, install the info + files, use a configure script, etc. + +Version 0.9 + +* The longest match was not always chosen: `a*|ab' didn't match `aab'. + diff --git a/gnu/lib/regex-0.12/README b/gnu/lib/regex-0.12/README new file mode 100644 index 00000000000..918e1a03b82 --- /dev/null +++ b/gnu/lib/regex-0.12/README @@ -0,0 +1,60 @@ +This directory contains the GNU regex library. It is compliant with +POSIX.2, except for internationalization features. + +See the file NEWS for a list of major changes in the current release. + +See the file INSTALL for compilation instructions. (The only thing +installed is the documentation; regex.c is compiled into regex.o, but +not installed anywhere.) + +The subdirectory `doc' contains a (programmers') manual for the library. +It's probably out-of-date. Improvements are welcome. + +The subdirectory `test' contains the various tests we've written. + +We know this code is not as fast as it might be. If you have specific +suggestions, profiling results, or other such useful information to +report, please do. + +Emacs 18 is not going use this revised regex (but Emacs 19 will). If +you want to try it with Emacs 18, apply the patch at the end of this +file first. + +Mail bug reports to bug-gnu-utils@prep.ai.mit.edu. + +Please include an actual regular expression that fails (and the syntax +used to compile it); without that, there's no way to reproduce the bug, +so there's no way we can fix it. Even if you include a patch, also +include the regular expression in error; otherwise, we can't know for +sure what you're trying to fix. + +Here is the patch to make this version of regex work with Emacs 18. + +*** ORIG/search.c Tue Jan 8 13:04:55 1991 +--- search.c Sun Jan 5 10:57:00 1992 +*************** +*** 25,26 **** +--- 25,28 ---- + #include "commands.h" ++ ++ #include <sys/types.h> + #include "regex.h" +*************** +*** 477,479 **** + /* really needed. */ +! && *(searchbuf.buffer) == (char) exactn /* first item is "exact match" */ + && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */ +--- 479,482 ---- + /* really needed. */ +! /* first item is "exact match" */ +! && *(searchbuf.buffer) == (char) RE_EXACTN_VALUE + && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */ +*************** +*** 1273,1275 **** + searchbuf.allocated = 100; +! searchbuf.buffer = (char *) malloc (searchbuf.allocated); + searchbuf.fastmap = search_fastmap; +--- 1276,1278 ---- + searchbuf.allocated = 100; +! searchbuf.buffer = (unsigned char *) malloc (searchbuf.allocated); + searchbuf.fastmap = search_fastmap; diff --git a/gnu/lib/regex-0.12/config.status b/gnu/lib/regex-0.12/config.status new file mode 100644 index 00000000000..1b276aacf34 --- /dev/null +++ b/gnu/lib/regex-0.12/config.status @@ -0,0 +1,59 @@ +#!/bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host sun-lamp.cs.berkeley.edu: +# +# configure + +for arg +do + case "$arg" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + exec /bin/sh configure ;; + *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;; + esac +done + +trap 'rm -f Makefile doc/Makefile test/Makefile; exit 1' 1 3 15 +CC='gcc' +INSTALL='/usr/bin/install -c' +INSTALL_PROGRAM='$(INSTALL)' +INSTALL_DATA='$(INSTALL) -m 644' +CPP='${CC-cc} -E' +ALLOCA='' +LIBS='' +srcdir='.' +DEFS=' -DHAVE_STRING_H=1' +prefix='/usr' +exec_prefix='${prefix}' +prsub='s%^prefix\([ ]*\)=\([ ]*\).*$%prefix\1=\2/usr% +s%^exec_prefix\([ ]*\)=\([ ]*\).*$%exec_prefix\1=\2${prefix}%' + +top_srcdir=$srcdir +for file in .. Makefile doc/Makefile test/Makefile; do if [ "x$file" != "x.." ]; then + srcdir=$top_srcdir + # Remove last slash and all that follows it. Not all systems have dirname. + dir=`echo $file|sed 's%/[^/][^/]*$%%'` + if test "$dir" != "$file"; then + test "$top_srcdir" != . && srcdir=$top_srcdir/$dir + test ! -d $dir && mkdir $dir + fi + echo creating $file + rm -f $file + echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file + sed -e " +$prsub +s%@CC@%$CC%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g +s%@LIBS@%$LIBS%g +s%@srcdir@%$srcdir%g +s%@DEFS@%$DEFS% +" $top_srcdir/${file}.in >> $file +fi; done + +exit 0 diff --git a/gnu/lib/regex-0.12/configure b/gnu/lib/regex-0.12/configure new file mode 100644 index 00000000000..29c5b803c32 --- /dev/null +++ b/gnu/lib/regex-0.12/configure @@ -0,0 +1,462 @@ +#!/bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf. +# Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# Usage: configure [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] [--no-create] +# [--prefix=PREFIX] [--exec-prefix=PREFIX] [--with-PACKAGE] [TARGET] +# Ignores all args except --srcdir, --prefix, --exec-prefix, --no-create, and +# --with-PACKAGE unless this script has special code to handle it. + + +for arg +do + # Handle --exec-prefix with a space before the argument. + if test x$next_exec_prefix = xyes; then exec_prefix=$arg; next_exec_prefix= + # Handle --host with a space before the argument. + elif test x$next_host = xyes; then next_host= + # Handle --prefix with a space before the argument. + elif test x$next_prefix = xyes; then prefix=$arg; next_prefix= + # Handle --srcdir with a space before the argument. + elif test x$next_srcdir = xyes; then srcdir=$arg; next_srcdir= + else + case $arg in + # For backward compatibility, also recognize exact --exec_prefix. + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* | --exec=* | --exe=* | --ex=* | --e=*) + exec_prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;; + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- | --exec | --exe | --ex | --e) + next_exec_prefix=yes ;; + + -gas | --gas | --ga | --g) ;; + + -host=* | --host=* | --hos=* | --ho=* | --h=*) ;; + -host | --host | --hos | --ho | --h) + next_host=yes ;; + + -nfp | --nfp | --nf) ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre | --no-cr | --no-c | --no- | --no) + no_create=1 ;; + + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + next_prefix=yes ;; + + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*) + srcdir=`echo $arg | sed 's/[-a-z_]*=//'` ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s) + next_srcdir=yes ;; + + -with-* | --with-*) + package=`echo $arg|sed 's/-*with-//'` + # Delete all the valid chars; see if any are left. + if test -n "`echo $package|sed 's/[-a-zA-Z0-9_]*//g'`"; then + echo "configure: $package: invalid package name" >&2; exit 1 + fi + eval "with_`echo $package|sed s/-/_/g`=1" ;; + + *) ;; + esac + fi +done + +trap 'rm -f conftest* core; exit 1' 1 3 15 + +rm -f conftest* +compile='${CC-cc} $CFLAGS $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1' + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +unique_file=regex.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + srcdirdefaulted=yes + # Try the directory containing this script, then `..'. + prog=$0 + confdir=`echo $prog|sed 's%/[^/][^/]*$%%'` + test "X$confdir" = "X$prog" && confdir=. + srcdir=$confdir + if test ! -r $srcdir/$unique_file; then + srcdir=.. + fi +fi +if test ! -r $srcdir/$unique_file; then + if test x$srcdirdefaulted = xyes; then + echo "configure: Can not find sources in \`${confdir}' or \`..'." 1>&2 + else + echo "configure: Can not find sources in \`${srcdir}'." 1>&2 + fi + exit 1 +fi +# Preserve a srcdir of `.' to avoid automounter screwups with pwd. +# But we can't avoid them for `..', to make subdirectories work. +case $srcdir in + .|/*|~*) ;; + *) srcdir=`cd $srcdir; pwd` ;; # Make relative path absolute. +esac + + +if test -z "$CC"; then + echo checking for gcc + saveifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/gcc; then + CC="gcc" + break + fi + done + IFS="$saveifs" +fi +test -z "$CC" && CC="cc" + +# Find out if we are using GNU C, under whatever name. +cat > conftest.c <<EOF +#ifdef __GNUC__ + yes +#endif +EOF +${CC-cc} -E conftest.c > conftest.out 2>&1 +if egrep yes conftest.out >/dev/null 2>&1; then + GCC=1 # For later tests. +fi +rm -f conftest* + +# Make sure to not get the incompatible SysV /etc/install and +# /usr/sbin/install, which might be in PATH before a BSD-like install, +# or the SunOS /usr/etc/install directory, or the AIX /bin/install, +# or the AFS install, which mishandles nonexistent args. (Sigh.) +if test -z "$INSTALL"; then + echo checking for install + saveifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + case $dir in + /etc|/usr/sbin|/usr/etc|/usr/afsws/bin) ;; + *) + if test -f $dir/install; then + if grep dspmsg $dir/install >/dev/null 2>&1; then + : # AIX + else + INSTALL="$dir/install -c" + INSTALL_PROGRAM='$(INSTALL)' + INSTALL_DATA='$(INSTALL) -m 644' + break + fi + fi + ;; + esac + done + IFS="$saveifs" +fi +INSTALL=${INSTALL-cp} +INSTALL_PROGRAM=${INSTALL_PROGRAM-'$(INSTALL)'} +INSTALL_DATA=${INSTALL_DATA-'$(INSTALL)'} + + +echo checking for AIX +echo checking how to run the C preprocessor +if test -z "$CPP"; then + CPP='${CC-cc} -E' + cat > conftest.c <<EOF +#include <stdio.h> +EOF +err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` +if test -z "$err"; then + : +else + CPP=/lib/cpp +fi +rm -f conftest* +fi + +cat > conftest.c <<EOF +#ifdef _AIX + yes +#endif + +EOF +eval "$CPP $DEFS conftest.c > conftest.out 2>&1" +if egrep "yes" conftest.out >/dev/null 2>&1; then + DEFS="$DEFS -D_ALL_SOURCE=1" +fi +rm -f conftest* + + +echo checking for DYNIX/ptx libseq +cat > conftest.c <<EOF +#if defined(_SEQUENT_) + yes +#endif + +EOF +eval "$CPP $DEFS conftest.c > conftest.out 2>&1" +if egrep "yes" conftest.out >/dev/null 2>&1; then + SEQUENT=1 +fi +rm -f conftest* + +test -n "$SEQUENT" && test -f /usr/lib/libseq.a && + LIBS="$LIBS -lseq" + +echo checking for POSIXized ISC +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + ISC=1 # If later tests want to check for ISC. + DEFS="$DEFS -D_POSIX_SOURCE=1" + if test -n "$GCC"; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +fi + +echo checking for minix/config.h +cat > conftest.c <<EOF +#include <minix/config.h> +EOF +err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` +if test -z "$err"; then + MINIX=1 +fi +rm -f conftest* + +# The Minix shell can't assign to the same variable on the same line! +if test -n "$MINIX"; then + DEFS="$DEFS -D_POSIX_SOURCE=1" + DEFS="$DEFS -D_POSIX_1_SOURCE=2" + DEFS="$DEFS -D_MINIX=1" +fi + + +echo checking for ANSI C header files +cat > conftest.c <<EOF +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` +if test -z "$err"; then + # SunOS string.h does not declare mem*, contrary to ANSI. +echo '#include <string.h>' > conftest.c +eval "$CPP $DEFS conftest.c > conftest.out 2>&1" +if egrep "memchr" conftest.out >/dev/null 2>&1; then + # SGI's /bin/cc from Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +cat > conftest.c <<EOF +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e,f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +eval $compile +if test -s conftest && (./conftest; exit) 2>/dev/null; then + DEFS="$DEFS -DSTDC_HEADERS=1" +fi +rm -f conftest* +fi +rm -f conftest* + +fi +rm -f conftest* + +for hdr in string.h +do +trhdr=HAVE_`echo $hdr | tr '[a-z]./' '[A-Z]__'` +echo checking for ${hdr} +cat > conftest.c <<EOF +#include <${hdr}> +EOF +err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"` +if test -z "$err"; then + DEFS="$DEFS -D${trhdr}=1" +fi +rm -f conftest* +done + + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo checking for working alloca.h +cat > conftest.c <<EOF +#include <alloca.h> +main() { exit(0); } +t() { char *p = alloca(2 * sizeof(int)); } +EOF +if eval $compile; then + DEFS="$DEFS -DHAVE_ALLOCA_H=1" +fi +rm -f conftest* + +decl="#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#if HAVE_ALLOCA_H +#include <alloca.h> +#else +#ifdef _AIX + #pragma alloca +#else +char *alloca (); +#endif +#endif +#endif +" +echo checking for alloca +cat > conftest.c <<EOF +$decl +main() { exit(0); } +t() { char *p = (char *) alloca(1); } +EOF +if eval $compile; then + : +else + alloca_missing=1 +fi +rm -f conftest* + +if test -n "$alloca_missing"; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.o +fi + +prog='/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *p; +char **p2; +/* HPUX 7.0 cc rejects these. */ +++p; +p2 = (char const* const*) p;' +echo checking for working const +cat > conftest.c <<EOF + +main() { exit(0); } +t() { $prog } +EOF +if eval $compile; then + : +else + DEFS="$DEFS -Dconst=" +fi +rm -f conftest* + + +if test -z "$prefix" +then + echo checking for gcc to derive installation directory prefix + saveifs="$IFS"; IFS="$IFS:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test $dir != . && test -f $dir/gcc; then + # Not all systems have dirname. + prefix=`echo $dir|sed 's%/[^/][^/]*$%%'` + break + fi + done + IFS="$saveifs" +fi + + +if test -n "$prefix"; then + test -z "$exec_prefix" && exec_prefix='${prefix}' + prsub="s%^prefix\\([ ]*\\)=\\([ ]*\\).*$%prefix\\1=\\2$prefix%" +fi +if test -n "$exec_prefix"; then + prsub="$prsub +s%^exec_prefix\\([ ]*\\)=\\([ ]*\\).*$%\ +exec_prefix\\1=\\2$exec_prefix%" +fi + +trap 'rm -f config.status; exit 1' 1 3 15 +echo creating config.status +rm -f config.status +cat > config.status <<EOF +#!/bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null`: +# +# $0 $* + +for arg +do + case "\$arg" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + exec /bin/sh $0 $* ;; + *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;; + esac +done + +trap 'rm -f Makefile doc/Makefile test/Makefile; exit 1' 1 3 15 +CC='$CC' +INSTALL='$INSTALL' +INSTALL_PROGRAM='$INSTALL_PROGRAM' +INSTALL_DATA='$INSTALL_DATA' +CPP='$CPP' +ALLOCA='$ALLOCA' +LIBS='$LIBS' +srcdir='$srcdir' +DEFS='$DEFS' +prefix='$prefix' +exec_prefix='$exec_prefix' +prsub='$prsub' +EOF +cat >> config.status <<\EOF + +top_srcdir=$srcdir +for file in .. Makefile doc/Makefile test/Makefile; do if [ "x$file" != "x.." ]; then + srcdir=$top_srcdir + # Remove last slash and all that follows it. Not all systems have dirname. + dir=`echo $file|sed 's%/[^/][^/]*$%%'` + if test "$dir" != "$file"; then + test "$top_srcdir" != . && srcdir=$top_srcdir/$dir + test ! -d $dir && mkdir $dir + fi + echo creating $file + rm -f $file + echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file + sed -e " +$prsub +s%@CC@%$CC%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g +s%@LIBS@%$LIBS%g +s%@srcdir@%$srcdir%g +s%@DEFS@%$DEFS% +" $top_srcdir/${file}.in >> $file +fi; done + +exit 0 +EOF +chmod +x config.status +test -n "$no_create" || ./config.status + diff --git a/gnu/lib/regex-0.12/configure.in b/gnu/lib/regex-0.12/configure.in new file mode 100644 index 00000000000..f0fc7802509 --- /dev/null +++ b/gnu/lib/regex-0.12/configure.in @@ -0,0 +1,23 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(regex.c) + +AC_PROG_CC +AC_PROG_INSTALL + +dnl I'm not sure if AC_AIX and AC_DYNIX_SEQ are really necessary. The +dnl Autoconf documentation isn't specific about which BSD functions they +dnl provide. +AC_AIX +AC_DYNIX_SEQ +AC_ISC_POSIX +AC_MINIX + +AC_STDC_HEADERS +AC_HAVE_HEADERS(string.h) + +AC_ALLOCA +AC_CONST + +AC_PREFIX(gcc) + +AC_OUTPUT(Makefile doc/Makefile test/Makefile) diff --git a/gnu/lib/regex-0.12/regex.c b/gnu/lib/regex-0.12/regex.c new file mode 100644 index 00000000000..8169880d7e4 --- /dev/null +++ b/gnu/lib/regex-0.12/regex.c @@ -0,0 +1,4948 @@ +/* Extended regular expression matching and search library, + version 0.12. + (Implements POSIX draft P10003.2/D11.2, except for + internationalization features.) + + Copyright (C) 1993 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* AIX requires this to be the first thing in the file. */ +#if defined (_AIX) && !defined (REGEX_MALLOC) + #pragma alloca +#endif + +#define _GNU_SOURCE + +/* We need this for `regex.h', and perhaps for the Emacs include files. */ +#include <sys/types.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* The `emacs' switch turns on certain matching commands + that make sense only in Emacs. */ +#ifdef emacs + +#include "lisp.h" +#include "buffer.h" +#include "syntax.h" + +/* Emacs uses `NULL' as a predicate. */ +#undef NULL + +#else /* not emacs */ + +/* We used to test for `BSTRING' here, but only GCC and Emacs define + `BSTRING', as far as I know, and neither of them use this code. */ +#if HAVE_STRING_H || STDC_HEADERS +#include <string.h> +#ifndef bcmp +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#endif +#ifndef bcopy +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#endif +#ifndef bzero +#define bzero(s, n) memset ((s), 0, (n)) +#endif +#else +#include <strings.h> +#endif + +#ifdef STDC_HEADERS +#include <stdlib.h> +#else +char *malloc (); +char *realloc (); +#endif + + +/* Define the syntax stuff for \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +#ifndef Sword +#define Sword 1 +#endif + +#ifdef SYNTAX_TABLE + +extern char *re_syntax_table; + +#else /* not SYNTAX_TABLE */ + +/* How many characters in the character set. */ +#define CHAR_SET_SIZE 256 + +static char re_syntax_table[CHAR_SET_SIZE]; + +static void +init_syntax_once () +{ + register int c; + static int done = 0; + + if (done) + return; + + bzero (re_syntax_table, sizeof re_syntax_table); + + for (c = 'a'; c <= 'z'; c++) + re_syntax_table[c] = Sword; + + for (c = 'A'; c <= 'Z'; c++) + re_syntax_table[c] = Sword; + + for (c = '0'; c <= '9'; c++) + re_syntax_table[c] = Sword; + + re_syntax_table['_'] = Sword; + + done = 1; +} + +#endif /* not SYNTAX_TABLE */ + +#define SYNTAX(c) re_syntax_table[c] + +#endif /* not emacs */ + +/* Get the interface, including the syntax bits. */ +#include "regex.h" + +/* isalpha etc. are used for the character classes. */ +#include <ctype.h> + +#ifndef isascii +#define isascii(c) 1 +#endif + +#ifdef isblank +#define ISBLANK(c) (isascii (c) && isblank (c)) +#else +#define ISBLANK(c) ((c) == ' ' || (c) == '\t') +#endif +#ifdef isgraph +#define ISGRAPH(c) (isascii (c) && isgraph (c)) +#else +#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c)) +#endif + +#define ISPRINT(c) (isascii (c) && isprint (c)) +#define ISDIGIT(c) (isascii (c) && isdigit (c)) +#define ISALNUM(c) (isascii (c) && isalnum (c)) +#define ISALPHA(c) (isascii (c) && isalpha (c)) +#define ISCNTRL(c) (isascii (c) && iscntrl (c)) +#define ISLOWER(c) (isascii (c) && islower (c)) +#define ISPUNCT(c) (isascii (c) && ispunct (c)) +#define ISSPACE(c) (isascii (c) && isspace (c)) +#define ISUPPER(c) (isascii (c) && isupper (c)) +#define ISXDIGIT(c) (isascii (c) && isxdigit (c)) + +#ifndef NULL +#define NULL 0 +#endif + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +#endif + +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we + use `alloca' instead of `malloc'. This is because using malloc in + re_search* or re_match* could cause memory leaks when C-g is used in + Emacs; also, malloc is slower and causes storage fragmentation. On + the other hand, malloc is more portable, and easier to debug. + + Because we sometimes use alloca, some routines have to be macros, + not functions -- `alloca'-allocated space disappears at the end of the + function it is called in. */ + +#ifdef REGEX_MALLOC + +#define REGEX_ALLOCATE malloc +#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) + +#else /* not REGEX_MALLOC */ + +/* Emacs already defines alloca, sometimes. */ +#ifndef alloca + +/* Make alloca work the best possible way. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if HAVE_ALLOCA_H +#include <alloca.h> +#else /* not __GNUC__ or HAVE_ALLOCA_H */ +#ifndef _AIX /* Already did AIX, up at the top. */ +char *alloca (); +#endif /* not _AIX */ +#endif /* not HAVE_ALLOCA_H */ +#endif /* not __GNUC__ */ + +#endif /* not alloca */ + +#define REGEX_ALLOCATE alloca + +/* Assumes a `char *destination' variable. */ +#define REGEX_REALLOCATE(source, osize, nsize) \ + (destination = (char *) alloca (nsize), \ + bcopy (source, destination, osize), \ + destination) + +#endif /* not REGEX_MALLOC */ + + +/* True if `size1' is non-NULL and PTR is pointing anywhere inside + `string1' or just past its end. This works if PTR is NULL, which is + a good thing. */ +#define FIRST_STRING_P(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* (Re)Allocate N items of type T using malloc, or fail. */ +#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + +#define BYTEWIDTH 8 /* In bits. */ + +#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef char boolean; +#define false 0 +#define true 1 + +/* These are the command codes that appear in compiled regular + expressions. Some opcodes are followed by argument bytes. A + command code can specify any interpretation whatsoever for its + arguments. Zero bytes may appear in the compiled regular expression. + + The value of `exactn' is needed in search.c (search_buffer) in Emacs. + So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of + `exactn' we use here must also be 1. */ + +typedef enum +{ + no_op = 0, + + /* Followed by one byte giving n, then by n literal bytes. */ + exactn = 1, + + /* Matches any (more or less) character. */ + anychar, + + /* Matches any one char belonging to specified set. First + following byte is number of bitmap bytes. Then come bytes + for a bitmap saying which chars are in. Bits in each byte + are ordered low-bit-first. A character is in the set if its + bit is 1. A character too large to have a bit in the map is + automatically not in the set. */ + charset, + + /* Same parameters as charset, but match any character that is + not one of those specified. */ + charset_not, + + /* Start remembering the text that is matched, for storing in a + register. Followed by one byte with the register number, in + the range 0 to one less than the pattern buffer's re_nsub + field. Then followed by one byte with the number of groups + inner to this one. (This last has to be part of the + start_memory only because we need it in the on_failure_jump + of re_match_2.) */ + start_memory, + + /* Stop remembering the text that is matched and store it in a + memory register. Followed by one byte with the register + number, in the range 0 to one less than `re_nsub' in the + pattern buffer, and one byte with the number of inner groups, + just like `start_memory'. (We need the number of inner + groups here because we don't have any easy way of finding the + corresponding start_memory when we're at a stop_memory.) */ + stop_memory, + + /* Match a duplicate of something remembered. Followed by one + byte containing the register number. */ + duplicate, + + /* Fail unless at beginning of line. */ + begline, + + /* Fail unless at end of line. */ + endline, + + /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + begbuf, + + /* Analogously, for end of buffer/string. */ + endbuf, + + /* Followed by two byte relative address to which to jump. */ + jump, + + /* Same as jump, but marks the end of an alternative. */ + jump_past_alt, + + /* Followed by two-byte relative address of place to resume at + in case of failure. */ + on_failure_jump, + + /* Like on_failure_jump, but pushes a placeholder instead of the + current string position when executed. */ + on_failure_keep_string_jump, + + /* Throw away latest failure point and then jump to following + two-byte relative address. */ + pop_failure_jump, + + /* Change to pop_failure_jump if know won't have to backtrack to + match; otherwise change to jump. This is used to jump + back to the beginning of a repeat. If what follows this jump + clearly won't match what the repeat does, such that we can be + sure that there is no use backtracking out of repetitions + already matched, then we change it to a pop_failure_jump. + Followed by two-byte address. */ + maybe_pop_jump, + + /* Jump to following two-byte address, and push a dummy failure + point. This failure point will be thrown away if an attempt + is made to use it for a failure. A `+' construct makes this + before the first repeat. Also used as an intermediary kind + of jump when compiling an alternative. */ + dummy_failure_jump, + + /* Push a dummy failure point and continue. Used at the end of + alternatives. */ + push_dummy_failure, + + /* Followed by two-byte relative address and two-byte number n. + After matching N times, jump to the address upon failure. */ + succeed_n, + + /* Followed by two-byte relative address, and two-byte number n. + Jump to the address N times, then fail. */ + jump_n, + + /* Set the following two-byte relative address to the + subsequent two-byte number. The address *includes* the two + bytes of number. */ + set_number_at, + + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ + +#ifdef emacs + ,before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ + + /* Matches any character whose syntax is specified. Followed by + a byte which contains a syntax code, e.g., Sword. */ + syntaxspec, + + /* Matches any character whose syntax is not that specified. */ + notsyntaxspec +#endif /* emacs */ +} re_opcode_t; + +/* Common operations on the compiled pattern. */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ + +#define STORE_NUMBER(destination, number) \ + do { \ + (destination)[0] = (number) & 0377; \ + (destination)[1] = (number) >> 8; \ + } while (0) + +/* Same as STORE_NUMBER, except increment DESTINATION to + the byte after where the number is stored. Therefore, DESTINATION + must be an lvalue. */ + +#define STORE_NUMBER_AND_INCR(destination, number) \ + do { \ + STORE_NUMBER (destination, number); \ + (destination) += 2; \ + } while (0) + +/* Put into DESTINATION a number stored in two contiguous bytes starting + at SOURCE. */ + +#define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + } while (0) + +#ifdef DEBUG +static void +extract_number (dest, source) + int *dest; + unsigned char *source; +{ + int temp = SIGN_EXTEND_CHAR (*(source + 1)); + *dest = *source & 0377; + *dest += temp << 8; +} + +#ifndef EXTRACT_MACROS /* To debug the macros. */ +#undef EXTRACT_NUMBER +#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. + SOURCE must be an lvalue. */ + +#define EXTRACT_NUMBER_AND_INCR(destination, source) \ + do { \ + EXTRACT_NUMBER (destination, source); \ + (source) += 2; \ + } while (0) + +#ifdef DEBUG +static void +extract_number_and_incr (destination, source) + int *destination; + unsigned char **source; +{ + extract_number (destination, *source); + *source += 2; +} + +#ifndef EXTRACT_MACROS +#undef EXTRACT_NUMBER_AND_INCR +#define EXTRACT_NUMBER_AND_INCR(dest, src) \ + extract_number_and_incr (&dest, &src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* If DEBUG is defined, Regex prints many voluminous messages about what + it is doing (if the variable `debug' is nonzero). If linked with the + main program in `iregex.c', you can enter patterns and strings + interactively. And if linked with the main program in `main.c' and + the other test files, you can run the already-written tests. */ + +#ifdef DEBUG + +/* We use standard I/O for debugging. */ +#include <stdio.h> + +/* It is useful to test things that ``must'' be true when debugging. */ +#include <assert.h> + +static int debug = 0; + +#define DEBUG_STATEMENT(e) e +#define DEBUG_PRINT1(x) if (debug) printf (x) +#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) print_partial_compiled_pattern (s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) print_double_string (w, s1, sz1, s2, sz2) + + +extern void printchar (); + +/* Print the fastmap in human-readable form. */ + +void +print_fastmap (fastmap) + char *fastmap; +{ + unsigned was_a_range = 0; + unsigned i = 0; + + while (i < (1 << BYTEWIDTH)) + { + if (fastmap[i++]) + { + was_a_range = 0; + printchar (i - 1); + while (i < (1 << BYTEWIDTH) && fastmap[i]) + { + was_a_range = 1; + i++; + } + if (was_a_range) + { + printf ("-"); + printchar (i - 1); + } + } + } + putchar ('\n'); +} + + +/* Print a compiled pattern string in human-readable form, starting at + the START pointer into it and ending just before the pointer END. */ + +void +print_partial_compiled_pattern (start, end) + unsigned char *start; + unsigned char *end; +{ + int mcnt, mcnt2; + unsigned char *p = start; + unsigned char *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { + switch ((re_opcode_t) *p++) + { + case no_op: + printf ("/no_op"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar ('/'); + printchar (*p++); + } + while (--mcnt); + break; + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d/%d", mcnt, *p++); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d/%d", mcnt, *p++); + break; + + case duplicate: + printf ("/duplicate/%d", *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { + register int c; + + printf ("/charset%s", + (re_opcode_t) *(p - 1) == charset_not ? "_not" : ""); + + assert (p + *p < pend); + + for (c = 0; c < *p; c++) + { + unsigned bit; + unsigned char map_byte = p[1 + c]; + + putchar ('/'); + + for (bit = 0; bit < BYTEWIDTH; bit++) + if (map_byte & (1 << bit)) + printchar (c * BYTEWIDTH + bit); + } + p += 1 + *p; + break; + } + + case begline: + printf ("/begline"); + break; + + case endline: + printf ("/endline"); + break; + + case on_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_jump/0/%d", mcnt); + break; + + case on_failure_keep_string_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_keep_string_jump/0/%d", mcnt); + break; + + case dummy_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/dummy_failure_jump/0/%d", mcnt); + break; + + case push_dummy_failure: + printf ("/push_dummy_failure"); + break; + + case maybe_pop_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/maybe_pop_jump/0/%d", mcnt); + break; + + case pop_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/pop_failure_jump/0/%d", mcnt); + break; + + case jump_past_alt: + extract_number_and_incr (&mcnt, &p); + printf ("/jump_past_alt/0/%d", mcnt); + break; + + case jump: + extract_number_and_incr (&mcnt, &p); + printf ("/jump/0/%d", mcnt); + break; + + case succeed_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2); + break; + + case jump_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2); + break; + + case set_number_at: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2); + break; + + case wordbound: + printf ("/wordbound"); + break; + + case notwordbound: + printf ("/notwordbound"); + break; + + case wordbeg: + printf ("/wordbeg"); + break; + + case wordend: + printf ("/wordend"); + +#ifdef emacs + case before_dot: + printf ("/before_dot"); + break; + + case at_dot: + printf ("/at_dot"); + break; + + case after_dot: + printf ("/after_dot"); + break; + + case syntaxspec: + printf ("/syntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; + + case notsyntaxspec: + printf ("/notsyntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; +#endif /* emacs */ + + case wordchar: + printf ("/wordchar"); + break; + + case notwordchar: + printf ("/notwordchar"); + break; + + case begbuf: + printf ("/begbuf"); + break; + + case endbuf: + printf ("/endbuf"); + break; + + default: + printf ("?%d", *(p-1)); + } + } + printf ("/\n"); +} + + +void +print_compiled_pattern (bufp) + struct re_pattern_buffer *bufp; +{ + unsigned char *buffer = bufp->buffer; + + print_partial_compiled_pattern (buffer, buffer + bufp->used); + printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated); + + if (bufp->fastmap_accurate && bufp->fastmap) + { + printf ("fastmap: "); + print_fastmap (bufp->fastmap); + } + + printf ("re_nsub: %d\t", bufp->re_nsub); + printf ("regs_alloc: %d\t", bufp->regs_allocated); + printf ("can_be_null: %d\t", bufp->can_be_null); + printf ("newline_anchor: %d\n", bufp->newline_anchor); + printf ("no_sub: %d\t", bufp->no_sub); + printf ("not_bol: %d\t", bufp->not_bol); + printf ("not_eol: %d\t", bufp->not_eol); + printf ("syntax: %d\n", bufp->syntax); + /* Perhaps we should print the translate table? */ +} + + +void +print_double_string (where, string1, size1, string2, size2) + const char *where; + const char *string1; + const char *string2; + int size1; + int size2; +{ + unsigned this_char; + + if (where == NULL) + printf ("(null)"); + else + { + if (FIRST_STRING_P (where)) + { + for (this_char = where - string1; this_char < size1; this_char++) + printchar (string1[this_char]); + + where = string2; + } + + for (this_char = where - string2; this_char < size2; this_char++) + printchar (string2[this_char]); + } +} + +#else /* not DEBUG */ + +#undef assert +#define assert(e) + +#define DEBUG_STATEMENT(e) +#define DEBUG_PRINT1(x) +#define DEBUG_PRINT2(x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) + +#endif /* not DEBUG */ + +/* 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. */ +reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; + + +/* 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; +} + +/* 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. */ + +static const char *re_error_msg[] = + { NULL, /* REG_NOERROR */ + "No match", /* REG_NOMATCH */ + "Invalid regular expression", /* REG_BADPAT */ + "Invalid collation character", /* REG_ECOLLATE */ + "Invalid character class name", /* REG_ECTYPE */ + "Trailing backslash", /* REG_EESCAPE */ + "Invalid back reference", /* REG_ESUBREG */ + "Unmatched [ or [^", /* REG_EBRACK */ + "Unmatched ( or \\(", /* REG_EPAREN */ + "Unmatched \\{", /* REG_EBRACE */ + "Invalid content of \\{\\}", /* REG_BADBR */ + "Invalid range end", /* REG_ERANGE */ + "Memory exhausted", /* REG_ESPACE */ + "Invalid preceding regular expression", /* REG_BADRPT */ + "Premature end of regular expression", /* REG_EEND */ + "Regular expression too big", /* REG_ESIZE */ + "Unmatched ) or \\)", /* REG_ERPAREN */ + }; + +/* Subroutine declarations and macros for regex_compile. */ + +static void store_op1 (), store_op2 (); +static void insert_op1 (), insert_op2 (); +static boolean at_begline_loc_p (), at_endline_loc_p (); +static boolean group_in_compile_stack (); +static reg_errcode_t compile_range (); + +/* Fetch the next character in the uncompiled pattern---translating it + if necessary. Also cast from a signed character in the constant + string passed to us by the user to an unsigned char that we can use + as an array index (in, e.g., `translate'). */ +#define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + if (translate) c = translate[c]; \ + } while (0) + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +#define PATFETCH_RAW(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + } while (0) + +/* Go backwards one character in the pattern. */ +#define PATUNFETCH p-- + + +/* If `translate' is non-null, return translate[D], else just D. We + cast the subscript to translate because some data is declared as + `char *', to avoid warnings when a string constant is passed. But + when we use a character as a subscript we must make it unsigned. */ +#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) + + +/* Macros for outputting the compiled pattern into `buffer'. */ + +/* If the buffer isn't allocated when it comes in, use this. */ +#define INIT_BUF_SIZE 32 + +/* Make sure we have at least N more bytes of space in buffer. */ +#define GET_BUFFER_SPACE(n) \ + while (b - bufp->buffer + (n) > bufp->allocated) \ + EXTEND_BUFFER () + +/* Make sure we have one more byte of buffer space and then add C to it. */ +#define BUF_PUSH(c) \ + do { \ + GET_BUFFER_SPACE (1); \ + *b++ = (unsigned char) (c); \ + } while (0) + + +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ +#define BUF_PUSH_2(c1, c2) \ + do { \ + GET_BUFFER_SPACE (2); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + } while (0) + + +/* As with BUF_PUSH_2, except for three bytes. */ +#define BUF_PUSH_3(c1, c2, c3) \ + do { \ + GET_BUFFER_SPACE (3); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + *b++ = (unsigned char) (c3); \ + } while (0) + + +/* Store a jump with opcode OP at LOC to location TO. We store a + relative address offset by the three bytes the jump itself occupies. */ +#define STORE_JUMP(op, loc, to) \ + store_op1 (op, loc, (to) - (loc) - 3) + +/* Likewise, for a two-argument jump. */ +#define STORE_JUMP2(op, loc, to, arg) \ + store_op2 (op, loc, (to) - (loc) - 3, arg) + +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP(op, loc, to) \ + insert_op1 (op, loc, (to) - (loc) - 3, b) + +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP2(op, loc, to, arg) \ + insert_op2 (op, loc, (to) - (loc) - 3, arg, b) + + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +#define MAX_BUF_SIZE (1L << 16) + + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +#define EXTEND_BUFFER() \ + do { \ + unsigned char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ + if (bufp->buffer == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_alt_jump) \ + fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ + } while (0) + + +/* Since we have one byte reserved for the register number argument to + {start,stop}_memory, the maximum number of groups we can report + things about is what fits in that byte. */ +#define MAX_REGNUM 255 + +/* But patterns can have more than `MAX_REGNUM' registers. We just + ignore the excess. */ +typedef unsigned regnum_t; + + +/* Macros for the compile stack. */ + +/* Since offsets can go either forwards or backwards, this type needs to + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ +typedef int pattern_offset_t; + +typedef struct +{ + pattern_offset_t begalt_offset; + pattern_offset_t fixup_alt_jump; + pattern_offset_t inner_group_offset; + pattern_offset_t laststart_offset; + regnum_t regnum; +} compile_stack_elt_t; + + +typedef struct +{ + compile_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} compile_stack_type; + + +#define INIT_COMPILE_STACK_SIZE 32 + +#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) + +/* The next available element. */ +#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) + + +/* Set the bit for character C in a list. */ +#define SET_LIST_BIT(c) \ + (b[((unsigned char) (c)) / BYTEWIDTH] \ + |= 1 << (((unsigned char) c) % BYTEWIDTH)) + + +/* Get the next unsigned number in the uncompiled pattern. */ +#define GET_UNSIGNED_NUMBER(num) \ + { if (p != pend) \ + { \ + PATFETCH (c); \ + while (ISDIGIT (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ + } + +#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +#define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) + +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. + Returns one of error codes defined in `regex.h', or zero for success. + + Assumes the `allocated' (and perhaps `buffer') and `translate' + fields are set in BUFP on entry. + + If it succeeds, results are put in BUFP (if it returns an error, the + contents of BUFP are undefined): + `buffer' is the compiled pattern; + `syntax' is set to SYNTAX; + `used' is set to the length of the compiled pattern; + `fastmap_accurate' is zero; + `re_nsub' is the number of subexpressions in PATTERN; + `not_bol' and `not_eol' are zero; + + The `fastmap' and `newline_anchor' fields are neither + examined nor set. */ + +static reg_errcode_t +regex_compile (pattern, size, syntax, bufp) + const char *pattern; + int size; + reg_syntax_t syntax; + struct re_pattern_buffer *bufp; +{ + /* We fetch characters from PATTERN here. Even though PATTERN is + `char *' (i.e., signed), we declare these variables as unsigned, so + they can be reliably used as array indices. */ + register unsigned char c, c1; + + /* A random tempory spot in PATTERN. */ + const char *p1; + + /* Points to the end of the buffer, where we should append. */ + register unsigned char *b; + + /* Keeps track of unclosed groups. */ + compile_stack_type compile_stack; + + /* Points to the current (ending) position in the pattern. */ + const char *p = pattern; + const char *pend = pattern + size; + + /* How to translate the characters in the pattern. */ + char *translate = bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell if a new exact-match + character can be added to that command or if the character requires + a new `exactn' command. */ + unsigned char *pending_exact = 0; + + /* Address of start of the most recently finished expression. + This tells, e.g., postfix * where to find the start of its + operand. Reset at the beginning of groups and alternatives. */ + unsigned char *laststart = 0; + + /* Address of beginning of regexp, or inside of last group. */ + unsigned char *begalt; + + /* Place in the uncompiled pattern (i.e., the {) to + which to go back if the interval is invalid. */ + const char *beg_interval; + + /* Address of the place where a forward jump should go to the end of + the containing expression. Each alternative of an `or' -- except the + last -- ends with a forward jump of this sort. */ + unsigned char *fixup_alt_jump = 0; + + /* Counts open-groups as they are encountered. Remembered for the + matching close-group on the compile stack, so the same register + number is put in the stop_memory as the start_memory. */ + regnum_t regnum = 0; + +#ifdef DEBUG + DEBUG_PRINT1 ("\nCompiling pattern: "); + if (debug) + { + unsigned debug_count; + + for (debug_count = 0; debug_count < size; debug_count++) + printchar (pattern[debug_count]); + putchar ('\n'); + } +#endif /* DEBUG */ + + /* Initialize the compile stack. */ + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); + if (compile_stack.stack == NULL) + return REG_ESPACE; + + compile_stack.size = INIT_COMPILE_STACK_SIZE; + compile_stack.avail = 0; + + /* Initialize the pattern buffer. */ + bufp->syntax = syntax; + bufp->fastmap_accurate = 0; + bufp->not_bol = bufp->not_eol = 0; + + /* Set `used' to zero, so that if we return an error, the pattern + printer (for debugging) will think there's no pattern. We reset it + at the end. */ + bufp->used = 0; + + /* Always count groups, whether or not bufp->no_sub is set. */ + bufp->re_nsub = 0; + +#if !defined (emacs) && !defined (SYNTAX_TABLE) + /* Initialize the syntax table. */ + init_syntax_once (); +#endif + + if (bufp->allocated == 0) + { + if (bufp->buffer) + { /* 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. */ + RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); + } + else + { /* Caller did not allocate a buffer. Do it for them. */ + bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); + } + if (!bufp->buffer) return REG_ESPACE; + + bufp->allocated = INIT_BUF_SIZE; + } + + begalt = b = bufp->buffer; + + /* Loop through the uncompiled pattern until we're at the end. */ + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '^': + { + if ( /* If at start of pattern, it's an operator. */ + p == pattern + 1 + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's come before. */ + || at_begline_loc_p (pattern, p, syntax)) + BUF_PUSH (begline); + else + goto normal_char; + } + break; + + + case '$': + { + if ( /* If at end of pattern, it's an operator. */ + p == pend + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's next. */ + || at_endline_loc_p (p, pend, syntax)) + BUF_PUSH (endline); + else + goto normal_char; + } + break; + + + case '+': + case '?': + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern... */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + return REG_BADRPT; + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + + { + /* Are we optimizing this jump? */ + boolean keep_string_p = false; + + /* 1 means zero (many) matches is allowed. */ + char zero_times_ok = 0, many_times_ok = 0; + + /* If there is a sequence of repetition chars, collapse it + down to just one (the right one). We can't combine + interval operators with these because of, e.g., `a{2}*', + which should only match an even number of `a's. */ + + for (;;) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + + if (p == pend) + break; + + PATFETCH (c); + + if (c == '*' + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) + ; + + else if (syntax & RE_BK_PLUS_QM && c == '\\') + { + if (p == pend) return REG_EESCAPE; + + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + + c = c1; + } + else + { + PATUNFETCH; + break; + } + + /* If we get here, we found another repeat character. */ + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { /* More than one repetition is allowed, so put in at the + end a backward relative jump from `b' to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). + + But if we are at the `*' in the exact sequence `.*\n', + insert an unconditional jump backwards to the ., + instead of the beginning of the loop. This way we only + push a failure point once, instead of every time + through the loop. */ + assert (p - 1 > pattern); + + /* Allocate the space for the jump. */ + GET_BUFFER_SPACE (3); + + /* We know we are not at the first character of the pattern, + because laststart was nonzero. And we've already + incremented `p', by the way, to be the character after + the `*'. Do we have to do something analogous here + for null bytes, because of RE_DOT_NOT_NULL? */ + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') + && zero_times_ok + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') + && !(syntax & RE_DOT_NEWLINE)) + { /* We have .*\n. */ + STORE_JUMP (jump, b, laststart); + keep_string_p = true; + } + else + /* Anything else. */ + STORE_JUMP (maybe_pop_jump, b, laststart - 3); + + /* We've added more stuff to the buffer. */ + b += 3; + } + + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump + : on_failure_jump, + laststart, b + 3); + pending_exact = 0; + b += 3; + + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); + b += 3; + } + } + break; + + + case '.': + laststart = b; + BUF_PUSH (anychar); + break; + + + case '[': + { + boolean had_char_class = false; + + if (p == pend) return REG_EBRACK; + + /* Ensure that we have enough space to push a charset: the + opcode, the length count, and the bitset; 34 bytes in all. */ + GET_BUFFER_SPACE (34); + + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* Push the number of bytes in the bitmap. */ + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + + /* Clear the whole map. */ + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-2] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + SET_LIST_BIT ('\n'); + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) return REG_EBRACK; + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) return REG_EESCAPE; + + PATFETCH (c1); + SET_LIST_BIT (c1); + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + return REG_ERANGE; + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret + = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) return ret; + } + + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + + ret = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) return ret; + } + + /* See if we're at the beginning of a possible character + class. */ + + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) return REG_EBRACK; + + for (;;) + { + PATFETCH (c); + if (c == ':' || c == ']' || p == pend + || c1 == CHAR_CLASS_MAX_LENGTH) + break; + str[c1++] = c; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and:`]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') + { + int ch; + boolean is_alnum = STREQ (str, "alnum"); + boolean is_alpha = STREQ (str, "alpha"); + boolean is_blank = STREQ (str, "blank"); + boolean is_cntrl = STREQ (str, "cntrl"); + boolean is_digit = STREQ (str, "digit"); + boolean is_graph = STREQ (str, "graph"); + boolean is_lower = STREQ (str, "lower"); + boolean is_print = STREQ (str, "print"); + boolean is_punct = STREQ (str, "punct"); + boolean is_space = STREQ (str, "space"); + boolean is_upper = STREQ (str, "upper"); + boolean is_xdigit = STREQ (str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) return REG_ECTYPE; + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) return REG_EBRACK; + + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) + { + if ( (is_alnum && ISALNUM (ch)) + || (is_alpha && ISALPHA (ch)) + || (is_blank && ISBLANK (ch)) + || (is_cntrl && ISCNTRL (ch)) + || (is_digit && ISDIGIT (ch)) + || (is_graph && ISGRAPH (ch)) + || (is_lower && ISLOWER (ch)) + || (is_print && ISPRINT (ch)) + || (is_punct && ISPUNCT (ch)) + || (is_space && ISSPACE (ch)) + || (is_upper && ISUPPER (ch)) + || (is_xdigit && ISXDIGIT (ch))) + SET_LIST_BIT (ch); + } + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + had_char_class = false; + } + } + else + { + had_char_class = false; + SET_LIST_BIT (c); + } + } + + /* Discard any (non)matching list bytes that are all 0 at the + end of the map. Decrease the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; + } + break; + + + case '(': + if (syntax & RE_NO_BK_PARENS) + goto handle_open; + else + goto normal_char; + + + case ')': + if (syntax & RE_NO_BK_PARENS) + goto handle_close; + else + goto normal_char; + + + case '\n': + if (syntax & RE_NEWLINE_ALT) + goto handle_alt; + else + goto normal_char; + + + case '|': + if (syntax & RE_NO_BK_VBAR) + goto handle_alt; + else + goto normal_char; + + + case '{': + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) + goto handle_interval; + else + goto normal_char; + + + case '\\': + if (p == pend) return REG_EESCAPE; + + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW (c); + + switch (c) + { + case '(': + if (syntax & RE_NO_BK_PARENS) + goto normal_backslash; + + handle_open: + bufp->re_nsub++; + regnum++; + + if (COMPILE_STACK_FULL) + { + RETALLOC (compile_stack.stack, compile_stack.size << 1, + compile_stack_elt_t); + if (compile_stack.stack == NULL) return REG_ESPACE; + + compile_stack.size <<= 1; + } + + /* These are the values to restore when we hit end of this + group. They are all relative offsets, so that if the + whole pattern moves because of realloc, they will still + be valid. */ + COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; + COMPILE_STACK_TOP.fixup_alt_jump + = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; + COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; + COMPILE_STACK_TOP.regnum = regnum; + + /* We will eventually replace the 0 with the number of + groups inner to this one. But do not push a + start_memory for groups beyond the last one we can + represent in the compiled pattern. */ + if (regnum <= MAX_REGNUM) + { + COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; + BUF_PUSH_3 (start_memory, regnum, 0); + } + + compile_stack.avail++; + + fixup_alt_jump = 0; + laststart = 0; + begalt = b; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + break; + + + case ')': + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; + + if (COMPILE_STACK_EMPTY) + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_backslash; + else + return REG_ERPAREN; + + handle_close: + if (fixup_alt_jump) + { /* Push a dummy failure point at the end of the + alternative for a possible future + `pop_failure_jump' to pop. See comments at + `push_dummy_failure' in `re_match_2'. */ + BUF_PUSH (push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); + } + + /* See similar code for backslashed left paren above. */ + if (COMPILE_STACK_EMPTY) + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_char; + else + return REG_ERPAREN; + + /* Since we just checked for an empty stack above, this + ``can't happen''. */ + assert (compile_stack.avail != 0); + { + /* We don't just want to restore into `regnum', because + later groups should continue to be numbered higher, + as in `(ab)c(de)' -- the second group is #2. */ + regnum_t this_group_regnum; + + compile_stack.avail--; + begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; + fixup_alt_jump + = COMPILE_STACK_TOP.fixup_alt_jump + ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 + : 0; + laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; + this_group_regnum = COMPILE_STACK_TOP.regnum; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + + /* We're at the end of the group, so now we know how many + groups were inside this one. */ + if (this_group_regnum <= MAX_REGNUM) + { + unsigned char *inner_group_loc + = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; + + *inner_group_loc = regnum - this_group_regnum; + BUF_PUSH_3 (stop_memory, this_group_regnum, + regnum - this_group_regnum); + } + } + break; + + + case '|': /* `\|'. */ + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) + goto normal_backslash; + handle_alt: + if (syntax & RE_LIMITED_OPS) + goto normal_char; + + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (on_failure_jump, begalt, b + 6); + pending_exact = 0; + b += 3; + + /* The alternative before this one has a jump after it + which gets executed if it gets matched. Adjust that + jump so it will jump to this alternative's analogous + jump (put in below, which in turn will jump to the next + (if any) alternative's such jump, etc.). The last such + jump jumps to the correct final destination. A picture: + _____ _____ + | | | | + | v | v + a | b | c + + If we are at `b', then fixup_alt_jump right now points to a + three-byte space after `a'. We'll put in the jump, set + fixup_alt_jump to right after `b', and leave behind three + bytes which we'll fill in when we get to after `c'. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + /* Mark and leave space for a jump after this alternative, + to be filled in later either by next alternative or + when know we're at the end of a series of alternatives. */ + fixup_alt_jump = b; + GET_BUFFER_SPACE (3); + b += 3; + + laststart = 0; + begalt = b; + break; + + + case '{': + /* If \{ is a literal. */ + if (!(syntax & RE_INTERVALS) + /* If we're at `\{' and it's not the open-interval + operator. */ + || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + || (p - 2 == pattern && p == pend)) + goto normal_backslash; + + handle_interval: + { + /* If got here, then the syntax allows intervals. */ + + /* At least (most) this many matches must be made. */ + int lower_bound = -1, upper_bound = -1; + + beg_interval = p - 1; + + if (p == pend) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_EBRACE; + } + + GET_UNSIGNED_NUMBER (lower_bound); + + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) upper_bound = RE_DUP_MAX; + } + else + /* Interval such as `{1}' => match exactly once. */ + upper_bound = lower_bound; + + if (lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_BADBR; + } + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (c != '\\') return REG_EBRACE; + + PATFETCH (c); + } + + if (c != '}') + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_BADBR; + } + + /* We just parsed a valid interval. */ + + /* If it's invalid to have no preceding re. */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + return REG_BADRPT; + else if (syntax & RE_CONTEXT_INDEP_OPS) + laststart = b; + else + goto unfetch_interval; + } + + /* If the upper bound is zero, don't want to succeed at + all; jump from `laststart' to `b + 3', which will be + the end of the buffer after we insert the jump. */ + if (upper_bound == 0) + { + GET_BUFFER_SPACE (3); + INSERT_JUMP (jump, laststart, b + 3); + b += 3; + } + + /* Otherwise, we have a nontrivial interval. When + we're all done, the pattern will look like: + set_number_at <jump count> <upper bound> + set_number_at <succeed_n count> <lower bound> + succeed_n <after jump addr> <succed_n count> + <body of loop> + jump_n <succeed_n addr> <jump count> + (The upper bound and `jump_n' are omitted if + `upper_bound' is 1, though.) */ + else + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned nbytes = 10 + (upper_bound > 1) * 10; + + GET_BUFFER_SPACE (nbytes); + + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + INSERT_JUMP2 (succeed_n, laststart, + b + 5 + (upper_bound > 1) * 5, + lower_bound); + b += 5; + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + insert_op2 (set_number_at, laststart, 5, lower_bound, b); + b += 5; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + STORE_JUMP2 (jump_n, b, laststart + 5, + upper_bound - 1); + b += 5; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + insert_op2 (set_number_at, laststart, b - laststart, + upper_bound - 1, b); + b += 5; + } + } + pending_exact = 0; + beg_interval = NULL; + } + break; + + unfetch_interval: + /* If an invalid interval, match the characters as literals. */ + assert (beg_interval); + p = beg_interval; + beg_interval = NULL; + + /* normal_char and normal_backslash need `c'. */ + PATFETCH (c); + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (p > pattern && p[-1] == '\\') + goto normal_backslash; + } + goto normal_char; + +#ifdef emacs + /* There is no way to specify the before_dot and after_dot + operators. rms says this is ok. --karl */ + case '=': + BUF_PUSH (at_dot); + break; + + case 's': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); + break; +#endif /* emacs */ + + + case 'w': + laststart = b; + BUF_PUSH (wordchar); + break; + + + case 'W': + laststart = b; + BUF_PUSH (notwordchar); + break; + + + case '<': + BUF_PUSH (wordbeg); + break; + + case '>': + BUF_PUSH (wordend); + break; + + case 'b': + BUF_PUSH (wordbound); + break; + + case 'B': + BUF_PUSH (notwordbound); + break; + + case '`': + BUF_PUSH (begbuf); + break; + + case '\'': + BUF_PUSH (endbuf); + 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) + goto normal_char; + + c1 = c - '0'; + + if (c1 > regnum) + return REG_ESUBREG; + + /* Can't back reference to a subexpression if inside of it. */ + if (group_in_compile_stack (compile_stack, c1)) + goto normal_char; + + laststart = b; + BUF_PUSH_2 (duplicate, c1); + break; + + + case '+': + case '?': + if (syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backslash; + + default: + normal_backslash: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + c = TRANSLATE (c); + goto normal_char; + } + break; + + + default: + /* Expects the character in `c'. */ + normal_char: + /* If no exactn currently being built. */ + if (!pending_exact + + /* If last exactn not at current position. */ + || pending_exact + *pending_exact + 1 != b + + /* We have only one byte following the exactn for the count. */ + || *pending_exact == (1 << BYTEWIDTH) - 1 + + /* If followed by a repetition operator. */ + || *p == '*' || *p == '^' + || ((syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((syntax & RE_INTERVALS) + && ((syntax & RE_NO_BK_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + /* Start building a new exactn. */ + + laststart = b; + + BUF_PUSH_2 (exactn, 0); + pending_exact = b - 1; + } + + BUF_PUSH (c); + (*pending_exact)++; + break; + } /* switch (c) */ + } /* while p != pend */ + + + /* Through the pattern now. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + if (!COMPILE_STACK_EMPTY) + return REG_EPAREN; + + free (compile_stack.stack); + + /* We have succeeded; set the length of the buffer. */ + bufp->used = b - bufp->buffer; + +#ifdef DEBUG + if (debug) + { + DEBUG_PRINT1 ("\nCompiled pattern: "); + print_compiled_pattern (bufp); + } +#endif /* DEBUG */ + + return REG_NOERROR; +} /* regex_compile */ + +/* Subroutines for `regex_compile'. */ + +/* Store OP at LOC followed by two-byte integer parameter ARG. */ + +static void +store_op1 (op, loc, arg) + re_opcode_t op; + unsigned char *loc; + int arg; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg); +} + + +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +store_op2 (op, loc, arg1, arg2) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg1); + STORE_NUMBER (loc + 3, arg2); +} + + +/* Copy the bytes from LOC to END to open up three bytes of space at LOC + for OP followed by two-byte integer parameter ARG. */ + +static void +insert_op1 (op, loc, arg, end) + re_opcode_t op; + unsigned char *loc; + int arg; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 3; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op1 (op, loc, arg); +} + + +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +insert_op2 (op, loc, arg1, arg2, end) + re_opcode_t op; + unsigned char *loc; + int arg1, arg2; + unsigned char *end; +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 5; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op2 (op, loc, arg1, arg2); +} + + +/* P points to just after a ^ in PATTERN. Return true if that ^ comes + after an alternative or a begin-subexpression. We assume there is at + least one character before the ^. */ + +static boolean +at_begline_loc_p (pattern, p, syntax) + const char *pattern, *p; + reg_syntax_t syntax; +{ + const char *prev = p - 2; + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; + + return + /* After a subexpression? */ + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) + /* After an alternative? */ + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); +} + + +/* The dual of at_begline_loc_p. This one is for $. We assume there is + at least one character after the $, i.e., `P < PEND'. */ + +static boolean +at_endline_loc_p (p, pend, syntax) + const char *p, *pend; + int syntax; +{ + const char *next = p; + boolean next_backslash = *next == '\\'; + const char *next_next = p + 1 < pend ? p + 1 : NULL; + + return + /* Before a subexpression? */ + (syntax & RE_NO_BK_PARENS ? *next == ')' + : next_backslash && next_next && *next_next == ')') + /* Before an alternative? */ + || (syntax & RE_NO_BK_VBAR ? *next == '|' + : next_backslash && next_next && *next_next == '|'); +} + + +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and + false if it's not. */ + +static boolean +group_in_compile_stack (compile_stack, regnum) + compile_stack_type compile_stack; + regnum_t regnum; +{ + int this_element; + + for (this_element = compile_stack.avail - 1; + this_element >= 0; + this_element--) + if (compile_stack.stack[this_element].regnum == regnum) + return true; + + return false; +} + + +/* Read the ending character of a range (in a bracket expression) from the + uncompiled pattern *P_PTR (which ends at PEND). We assume the + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) + Then we set the translation of all bits between the starting and + ending characters (inclusive) in the compiled pattern B. + + Return an error code. + + We use these short variable names so we can use the same macros as + `regex_compile' itself. */ + +static reg_errcode_t +compile_range (p_ptr, pend, translate, syntax, b) + const char **p_ptr, *pend; + char *translate; + reg_syntax_t syntax; + unsigned char *b; +{ + unsigned this_char; + + const char *p = *p_ptr; + int range_start, range_end; + + if (p == pend) + return REG_ERANGE; + + /* Even though the pattern is a signed `char *', we need to fetch + with unsigned char *'s; if the high bit of the pattern character + is set, the range endpoints will be negative if we fetch using a + signed char *. + + We also want to fetch the endpoints without translating them; the + appropriate translation is done in the bit-setting loop below. */ + range_start = ((unsigned char *) p)[-2]; + range_end = ((unsigned char *) p)[0]; + + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + /* If the start is after the end, the range is empty. */ + if (range_start > range_end) + return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + + /* Here we see why `this_char' has to be larger than an `unsigned + char' -- the range is inclusive, so if `range_end' == 0xff + (assuming 8-bit characters), we would otherwise go into an infinite + loop, since all characters <= 0xff. */ + for (this_char = range_start; this_char <= range_end; this_char++) + { + SET_LIST_BIT (TRANSLATE (this_char)); + } + + return REG_NOERROR; +} + +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +#ifndef INIT_FAILURE_ALLOC +#define INIT_FAILURE_ALLOC 5 +#endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_SPACE each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ +int re_max_failures = 2000; + +typedef const unsigned char *fail_stack_elt_t; + +typedef struct +{ + fail_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} fail_stack_type; + +#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) + + +/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ + +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (fail_stack_elt_t *) \ + REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE requires `destination' be declared. */ + +#define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ + ? 0 \ + : ((fail_stack).stack = (fail_stack_elt_t *) \ + REGEX_REALLOCATE ((fail_stack).stack, \ + (fail_stack).size * sizeof (fail_stack_elt_t), \ + ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push PATTERN_OP on FAIL_STACK. + + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +#define PUSH_PATTERN_OP(pattern_op, fail_stack) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (fail_stack)) \ + ? 0 \ + : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ + 1)) + +/* This pushes an item onto the failure stack. Must be a four-byte + value. Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_ITEM(item) \ + fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item + +/* The complement operation. Assumes `fail_stack' is nonempty. */ +#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +#ifdef DEBUG +#define DEBUG_PUSH PUSH_FAILURE_ITEM +#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () +#else +#define DEBUG_PUSH(item) +#define DEBUG_POP(item_addr) +#endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be + declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + int this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + PUSH_FAILURE_ITEM (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + PUSH_FAILURE_ITEM (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ + PUSH_FAILURE_ITEM (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ + PUSH_FAILURE_ITEM (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_ITEM (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_ITEM (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +/* This is the number of items that are pushed and popped on the stack + for each register. */ +#define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +#ifdef DEBUG +#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +#else +#define NUM_NONREG_ITEMS 4 +#endif + +/* We push at most this many items on the stack. */ +#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +#define NUM_FAILURE_ITEMS \ + ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ + +#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ + int this_reg; \ + const unsigned char *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_ITEM (); \ + if (string_temp != NULL) \ + str = (const char *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (unsigned char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ + \ + low_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ + \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ + \ + regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + } \ + \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible + characters can start a string that matches the pattern. This fastmap + is used by re_search to skip quickly over impossible starting points. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as BUFP->fastmap. + + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in + the pattern buffer. + + Returns 0 if we succeed, -2 if an internal error. */ + +int +re_compile_fastmap (bufp) + struct re_pattern_buffer *bufp; +{ + int j, k; + fail_stack_type fail_stack; +#ifndef REGEX_MALLOC + char *destination; +#endif + /* We don't push any register information onto the failure stack. */ + unsigned num_regs = 0; + + register char *fastmap = bufp->fastmap; + unsigned char *pattern = bufp->buffer; + unsigned long size = bufp->used; + const unsigned char *p = pattern; + register unsigned char *pend = pattern + size; + + /* Assume that each path through the pattern can be null until + proven otherwise. We set this false at the bottom of switch + statement, to which we get only if a particular path doesn't + match the empty string. */ + boolean path_can_be_null = true; + + /* We aren't doing a `succeed_n' to begin with. */ + boolean succeed_n_p = false; + + assert (fastmap != NULL && p != NULL); + + INIT_FAIL_STACK (); + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ + bufp->fastmap_accurate = 1; /* It will be when we're done. */ + bufp->can_be_null = 0; + + while (p != pend || !FAIL_STACK_EMPTY ()) + { + if (p == pend) + { + bufp->can_be_null |= path_can_be_null; + + /* Reset for next path. */ + path_can_be_null = true; + + p = fail_stack.stack[--fail_stack.avail]; + } + + /* We should never be about to go beyond the end of the pattern. */ + assert (p < pend); + +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + + /* I guess the idea here is to simply not bother with a fastmap + if a backreference is used, since it's too hard to figure out + the fastmap for the corresponding group. Setting + `can_be_null' stops `re_search_2' from using the fastmap, so + that is all we do. */ + case duplicate: + bufp->can_be_null = 1; + return 0; + + + /* Following are the cases which match a character. These end + with `break'. */ + + case exactn: + fastmap[p[1]] = 1; + break; + + + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + fastmap[j] = 1; + break; + + + case charset_not: + /* Chars beyond end of map must be allowed. */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + fastmap[j] = 1; + break; + + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; + + + case anychar: + /* `.' matches anything ... */ + for (j = 0; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + /* ... except perhaps newline. */ + if (!(bufp->syntax & RE_DOT_NEWLINE)) + fastmap['\n'] = 0; + + /* Return if we have already set `can_be_null'; if we have, + then the fastmap is irrelevant. Something's wrong here. */ + else if (bufp->can_be_null) + return 0; + + /* Otherwise, have to check alternative paths. */ + break; + + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + /* All cases after this match the empty string. These end with + `continue'. */ + + + case before_dot: + case at_dot: + case after_dot: + continue; +#endif /* not emacs */ + + + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case push_dummy_failure: + continue; + + + case jump_n: + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + + /* Jump backward implies we just went through the body of a + loop and matched nothing. Opcode jumped to should be + `on_failure_jump' or `succeed_n'. Just treat it like an + ordinary jump. For a * loop, it has pushed its failure + point already; if so, discard that as redundant. */ + if ((re_opcode_t) *p != on_failure_jump + && (re_opcode_t) *p != succeed_n) + continue; + + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + + /* If what's on the stack is where we are now, pop it. */ + if (!FAIL_STACK_EMPTY () + && fail_stack.stack[fail_stack.avail - 1] == p) + fail_stack.avail--; + + continue; + + + case on_failure_jump: + case on_failure_keep_string_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + + /* For some patterns, e.g., `(a?)?', `p+j' here points to the + end of the pattern. We don't want to push such a point, + since when we restore it above, entering the switch will + increment `p' past the end of the pattern. We don't need + to push such a point since we obviously won't find any more + fastmap entries beyond `pend'. Such a pattern can match + the null string, though. */ + if (p + j < pend) + { + if (!PUSH_PATTERN_OP (p + j, fail_stack)) + return -2; + } + else + bufp->can_be_null = 1; + + if (succeed_n_p) + { + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + succeed_n_p = false; + } + + continue; + + + case succeed_n: + /* Get to the number of times to succeed. */ + p += 2; + + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 4; + succeed_n_p = true; /* Spaghetti code alert. */ + goto handle_on_failure_jump; + } + continue; + + + case set_number_at: + p += 4; + continue; + + + case start_memory: + case stop_memory: + p += 2; + continue; + + + default: + abort (); /* We have listed all the cases. */ + } /* switch *p++ */ + + /* Getting here means we have found the possible starting + characters for one path of the pattern -- and that the empty + string does not match. We need not follow this path further. + Instead, look at the next alternative (remembered on the + stack), or quit if no more. The test at the top of the loop + does these things. */ + path_can_be_null = false; + p = pend; + } /* while p */ + + /* Set `can_be_null' for the last path (also the first path, if the + pattern is empty). */ + bufp->can_be_null |= path_can_be_null; + return 0; +} /* re_compile_fastmap */ + +/* 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; + } +} + +/* Searching routines. */ + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search (bufp, string, size, startpos, range, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, startpos, range; + struct re_registers *regs; +{ + return re_search_2 (bufp, NULL, 0, string, size, startpos, range, + regs, size); +} + + +/* Using the compiled pattern in BUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. + + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. + + RANGE is how far to scan while trying to match. RANGE = 0 means try + only at STARTPOS; in general, the last start tried is STARTPOS + + RANGE. + + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire BUFP->buffer and its contained + subexpressions. + + Do not consider matching one past the index STOP in the virtual + concatenation of STRING1 and STRING2. + + We return either the position in the strings at which the match was + found, -1 if no match, or -2 if error (such as failure + stack overflow). */ + +int +re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int startpos; + int range; + struct re_registers *regs; + int stop; +{ + int val; + register char *fastmap = bufp->fastmap; + register char *translate = bufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; + + /* Check for out-of-range STARTPOS. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up RANGE if it might eventually take us outside + the virtual concatenation of STRING1 and STRING2. */ + if (endpos < -1) + range = -1 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) + { + if (startpos > 0) + return -1; + else + range = 1; + } + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + + /* Loop through the string, looking for a place to start matching. */ + for (;;) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot be the start of a match. If the pattern can match the + null string, however, we don't need to skip characters; we want + the first null string. */ + if (fastmap && startpos < total_size && !bufp->can_be_null) + { + if (range > 0) /* Searching forwards. */ + { + register const char *d; + register int lim = 0; + int irange = range; + + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; + + /* Written out as an if-else to avoid testing `translate' + inside the loop. */ + if (translate) + while (range > lim + && !fastmap[(unsigned char) + translate[(unsigned char) *d++]]) + range--; + else + while (range > lim && !fastmap[(unsigned char) *d++]) + range--; + + startpos += irange - range; + } + else /* Searching backwards. */ + { + register char c = (size1 == 0 || startpos >= size1 + ? string2[startpos - size1] + : string1[startpos]); + + if (!fastmap[(unsigned char) TRANSLATE (c)]) + goto advance; + } + } + + /* If can't match the null string, and that's all we have left, fail. */ + if (range >= 0 && startpos == total_size && fastmap + && !bufp->can_be_null) + return -1; + + val = re_match_2 (bufp, string1, size1, string2, size2, + startpos, regs, stop); + if (val >= 0) + return startpos; + + if (val == -2) + return -2; + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } + return -1; +} /* re_search_2 */ + +/* Declarations and macros for re_match_2. */ + +static int bcmp_translate (); +static boolean alt_match_null_string_p (), + common_op_match_null_string_p (), + group_match_null_string_p (); + +/* Structure for per-register (a.k.a. per-group) information. + This must not be longer than one word, because we push this value + onto the failure stack. Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ +typedef union +{ + fail_stack_elt_t word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +#define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} register_info_type; + +#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +#define IS_ACTIVE(R) ((R).bits.is_active) +#define MATCHED_SOMETHING(R) ((R).bits.matched_something) +#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +#define SET_REGS_MATCHED() \ + do \ + { \ + unsigned r; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + while (0) + + +/* This converts PTR, a pointer into one of the search strings `string1' + and `string2' into an offset from the beginning of that string. */ +#define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1) + +/* Registers are set to a sentinel when they haven't yet matched. */ +#define REG_UNSET_VALUE ((char *) -1) +#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + + +/* Macros for dealing with the split strings in re_match_2. */ + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ +#define PREFETCH() \ + while (d == dend) \ + { \ + /* End of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + + +/* Test if at very beginning or at very end of the virtual concatenation + of `string1' and `string2'. If only one string, it's `string2'. */ +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END(d) ((d) == end2) + + +/* Test if D points to a character which is word-constituent. We have + two special cases to check for: if past the end of string1, look at + the first character in string2; and if before the beginning of + string2, look at the last character in string1. */ +#define WORDCHAR_P(d) \ + (SYNTAX ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + == Sword) + +/* Test if the character before D and the one at D differ with respect + to being word-constituent. */ +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) + + +/* Free everything we malloc. */ +#ifdef REGEX_MALLOC +#define FREE_VAR(var) if (var) free (var); var = NULL +#define FREE_VARIABLES() \ + do { \ + FREE_VAR (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + } while (0) +#else /* not REGEX_MALLOC */ +/* Some MIPS systems (at least) want this to free alloca'd storage. */ +#define FREE_VARIABLES() alloca (0) +#endif /* not REGEX_MALLOC */ + + +/* These values must meet several constraints. They must not be valid + register values; since we have a limit of 255 registers (because + we use only one byte in the pattern for the register number), we can + use numbers larger than 255. They must differ by 1, because of + NUM_FAILURE_ITEMS above. And the value for the lowest register must + be larger than the value for the highest register, so we do not try + to actually save any registers when none are active. */ +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) + +/* Matching routines. */ + +#ifndef emacs /* Emacs never uses this. */ +/* re_match is like re_match_2 except it takes only a single string. */ + +int +re_match (bufp, string, size, pos, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, pos; + struct re_registers *regs; + { + return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size); +} +#endif /* not emacs */ + + +/* re_match_2 matches the compiled pattern in BUFP against the + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 + and SIZE2, respectively). We start matching at POS, and stop + matching at STOP. + + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we + store offsets for the substring each group matched in REGS. See the + documentation for exactly how many groups we fill. + + We return -1 if no match, -2 if an internal error (such as the + failure stack overflowing). Otherwise, we return the length of the + matched substring. */ + +int +re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int size1, size2; + int pos; + struct re_registers *regs; + int stop; +{ + /* General temporaries. */ + int mcnt; + unsigned char *p1; + + /* Just past the end of the corresponding string. */ + const char *end1, *end2; + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + const char *end_match_1, *end_match_2; + + /* Where we are in the data, and the end of the current string. */ + const char *d, *dend; + + /* Where we are in the pattern, and the end of the pattern. */ + unsigned char *p = bufp->buffer; + register unsigned char *pend = p + bufp->used; + + /* We use this to map every character in the string. */ + char *translate = bufp->translate; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to + the subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where + to resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is + a ``dummy''; if a failure happens and the failure point is a dummy, + it gets discarded and the next next one is tried. */ + fail_stack_type fail_stack; +#ifdef DEBUG + static unsigned failure_id = 0; + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; +#endif + + /* We fill all the registers internally, independent of what we + return, for use in backreferences. The number here includes + an element for register zero. */ + unsigned num_regs = bufp->re_nsub + 1; + + /* The currently active registers. */ + unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG; + unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG; + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ + const char **regstart, **regend; + + /* If a group that's operated upon by a repetition operator fails to + match anything, then the register for its start will need to be + restored because it will have been set to wherever in the string we + are when we last see its open-group operator. Similarly for a + register's end. */ + const char **old_regstart, **old_regend; + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ + register_info_type *reg_info; + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + unsigned best_regs_set = false; + const char **best_regstart, **best_regend; + + /* Logically, this is `best_regend[0]'. But we don't want to have to + allocate space for that if we're not allocating space for anything + else (see below). Also, we never need info about register 0 for + any of the other register vectors, and it seems rather a kludge to + treat `best_regend' differently than the rest. So we keep track of + the end of the best match so far in a separate variable. We + initialize this to NULL so that when we backtrack the first time + and need to test it, it's not garbage. */ + const char *match_end = NULL; + + /* Used when we pop values we don't care about. */ + const char **reg_dummy; + register_info_type *reg_info_dummy; + +#ifdef DEBUG + /* Counts the total number of registers pushed. */ + unsigned num_regs_pushed = 0; +#endif + + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + + INIT_FAIL_STACK (); + + /* Do not bother to initialize all the register variables if there are + no groups in the pattern, as it takes a fair amount of time. If + there are groups, we include space for register 0 (the whole + pattern), even though we never use it, since it simplifies the + array indexing. We should fix this. */ + if (bufp->re_nsub) + { + regstart = REGEX_TALLOC (num_regs, const char *); + regend = REGEX_TALLOC (num_regs, const char *); + old_regstart = REGEX_TALLOC (num_regs, const char *); + old_regend = REGEX_TALLOC (num_regs, const char *); + best_regstart = REGEX_TALLOC (num_regs, const char *); + best_regend = REGEX_TALLOC (num_regs, const char *); + reg_info = REGEX_TALLOC (num_regs, register_info_type); + reg_dummy = REGEX_TALLOC (num_regs, const char *); + reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); + + if (!(regstart && regend && old_regstart && old_regend && reg_info + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) + { + FREE_VARIABLES (); + return -2; + } + } +#ifdef REGEX_MALLOC + else + { + /* We must initialize all our variables to NULL, so that + `FREE_VARIABLES' doesn't try to free them. */ + regstart = regend = old_regstart = old_regend = best_regstart + = best_regend = reg_dummy = NULL; + reg_info = reg_info_dummy = (register_info_type *) NULL; + } +#endif /* REGEX_MALLOC */ + + /* The starting position is bogus. */ + if (pos < 0 || pos > size1 + size2) + { + FREE_VARIABLES (); + return -1; + } + + /* Initialize subexpression text positions to -1 to mark ones that no + start_memory/stop_memory has been seen for. Also initialize the + register information struct. */ + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = regend[mcnt] + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; + + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + /* We move `string1' into `string2' if the latter's empty -- but not if + `string1' is null. */ + if (size2 == 0 && string1 != NULL) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ + if (stop <= size1) + { + end_match_1 = string1 + stop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + stop - size1; + } + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. `d' + is advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal `string2'. */ + if (size1 > 0 && pos <= size1) + { + d = string1 + pos; + dend = end_match_1; + } + else + { + d = string2 + pos - size1; + dend = end_match_2; + } + + DEBUG_PRINT1 ("The compiled pattern is: "); + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); + DEBUG_PRINT1 ("The string to match is: `"); + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); + DEBUG_PRINT1 ("'\n"); + + /* This loops over pattern commands. It exits by returning from the + function if the match is complete, or it drops through if the match + fails at this starting point in the input data. */ + for (;;) + { + DEBUG_PRINT2 ("\n0x%x: ", p); + + if (p == pend) + { /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); + + /* If we haven't matched the entire string, and we want the + longest match, try backtracking. */ + if (d != end_match_2) + { + DEBUG_PRINT1 ("backtracking.\n"); + + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ + boolean same_str_p = (FIRST_STRING_P (match_end) + == MATCHING_IN_FIRST_STRING); + + /* If exceeds best match so far, save it. */ + if (!best_regs_set + || (same_str_p && d > match_end) + || (!same_str_p && !MATCHING_IN_FIRST_STRING)) + { + best_regs_set = true; + match_end = d; + + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + + /* If no failure points, don't restore garbage. */ + else if (best_regs_set) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } /* d != end_match_2 */ + + DEBUG_PRINT1 ("Accepting match.\n"); + + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) + { + /* Have the register data arrays been allocated? */ + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ + regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->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 (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + } + } + else + assert (bufp->regs_allocated == REGS_FIXED); + + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; + regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1 + : d - string2 + size1); + } + + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ + for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++) + { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { + regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]); + } + } + + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + } /* regs && !bufp->no_sub */ + + FREE_VARIABLES (); + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); + + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + + return mcnt; + } + + /* Otherwise match next pattern command. */ +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case no_op: + DEBUG_PRINT1 ("EXECUTING no_op.\n"); + break; + + + /* Match the next n pattern characters exactly. The following + byte in the pattern defines n, and the n bytes after that + are the characters to match. */ + case exactn: + mcnt = *p++; + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); + + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH (); + if (translate[(unsigned char) *d++] != (char) *p++) + goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH (); + if (*d++ != (char) *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED (); + break; + + + /* Match any character except possibly a newline or a null. */ + case anychar: + DEBUG_PRINT1 ("EXECUTING anychar.\n"); + + PREFETCH (); + + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) + goto fail; + + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%d'.\n", *d); + d++; + break; + + + case charset: + case charset_not: + { + register unsigned char c; + boolean not = (re_opcode_t) *(p - 1) == charset_not; + + DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + + PREFETCH (); + c = TRANSLATE (*d); /* The character to match. */ + + /* Cast to `unsigned' instead of `unsigned char' in case the + bit list is a full 32 bytes long. */ + if (c < (unsigned) (*p * BYTEWIDTH) + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; + + SET_REGS_MATCHED (); + d++; + break; + } + + + /* The beginning of a group is represented by start_memory. + The arguments are the register number in the next byte, and the + number of groups inner to this one in the next. The text + matched within the group is recorded (in the internal + registers data structure) under the register number. */ + case start_memory: + DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); + + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = group_match_null_string_p (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + DEBUG_PRINT2 (" old_regstart: %d\n", + POINTER_TO_OFFSET (old_regstart[*p])); + + regstart[*p] = d; + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); + + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* This is the new highest active register. */ + highest_active_reg = *p; + + /* If nothing was active before, this is the new lowest active + register. */ + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *p; + + /* Move past the register number and inner group count. */ + p += 2; + break; + + + /* The stop_memory opcode represents the end of a group. Its + arguments are the same as start_memory's: the register + number, and the number of inner groups. */ + case stop_memory: + DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); + + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + DEBUG_PRINT2 (" old_regend: %d\n", + POINTER_TO_OFFSET (old_regend[*p])); + + regend[*p] = d; + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); + + /* This register isn't active anymore. */ + IS_ACTIVE (reg_info[*p]) = 0; + + /* If this was the only register active, nothing is active + anymore. */ + if (lowest_active_reg == highest_active_reg) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + { /* We must scan for the new highest active register, since + it isn't necessarily one less than now: consider + (a(b)c(d(e)f)g). When group 3 ends, after the f), the + new highest active register is 1. */ + unsigned char r = *p - 1; + while (r > 0 && !IS_ACTIVE (reg_info[r])) + r--; + + /* If we end up at register zero, that means that we saved + the registers as the result of an `on_failure_jump', not + a `start_memory', and we jumped to past the innermost + `stop_memory'. For example, in ((.)*) we save + registers 1 and 2 as a result of the *, but when we pop + back to the second ), we are at the stop_memory 1. + Thus, nothing is active. */ + if (r == 0) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + highest_active_reg = r; + } + + /* If just failed to match something this time around with a + group that's operated on by a repetition operator, try to + force exit from the ``loop'', and restore the register + information for this group that we had before trying this + last match. */ + if ((!MATCHED_SOMETHING (reg_info[*p]) + || (re_opcode_t) p[-3] == start_memory) + && (p + 2) < pend) + { + boolean is_a_jump_n = false; + + p1 = p + 2; + mcnt = 0; + switch ((re_opcode_t) *p1++) + { + case jump_n: + is_a_jump_n = true; + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (is_a_jump_n) + p1 += 2; + break; + + default: + /* do nothing */ ; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump right before the start_memory + corresponding to this stop_memory, exit from the loop + by forcing a failure after pushing on the stack the + on_failure_jump's jump in the pattern, and d. */ + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump + && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) + { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) + { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < *p + *(p + 1); r++) + { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if ((int) old_regend[r] >= (int) regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); + + goto fail; + } + } + + /* Move past the register number and the inner group count. */ + p += 2; + break; + + + /* \<digit> has been turned into a `duplicate' command which is + followed by the numeric value of <digit> as the register number. */ + case duplicate: + { + register const char *d2, *dend2; + int regno = *p++; /* Get which register to match against. */ + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); + + /* Can't back reference a group which we've never matched. */ + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) + goto fail; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((FIRST_STRING_P (regstart[regno]) + == FIRST_STRING_P (regend[regno])) + ? regend[regno] : end_match_1); + for (;;) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + + /* End of string1 => advance to string2. */ + d2 = string2; + dend2 = regend[regno]; + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH (); + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? bcmp_translate (d, d2, mcnt, translate) + : bcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + } + } + break; + + + /* begline matches the empty string at the beginning of the string + (unless `not_bol' is set in `bufp'), and, if + `newline_anchor' is set, after newlines. */ + case begline: + DEBUG_PRINT1 ("EXECUTING begline.\n"); + + if (AT_STRINGS_BEG (d)) + { + if (!bufp->not_bol) break; + } + else if (d[-1] == '\n' && bufp->newline_anchor) + { + break; + } + /* In all other cases, we fail. */ + goto fail; + + + /* endline is the dual of begline. */ + case endline: + DEBUG_PRINT1 ("EXECUTING endline.\n"); + + if (AT_STRINGS_END (d)) + { + if (!bufp->not_eol) break; + } + + /* We have to ``prefetch'' the next character. */ + else if ((d == end1 ? *string2 : *d) == '\n' + && bufp->newline_anchor) + { + break; + } + goto fail; + + + /* Match at the very beginning of the data. */ + case begbuf: + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); + if (AT_STRINGS_BEG (d)) + break; + goto fail; + + + /* Match at the very end of the data. */ + case endbuf: + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); + if (AT_STRINGS_END (d)) + break; + goto fail; + + + /* on_failure_keep_string_jump is used to optimize `.*\n'. It + pushes NULL as the value for the string on the stack. Then + `pop_failure_point' will keep the current value for the + string, instead of restoring it. To see why, consider + matching `foo\nbar' against `.*\n'. The .* matches the foo; + then the . fails against the \n. But the next thing we want + to do is match the \n against the \n; if we restored the + string value, we would be back at the foo. + + Because this is used only in specific cases, we don't need to + check all the things that `on_failure_jump' does, to make + sure the right things get saved on the stack. Hence we don't + share its code. The only reason to push anything on the + stack at all is that otherwise we would have to change + `anychar's code to do something besides goto fail in this + case; that seems worse than this. */ + case on_failure_keep_string_jump: + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); + + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); + break; + + + /* Uses of on_failure_jump: + + Each alternative starts with an on_failure_jump that points + to the beginning of the next alternative. Each alternative + except the last ends with a jump that in effect jumps past + the rest of the alternatives. (They really jump to the + ending jump of the following alternative, because tensioning + these jumps is a hassle.) + + Repeats start with an on_failure_jump that points past both + the repetition text and either the following jump or + pop_failure_jump back to this on_failure_jump. */ + case on_failure_jump: + on_failure: + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); + + /* If this on_failure_jump comes right before a group (i.e., + the original * applied to a group), save the information + for that group and all inner ones, so that if we fail back + to this point, the group's information will be correct. + For example, in \(a*\)*\1, we need the preceding group, + and in \(\(a*\)b*\)\2, we need the inner group. */ + + /* We can't use `p' to check ahead because we push + a failure point to `p + mcnt' after we do this. */ + p1 = p; + + /* We need to skip no_op's before we look for the + start_memory in case this on_failure_jump is happening as + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 + against aba. */ + while (p1 < pend && (re_opcode_t) *p1 == no_op) + p1++; + + if (p1 < pend && (re_opcode_t) *p1 == start_memory) + { + /* We have a new highest active register now. This will + get reset at the start_memory we are about to get to, + but we will have saved all the registers relevant to + this repetition op, as described above. */ + highest_active_reg = *(p1 + 1) + *(p1 + 2); + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *(p1 + 1); + } + + DEBUG_PRINT1 (":\n"); + PUSH_FAILURE_POINT (p + mcnt, d, -2); + break; + + + /* A smart repeat ends with `maybe_pop_jump'. + We change it to either `pop_failure_jump' or `jump'. */ + case maybe_pop_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); + { + register unsigned char *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. */ + while (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; /* Skip over args, too. */ + + /* If we're at the end of the pattern, we can change. */ + if (p2 == pend) + { + /* Consider what happens when matching ":\(.*\)" + against ":/". I don't really understand this code + yet. */ + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 + (" End of pattern: change to `pop_failure_jump'.\n"); + } + + else if ((re_opcode_t) *p2 == exactn + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) + { + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; + p1 = p + mcnt; + + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ + if ((re_opcode_t) p1[3] == exactn && p1[5] != c) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset + || (re_opcode_t) p1[3] == charset_not) + { + int not = (re_opcode_t) p1[3] == charset_not; + + if (c < (unsigned char) (p1[4] * BYTEWIDTH) + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + /* `not' is equal to 1 if c would match, which means + that we can't change to pop_failure_jump. */ + if (!not) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + } + p -= 2; /* Point at relative address again. */ + if ((re_opcode_t) p[-1] != pop_failure_jump) + { + p[-1] = (unsigned char) jump; + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } + /* Note fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to + its matching on_failure_jump, where the latter will push a + failure point. The pop_failure_jump takes off failure + points put on by this pop_failure_jump's matching + on_failure_jump; we got through the pattern to here from the + matching on_failure_jump, so didn't fail. */ + case pop_failure_jump: + { + /* We need to pass separate storage for the lowest and + highest registers, even though we don't care about the + actual values. Otherwise, we will restore only one + register from the stack, since lowest will == highest in + `pop_failure_point'. */ + unsigned dummy_low_reg, dummy_high_reg; + unsigned char *pdummy; + const char *sdummy; + + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); + POP_FAILURE_POINT (sdummy, pdummy, + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } + /* Note fall through. */ + + + /* Unconditionally jump (without popping any failure points). */ + case jump: + unconditional_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); + p += mcnt; /* Do the jump. */ + DEBUG_PRINT2 ("(to 0x%x).\n", p); + break; + + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); + goto unconditional_jump; + + + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at pop_failure_jump. We will end up at + pop_failure_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for pop_failure_jump to pop. */ + case dummy_failure_jump: + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); + /* It doesn't matter what we push for the string here. What + the code at `fail' tests is the value for the pattern. */ + PUSH_FAILURE_POINT (0, 0, -2); + goto unconditional_jump; + + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `pop_failure_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT (0, 0, -2); + break; + + /* Have to succeed matching what follows at least n times. + After that, handle like `on_failure_jump'. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); + + assert (mcnt >= 0); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) + { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR (p, mcnt); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt); + } + else if (mcnt == 0) + { + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); + p[2] = (unsigned char) no_op; + p[3] = (unsigned char) no_op; + goto on_failure; + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); + + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER (p + 2, mcnt); + goto unconditional_jump; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + break; + + case set_number_at: + { + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); + STORE_NUMBER (p1, mcnt); + break; + } + + case wordbound: + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + break; + goto fail; + + case notwordbound: + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + goto fail; + break; + + case wordbeg: + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); + if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + break; + goto fail; + + case wordend: + DEBUG_PRINT1 ("EXECUTING wordend.\n"); + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) + && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) + break; + goto fail; + +#ifdef emacs +#ifdef emacs19 + case before_dot: + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) >= point) + goto fail; + break; + + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) != point) + goto fail; + break; + + case after_dot: + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) <= point) + goto fail; + break; +#else /* not emacs19 */ + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point) + goto fail; + break; +#endif /* not emacs19 */ + + case syntaxspec: + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchsyntax; + + case wordchar: + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); + mcnt = (int) Sword; + matchsyntax: + PREFETCH (); + if (SYNTAX (*d++) != (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + + case notsyntaxspec: + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchnotsyntax; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); + mcnt = (int) Sword; + matchnotsyntax: + PREFETCH (); + if (SYNTAX (*d++) == (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + +#else /* not emacs */ + case wordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); + PREFETCH (); + if (!WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); + PREFETCH (); + if (WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; +#endif /* not emacs */ + + default: + abort (); + } + continue; /* Successfully executed one pattern command; keep going. */ + + + /* We goto here if a matching operation fails. */ + fail: + if (!FAIL_STACK_EMPTY ()) + { /* A restart point is known. Restore to that state. */ + DEBUG_PRINT1 ("\nFAIL:\n"); + POP_FAILURE_POINT (d, p, + lowest_active_reg, highest_active_reg, + regstart, regend, reg_info); + + /* If this failure point is a dummy, try the next one. */ + if (!p) + goto fail; + + /* If we failed to the end of the pattern, don't examine *p. */ + assert (p <= pend); + if (p < pend) + { + boolean is_a_jump_n = false; + + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + switch ((re_opcode_t) *p) + { + case jump_n: + is_a_jump_n = true; + case maybe_pop_jump: + case pop_failure_jump: + case jump: + p1 = p + 1; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) + || (!is_a_jump_n + && (re_opcode_t) *p1 == on_failure_jump)) + goto fail; + break; + default: + /* do nothing */ ; + } + } + + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else + break; /* Matching at this starting point really fails. */ + } /* for (;;) */ + + if (best_regs_set) + goto restore_best_regs; + + FREE_VARIABLES (); + + return -1; /* Failure to match. */ +} /* re_match_2 */ + +/* Subroutine definitions for re_match_2. */ + + +/* We are passed P pointing to a register number after a start_memory. + + Return true if the pattern up to the corresponding stop_memory can + match the empty string, and false otherwise. + + If we find the matching stop_memory, sets P to point to one past its number. + Otherwise, sets P to an undefined byte less than or equal to END. + + We don't handle duplicates properly (yet). */ + +static boolean +group_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + /* Point to after the args to the start_memory. */ + unsigned char *p1 = *p + 2; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and return true or + false, as appropriate, when we get to one that can't, or to the + matching stop_memory. */ + + switch ((re_opcode_t) *p1) + { + /* Could be either a loop or a series of alternatives. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + /* If the next operation is not a jump backwards in the + pattern. */ + + if (mcnt >= 0) + { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': + + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c + + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ + + + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ + + while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) + { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ + + if (!alt_match_null_string_p (p1, p1 + mcnt - 3, + reg_info)) + return false; + + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; + + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((re_opcode_t) *p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) + { + /* Get to the beginning of the n-th alternative. */ + p1 -= 3; + break; + } + } + + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - 2); + + if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) + return false; + + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ + break; + + + case stop_memory: + assert (p1[1] == **p); + *p = p1 + 2; + return true; + + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return false; +} /* group_match_null_string_p */ + + +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: + It expects P to be the first byte of a single alternative and END one + byte past the last. The alternative can contain groups. */ + +static boolean +alt_match_null_string_p (p, end, reg_info) + unsigned char *p, *end; + register_info_type *reg_info; +{ + int mcnt; + unsigned char *p1 = p; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and break when we get + to one that can't. */ + + switch ((re_opcode_t) *p1) + { + /* It's a loop. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + break; + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return true; +} /* alt_match_null_string_p */ + + +/* Deals with the ops common to group_match_null_string_p and + alt_match_null_string_p. + + Sets P to one after the op and its arguments, if any. */ + +static boolean +common_op_match_null_string_p (p, end, reg_info) + unsigned char **p, *end; + register_info_type *reg_info; +{ + int mcnt; + boolean ret; + int reg_no; + unsigned char *p1 = *p; + + switch ((re_opcode_t) *p1++) + { + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbeg: + case wordend: + case wordbound: + case notwordbound: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + break; + + case start_memory: + reg_no = *p1; + assert (reg_no > 0 && reg_no <= MAX_REGNUM); + ret = group_match_null_string_p (&p1, end, reg_info); + + /* Have to set this here in case we're checking a group which + contains a group and a back reference to it. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; + + if (!ret) + return false; + break; + + /* If this is an optimized succeed_n for zero times, make the jump. */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (mcnt >= 0) + p1 += mcnt; + else + return false; + break; + + case succeed_n: + /* Get to the number of times to succeed. */ + p1 += 2; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt == 0) + { + p1 -= 4; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + } + else + return false; + break; + + case duplicate: + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) + return false; + break; + + case set_number_at: + p1 += 4; + + default: + /* All other opcodes mean we cannot match the empty string. */ + return false; + } + + *p = p1; + return true; +} /* common_op_match_null_string_p */ + + +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN + bytes; nonzero otherwise. */ + +static int +bcmp_translate (s1, s2, len, translate) + unsigned char *s1, *s2; + register int len; + char *translate; +{ + register unsigned char *p1 = s1, *p2 = s2; + while (len) + { + if (translate[*p1++] != translate[*p2++]) return 1; + len--; + } + return 0; +} + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length SIZE) 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. + + We call regex_compile to do the actual compilation. */ + +const char * +re_compile_pattern (pattern, length, bufp) + const char *pattern; + int length; + struct re_pattern_buffer *bufp; +{ + reg_errcode_t ret; + + /* GNU code is written to assume at least RE_NREGS registers will be set + (and at least one extra will be -1). */ + bufp->regs_allocated = REGS_UNALLOCATED; + + /* 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. */ + bufp->no_sub = 0; + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = regex_compile (pattern, length, re_syntax_options, bufp); + + return re_error_msg[(int) ret]; +} + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them if this is an Emacs or POSIX compilation. */ + +#if !defined (emacs) && !defined (_POSIX_SOURCE) + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +re_comp (s) + const char *s; +{ + reg_errcode_t ret; + + if (!s) + { + if (!re_comp_buf.buffer) + return "No previous regular expression"; + return 0; + } + + if (!re_comp_buf.buffer) + { + re_comp_buf.buffer = (unsigned char *) malloc (200); + if (re_comp_buf.buffer == NULL) + return "Memory exhausted"; + re_comp_buf.allocated = 200; + + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + if (re_comp_buf.fastmap == NULL) + return "Memory exhausted"; + } + + /* 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 = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + + /* Yes, we're discarding `const' here. */ + return (char *) re_error_msg[(int) ret]; +} + + +int +re_exec (s) + const char *s; +{ + const int len = strlen (s); + return + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); +} +#endif /* not emacs and not _POSIX_SOURCE */ + +/* POSIX.2 functions. Don't define these for Emacs. */ + +#ifndef emacs + +/* 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' and `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 *preg; + const char *pattern; + int cflags; +{ + reg_errcode_t ret; + unsigned syntax + = (cflags & REG_EXTENDED) ? + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; + + /* regex_compile will allocate the space for the compiled pattern. */ + preg->buffer = 0; + preg->allocated = 0; + + /* Don't bother to use a fastmap when searching. This simplifies the + REG_NEWLINE case: if we used a fastmap, we'd have to put all the + characters after newlines into the fastmap. This way, we just try + every character. */ + preg->fastmap = 0; + + if (cflags & REG_ICASE) + { + unsigned i; + + preg->translate = (char *) malloc (CHAR_SET_SIZE); + if (preg->translate == NULL) + return (int) REG_ESPACE; + + /* Map uppercase characters to corresponding lowercase ones. */ + for (i = 0; i < CHAR_SET_SIZE; i++) + preg->translate[i] = ISUPPER (i) ? tolower (i) : i; + } + else + preg->translate = NULL; + + /* 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); + + /* POSIX says a null character in the pattern terminates it, so we + can use strlen here in compiling the pattern. */ + ret = regex_compile (pattern, strlen (pattern), syntax, preg); + + /* 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; + + return (int) ret; +} + + +/* 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 *preg; + const char *string; + size_t nmatch; + regmatch_t pmatch[]; + int eflags; +{ + int ret; + struct re_registers regs; + regex_t private_preg; + int len = strlen (string); + boolean want_reg_info = !preg->no_sub && nmatch > 0; + + private_preg = *preg; + + private_preg.not_bol = !!(eflags & REG_NOTBOL); + private_preg.not_eol = !!(eflags & REG_NOTEOL); + + /* The user has told us exactly how many registers to return + information about, via `nmatch'. We have to pass that on to the + matching routines. */ + private_preg.regs_allocated = REGS_FIXED; + + if (want_reg_info) + { + regs.num_regs = nmatch; + regs.start = TALLOC (nmatch, regoff_t); + regs.end = TALLOC (nmatch, regoff_t); + if (regs.start == NULL || regs.end == NULL) + return (int) REG_NOMATCH; + } + + /* Perform the searching operation. */ + ret = re_search (&private_preg, string, len, + /* start: */ 0, /* range: */ len, + want_reg_info ? ®s : (struct re_registers *) 0); + + /* Copy the register information to the POSIX structure. */ + if (want_reg_info) + { + if (ret >= 0) + { + unsigned r; + + for (r = 0; r < nmatch; r++) + { + pmatch[r].rm_so = regs.start[r]; + pmatch[r].rm_eo = regs.end[r]; + } + } + + /* If we needed the temporary register info, free the space now. */ + free (regs.start); + free (regs.end); + } + + /* We want zero return to mean success, unlike `re_search'. */ + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; +} + + +/* 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 *preg; + char *errbuf; + size_t errbuf_size; +{ + const char *msg; + size_t msg_size; + + if (errcode < 0 + || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[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 = re_error_msg[errcode]; + + /* POSIX doesn't require that we do anything in this case, but why + not be nice. */ + if (! msg) + msg = "Success"; + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (errbuf_size != 0) + { + if (msg_size > errbuf_size) + { + strncpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; + } + else + strcpy (errbuf, msg); + } + + return msg_size; +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (preg) + regex_t *preg; +{ + if (preg->buffer != NULL) + free (preg->buffer); + preg->buffer = NULL; + + preg->allocated = 0; + preg->used = 0; + + if (preg->fastmap != NULL) + free (preg->fastmap); + preg->fastmap = NULL; + preg->fastmap_accurate = 0; + + if (preg->translate != NULL) + free (preg->translate); + preg->translate = NULL; +} + +#endif /* not emacs */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/gnu/lib/regex-0.12/regex.h b/gnu/lib/regex-0.12/regex.h new file mode 100644 index 00000000000..408dd210348 --- /dev/null +++ b/gnu/lib/regex-0.12/regex.h @@ -0,0 +1,490 @@ +/* Definitions for data structures and routines for the regular + expression library, version 0.12. + + Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef __REGEXP_LIBRARY_H__ +#define __REGEXP_LIBRARY_H__ + +/* POSIX says that <sys/types.h> must be included (by the caller) before + <regex.h>. */ + +#ifdef VMS +/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it + should be there. */ +#include <stddef.h> +#endif + + +/* 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 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 (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) + +/* 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. */ +extern 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_UNMATCHED_RIGHT_PAREN_ORD) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS) + +#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) + +/* 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) + +/* 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_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS + replaces RE_CONTEXT_INDEP_OPS 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 +#define RE_DUP_MAX ((1 << 15) - 1) + + +/* 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) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ + 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, /* Not implemented. */ + 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. */ + +struct re_pattern_buffer +{ +/* [[[begin 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 allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long 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. */ + char *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; + +/* [[[end pattern_buffer]]] */ +}; + +typedef struct re_pattern_buffer regex_t; + + +/* search.c (search_buffer) in Emacs needs this one opcode value. It is + defined both in `regex.c' and here. */ +#define RE_EXACTN_VALUE 1 + +/* 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. */ + +/* To avoid duplicating every routine declaration -- once with a + prototype (if we are ANSI), and once without (if we aren't) -- we + use the following macro to declare argument types. This + unfortunately clutters up the declarations a bit, but I think it's + worth it. */ + +#if __STDC__ + +#define _RE_ARGS(args) args + +#else /* not __STDC__ */ + +#define _RE_ARGS(args) () + +#endif /* not __STDC__ */ + +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the `re_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax _RE_ARGS ((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. */ +extern const char *re_compile_pattern + _RE_ARGS ((const char *pattern, int 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. */ +extern int re_compile_fastmap _RE_ARGS ((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). */ +extern int re_search + _RE_ARGS ((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. */ +extern int re_search_2 + _RE_ARGS ((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. */ +extern int re_match + _RE_ARGS ((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'. */ +extern int re_match_2 + _RE_ARGS ((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. */ +extern void re_set_registers + _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends)); + +/* 4.2 bsd compatibility. */ +extern char *re_comp _RE_ARGS ((const char *)); +extern int re_exec _RE_ARGS ((const char *)); + +/* POSIX compatibility. */ +extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags)); +extern int regexec + _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags)); +extern size_t regerror + _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf, + size_t errbuf_size)); +extern void regfree _RE_ARGS ((regex_t *preg)); + +#endif /* not __REGEXP_LIBRARY_H__ */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ |
