cvs vendor branch: restore local regex source files vendor/CVS
authorJohn Marino <draco@marino.st>
Sat, 7 May 2011 11:23:46 +0000 (13:23 +0200)
committerJohn Marino <draco@marino.st>
Sat, 7 May 2011 16:01:56 +0000 (18:01 +0200)
15 files changed:
contrib/cvs-1.12/ABOUT-NLS [deleted file]
contrib/cvs-1.12/AUTHORS [deleted file]
contrib/cvs-1.12/BUGS [deleted file]
contrib/cvs-1.12/DEVEL-CVS [deleted file]
contrib/cvs-1.12/HACKING [deleted file]
contrib/cvs-1.12/INSTALL [deleted file]
contrib/cvs-1.12/MINOR-BUGS [deleted file]
contrib/cvs-1.12/NEWS [deleted file]
contrib/cvs-1.12/PROJECTS [deleted file]
contrib/cvs-1.12/TODO [deleted file]
contrib/cvs-1.12/lib/regcomp.c [new file with mode: 0644]
contrib/cvs-1.12/lib/regex.c [new file with mode: 0644]
contrib/cvs-1.12/lib/regex_internal.c [new file with mode: 0644]
contrib/cvs-1.12/lib/regex_internal.h [new file with mode: 0644]
contrib/cvs-1.12/lib/regexec.c [new file with mode: 0644]

diff --git a/contrib/cvs-1.12/ABOUT-NLS b/contrib/cvs-1.12/ABOUT-NLS
deleted file mode 100644 (file)
index da27fad..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-Automake started requiring this file after I included the gettext support from
-GNULIB <http://savannah.gnu.org/projects/gnulib>.  I'm not sure why, exactly,
-but there was an nls.m4 macro I had to import which claims that NLS stands for
-"Native Language Support".  If someone would like to replace this ABOUT-NLS
-file with a more appropriate one, please do.
diff --git a/contrib/cvs-1.12/AUTHORS b/contrib/cvs-1.12/AUTHORS
deleted file mode 100644 (file)
index 938d55a..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-Authors of GNU CVS
-
-The conflict-resolution algorithms and much of the administrative file
-definitions of CVS were based on the original package written by Dick Grune
-at Vrije Universiteit in Amsterdam <dick@cs.vu.nl>, and posted to
-comp.sources.unix in the volume 6 release sometime in 1986.  This original
-version was a collection of shell scripts.  I am thankful that Dick made
-his work available.
-
-Brian Berliner from Prisma, Inc. (now at Sun Microsystems, Inc.)
-<berliner@sun.com> converted the original CVS shell scripts into reasonably
-fast C and added many, many features to support software release control
-functions.  See the manual page in the "man" directory.  A copy of the
-USENIX article presented at the Winter 1990 USENIX Conference, Washington
-D.C., is included in the "doc" directory.
-
-Jeff Polk from BSDI <polk@bsdi.com> converted the CVS 1.2
-sources into much more readable and maintainable C code.  He also added a
-whole lot of functionality and modularity to the code in the process.
-See the bottom of the NEWS file (from about 1992).
-
-david d `zoo' zuhn <zoo@armadillo.com> contributed the working base code
-for CVS 1.4 Alpha.  His work carries on from work done by K. Richard Pixley
-and others at Cygnus Support.  The CVS 1.4 upgrade is due in large part to
-Zoo's efforts.
-
-David G. Grubbs <dgg@odi.com> contributed the CVS "history" and "release"
-commands.  As well as the ever-so-useful "-n" option of CVS which tells CVS
-to show what it would do, without actually doing it.  He also contributed
-support for the .cvsignore file.
-
-The Free Software Foundation (GNU) contributed most of the portability
-framework that CVS now uses.  This can be found in the "configure" script,
-the Makefile's, and basically most of the "lib" directory.
-
-K. Richard Pixley, Cygnus Support <rich@cygnus.com> contributed many bug
-fixes/enhancement as well as completing early reviews of the CVS 1.3 manual
-pages.
-
-Roland Pesch, then of Cygnus Support <roland@wrs.com> contributed
-brand new cvs(1) and cvs(5) manual pages.  Thanks to him for saving us
-from poor use of our language!
-
-Paul Sander, HaL Computer Systems, Inc. <paul@hal.com> wrote and
-contributed the code in lib/sighandle.c.  I added support for POSIX, BSD,
-and non-POSIX/non-BSD systems.
-
-Jim Kingdon and others at Cygnus Support <info@cygnus.com> wrote the
-remote repository access code.
-
-Larry Jones and Derek Price <derek@ximbiot.com> have been maintaining and
-enhancing CVS for some years.  Mark D. Baushke <mdb@gnu.org> came on in
-2003.
-
-Conrad Pino <Conrad@Pino.com> began maintaining the Windows port in 2004.
-
-There have been many, many contributions not listed here.  Consult the
-individual ChangeLog files in each directory for a more complete idea.
-
-In addition to the above contributors, the following Beta testers
-deserve special mention for their support.  This is only a partial
-list; if you have helped in this way and would like to be listed, let
-bug-cvs know (as described in the Cederqvist manual).
-
-       Mark D. Baushke <mdb@cisco.com>
-       Per Cederqvist <ceder@signum.se>
-       J.T. Conklin <jtc@cygnus.com>
-       Vince DeMarco <vdemarco@fdcsrvr.cs.mci.com>
-       Paul Eggert <eggert@twinsun.com>
-       Lal George <george@research.att.com>
-       Dean E. Hardi <Dean.E.Hardi@ccmail.jpl.nasa.gov>
-       Mike Heath <mike@pencom.com>
-       Jim Kingdon <kingdon@cygnus.com>
-       Bernd Leibing <bernd.leibing@rz.uni-ulm.de>
-       Benedict Lofstedt <benedict@tusc.com.au>
-       Dave Love <d.love@dl.ac.uk>
-       Robert Lupton the Good <rhl@astro.princeton.edu>
-       Tom McAliney <tom@hilco.com>
-       Eberhard Mattes <mattes@azu.informatik.uni-stuttgart.de>
-       Jim Meyering <meyering@comco.com>
-       Thomas Mohr <mohr@lts.sel.alcatel.de>
-       Thomas Nilsson <thoni@softlab.se>
-       Raye Raskin <raye.raskin@lia.com>
-       Harlan Stenn <harlan@landmark.com>
-       Gunnar Tornblom <gunnar.tornblom@senet.abb.se>
-       Greg A. Woods <woods@planix.com>
-
-Many contributors have added code to the "contrib" directory.  See the
-README file there for a list of what is available.  There is also a
-contributed GNU Emacs CVS-mode in tools/pcl-cvs.
diff --git a/contrib/cvs-1.12/BUGS b/contrib/cvs-1.12/BUGS
deleted file mode 100644 (file)
index 382ba5f..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-See the Cederqvist manual (cvs.texinfo) for information on how to
-report bugs (and what will happen to your bug reports if you do).
-
-The following is a list of some of the known bugs.  It may or may not
-be comprehensive.  We would dearly love for people to volunteer to
-help us keep it up to date (for starters, if you notice any
-inaccuracies, please let bug-cvs know as described in the Cederqvist
-manual).  There are some other reported bugs in MINOR-BUGS; the
-difference, at least in theory, is that those bugs are less serious.
-
-
-* For platform-specific information (in some cases including known
-bugs), see README.VMS, windows-NT/README, or os2/README.  There is no
-similar file for the unix-like operating systems (not yet, at least).
-This file also might contain some platform-specific bugs.
-
-
-* If your login name contains a space or various other characters
-(particularly an issue on Windows), CVS will have trouble (it will
-write invalid RCS files, probably).  The fix would be to have CVS
-change such characters to underscores before writing them to the RCS
-file.  Furthermore, the LOGNAME or USER environment variables usually
-won't override the system login name, so this can be hard to work
-around.
-
-
-* If you specify the -w global option to client/server CVS, it only
-overrides a CVSREAD environment variable set on the client, not a
-CVSREAD variable which was set on the server (for example, in .bashrc
-when the server was run via rsh).  The fix of course will be to
-provide a "Option-read-write" request which sends -w, in addition to
-"Global_option -r" which sends -r.
-
-
-* Symbolic links to files will not work with or without LockDir.  In the
-repository, you should avoid using symbolic links to files since this issue
-can cause data loss.  Symlinks are only a problem when writing files.  If your
-repository does not allow any write access, symlinks are not a problem.
-
-
-* Symbolic links to directories will not work with LockDir.  In the
-repository, you should avoid using symbolic links to directories if
-you intend to use LockDir as the correct directory will NOT be locked
-by CVS during write.  Directory symlinks are not recommended, but should work
-as long as LockDir is not being used.  Symlinks are only a problem when
-writing files.  If your repository does not allow any write access, symlinks
-are never a problem, whether or not LockDir is in use.
-
-
-* The -m option to "cvs add" does not work with client/server CVS.
-CVS will accept the option, but it won't actually set the
-file's description.
-
-
-* cvs update walks into a user's work directory if there's a directory
-  of the same name in the repository even if the user's directory
-  doesn't yet have a CVS admin sub-directory.  This can greatly confuse
-  users who try to add the same directory at nearly the same time.
-
-
-* From: "Charles M. Hannum" <mycroft@ai.mit.edu>
-  To: info-cvs@prep.ai.mit.edu
-  Subject: Still one more bug
-  Date: Sat, 25 Feb 1995 17:01:15 -0500
-  
-  mycroft@duality [1]; cd /usr/src/lib/libc
-  mycroft@duality [1]; cvs diff -C2 '-D1 day ago' -Dnow
-  cvs server: Diffing .
-  cvs server: Diffing DB
-  cvs [server aborted]: could not chdir to DB: No such file or directory
-  mycroft@duality [1];
-  
-  `DB' is an old directory, which no longer has files in it, and is
-  removed automatically when I use the `-P' option to checkout.
-  
-  This error doesn't occur when run locally.
-  
-  P.S.  Is anyone working on fixing these bugs?
-
-
-* CVS does not always seem to be waiting to the next filesystem timestamp
-quanta after commits.  So far this has only shown up in testing under the BSDI
-OS.  The symptoms are that ocassionally CVS will not notice that modified files
-are modified, though the file must be modified within a short time after the
-commit, probably milliseconds or seconds, for this symptom to be noticed.  One
-suspected cause is that one of the calls to sleep_past() is being called with
-an incorrect value, though this does not explain why symptoms have only been
-noticed under BSDI.
-
-
-* The CVS server is leaving a temp directory (/tmp/cvs-serv*) on AIX 4.3 under
-very rare circumstances (one out of c. 10,500 test cases).  This appears to be
-dependent on some sort of race condition as it disappears with tracing enabled
-and under the debugger.  Informative feedback is welcome.
-
-
-* UNICOS 9.0 on Cray currently fails testing in both client/server and
-  writeproxy modes.
-
-
-* Status
-
-  This experimental version of CVS contains new features which may not have
-  been tested as thoroughly as the stable release.  It is classified as:
-
-                          /*-------------.
-                          | Experimental |
-                          `-------------*/
-
-                     /*-------------------------.
-                     | Sane for full scale use. |
-                     `-------------------------*/
-
diff --git a/contrib/cvs-1.12/DEVEL-CVS b/contrib/cvs-1.12/DEVEL-CVS
deleted file mode 100644 (file)
index cf4e3a7..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-                        CVS Development Policies
-
-This file, DEVEL-CVS, contains the policies by which the CVS
-development group operates.  Also see the HACKING file.
-
-----------------------------------------------------------------------
-Policies regarding the CVS source repository:
-
-By checking items into the repository, developers agree to permit
-distribution of such items under the terms of the GNU Public License.
-
-----------------------------------------------------------------------
-Procedure for dealing with people who want to be developers:
-
-People who want checkin access are first requested to send
-patches and have them reviewed by a developer.  If they submit some
-good ones (preferably over a period of time, to demonstrate sustained
-interest), then one of the developers can ask the other CVS
-developers, usually via the bug-cvs@nongnu.org mailing list, whether it
-is OK to make this person a developer (after first sending the
-prospective developer a copy of this file and then having the
-prospective developer say they want to be a developer).  If there are
-no objections, the person will be made a developer.
-
-----------------------------------------------------------------------
-Policy regarding checkout-only access:
-
-Checkout-only access to the CVS repository is available to all, on an
-anonymous basis (no need for registration or other complications).
-The exact technical mechanisms by which it is available are not
-covered by this policy.
diff --git a/contrib/cvs-1.12/HACKING b/contrib/cvs-1.12/HACKING
deleted file mode 100644 (file)
index e294576..0000000
+++ /dev/null
@@ -1,453 +0,0 @@
-How to write code for CVS
-
-* License of CVS
-
-    CVS is Copyright (C) 1989-2005 The 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 1, or (at your option)
-    any later version.
-
-    More details are available in the COPYING file but, in simplified
-    terms, this means that any distributed modifications you make to
-    this software must also be released under the GNU General Public
-    License.
-
-    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.
-
-* Source
-
-Patches against the development version of CVS are most likely to be accepted:
-
-       $ export CVS_RSH="ssh"
-       $ cvs -z3 -d:ext:anoncvs@savannah.nongnu.org:/cvsroot/cvs co ccvs
-
-* Compiler options
-
-If you are using GCC, you'll want to configure with -Wall, which can
-detect many programming errors.  This is not the default because it
-might cause spurious warnings, but at least on some machines, there
-should be no spurious warnings.  For example:
-
-       $ ./configure CPPFLAGS=-Wall
-
-* Backwards Compatibility
-
-Only bug fixes are accepted into the stable branch.  New features should be
-applied to the trunk.
-
-If it is not inextricable from a bug fix, CVS's output (to stdout/stderr)
-should not be changed on the stable branch in order to best support scripts and
-other tools which parse CVS's output.  It is ok to change output between
-feature releases (on the trunk), though such changes should be noted in the
-NEWS file.
-
-Changes in the way CVS responds to command line options, config options, etc.
-should be accompanied by deprecation warnings for an entire stable series of
-releases before being changed permanently, if at all possible.
-
-* Indentation style
-
-CVS mostly uses a consistent indentation style which looks like this:
-
-void
-foo (char *arg, int c)
-{
-    long aflag;
-
-    if (arg)
-    {
-       bar (arg);
-       baz (arg);
-    }
-
-    switch (c)
-    {
-      case 'A':
-        aflag = 1;
-        break;
-      case 'E':
-        go to myerr;
-    }
-
-    printf ("Literal string line 1\n"
-           "Literal string line 2\n"
-           "Literal string line 3\n");
-    return;
-
-  myerr:
-    printf ("Error argument found\n");
-}
-
-  - Do not cast NULL unless it is a stdarg argument to a function.
-
-  - Do not cast functions returning (void *), e.g., xmalloc ().
-
-  - Do not cast non-stdarg arguments to a function to '(void *)'
-    except to drop a 'const' modifier.
-
-  - Snuggle ! close to its expression (i.e., '! foo' => '!foo').
-
-  - Functions and C statements have a space before the "("
-    and the expression does not have a leading or trailing space
-    (i.e., 'if( foo )' => 'if (foo)'), although it is sometimes
-    desirable to add a newline after the "(" for #ifdef'd code.
-       
-  - For switch statements, indent 'case' by 2 and the body of the case
-    by an additional 2 spaces.
-
-  - Labels should be indented by 2 spaces rather than the 4 spaces
-    used by the rest of the current block level.
-
-
-    while ((var = next_arg ()) != 0)
-    {
-      again:
-        switch (var)
-        {
-          case ONE:
-            code_for_case_one ();
-            break;
-          case TWO:
-            code_for_case_two ();
-            break;
-          case THREE:
-            push_arg (RESET_ONE);
-            var = ONE;
-           go to again;
-          default:
-            code_for_default_case ():
-            break;
-        }
-    }
-
-  - NULL-protected free goes on one line if possible, for example:
-        
-       if (var)
-            free (var);
-       if (var2 != NULL)
-            free (var2);
-
-    should be written as:
-          
-        if (var) free (var);
-        if (var2) free (var2);
-
-    if the value needs to be set to NULL after the free, then use
-
-       if (var)
-       {
-            free (var):
-            var = NULL;
-       }
-
-    as the idiom. 
-
-  - Use whitespace in arithmetic expressions, for example
-
-       foo (arg+2);
-
-    should be written as
-
-       foo (arg + 2);
-
-    likewise for normal arithmetic expression assignments.
-
-  - Argument lists get a space after a comma.
-
-  - Do not parenthesize return values unless the expression needs to
-    span multiple lines.
-
-  - Cast negative constants when used in assignments or comparisons
-    with unsigned types.
-
-  - Try to be consistent with block comments:
-
-    /* This is a good block comment (spanning multiple lines of text).
-     * It starts with slash-star, leads each line with a star aligned with
-     * the first, and ends with a similarly aligned star-slash on a line
-     * by itself.
-     */
-
-    /* This is a bad block comment,
-       because it can make it hard to tell what is code
-       and what is not code. */
-
-  - Sentences in comments should have a double space between each
-    period (.) and the beginning of the next sentence.
-
-  - Conditional expressions that need to be split should put the ?
-    operator on the new line.
-
-  - Follow GNU standards for breaking logical expressions over
-    multiple lines where possible.
-
-  - Do not snuggle open-lbrace blocks.
-
-  - Remove '#if 0' code where possible. Add a comment FIXME if it
-    really is a possible problem.
-
-  - Remove commented-out code where possible (FIXME blocks are
-    excepted). 
-
-The file cvs-format.el contains settings for emacs and the NEWS file
-contains a set of options for the indent program which I haven't tried
-but which are correct as far as I know.  You will find some code which
-does not conform to this indentation style; the plan is to re-indent it
-as those sections of the code are changed (one function at a time,
-perhaps).
-
-In a submitted patch it is acceptable to refrain from changing the
-indentation of large blocks of code to minimize the size of the patch;
-the person checking in such a patch should re-indent it.
-
-* Portability
-
-The general rule for portability is that it is only worth including
-portability cruft for systems on which people are actually testing and
-using new CVS releases.  Without testing, CVS will fail to be portable
-for any number of unanticipated reasons.
-
-CVS is now assuming a freestanding C89 compiler.  If you don't have one, you
-should find an old release of GCC that did not require a freestanding C89
-compiler to build, build that on your system, build a newer release of GCC
-if you wish, then build CVS using GCC as your freestanding C89 compiler.
-
-A freestanding C89 compiler is guaranteed to support function prototypes,
-void *, and assert().
-
-The following headers can be assumed and are included from lib/system.h for a
-freestanding C89 implementation: <float.h>, <limits.h>, <stdarg.h>, <stddef.h>.
-We are not assuming the other standard headers listed by C89 (hosted headers)
-because these four headers are the only headers guaranteed to be shipped with
-a C89 compiler (freestanding compiler).  We are not currently assuming that the
-system the compiler is running on provides the rest of the C89 headers.
-
-The following C89 hosted headers can be assumed due to their presence in UNIX
-version 7 and are included from lib/system.h: <assert.h>, <ctype.h>, <errno.h>,
-<math.h>, <setjmp.h>, <signal.h>, <stdio.h>.  <time.h> can also be assumed but
-is included via lib/xtime.h via lib/system.h to include some Autoconf magic
-which avoids including <time.h> and <sys/time.h> on systems that can't handle
-both.
-
-The following C89 headers are also assumed since we believe GCC includes them
-even on systems where it is installed as a freestanding compiler when the
-system lacks them, despite their not being required: <stdlib.h>, <string.h>.
-When the system does not lack these headers, they can sometimes not be
-standards compatible, but GCC provides a script, `fixincludes', for the purpose
-of fixing ANSI conformance problems and we think we can rely on asking users to
-either use GCC or run this script to fix conformance problems manually.  A
-GNULIB developer has made a statement that if this turns out to be a problem,
-GNULIB <stdlib.h> and <string.h> substitutes could be included in GNULIB, so if
-we discover the problem, this should be discussed on <bug-gnulib@gnu.org>.
-
-A substitute C99 <stdbool.h> is included from GNULIB for platforms that lack
-this header.  Please see the comments in the lib/stdbool_.h file for its
-limitations.
-
-<sys/types.h> can be assumed despite a lack of a presence in even C99, since
-it has been around nearly forever and no-one has ever complained about our code
-assuming its existence.
-
-CVS has also been assuming <pwd.h> for some time.  I am unsure of the
-rationale.
-
-GNULIB also assumes <sys/stat.h>.  I am unsure of the rationale.
-
-A substitute POSIX.2 <fnmatch.h> header and fnmatch() function is provided for
-systems that lack them.  Similarly for the non-standard <alloca.h> header and
-alloca() function.  Other substitute headers and functions are also provided
-when needed.  See the lib directory or the maint-aux/srclist.txt file for more
-information.
-
-Please do not use multi-line strings.  Despite their common acceptance by many
-compilers, they are not part of the ANSI C specification.  As of GCC version
-3.3, they are no longer supported.  See the Indentation Style section above for
-an example of a literal string which is not multi-line but which will print
-multiple lines.
-
-* Other style issues
-
-When composing header files, do not declare function prototypes using the
-`extern' storage-class identifier.  Under C89, there is no functional
-difference between a function declaration with and without `extern', unless the 
-function is declared `static'.  This is NOT the case for global variables.
-Global variables declared in header files MUST be declared `extern'.  For
-example:
-
-/* Global variables */
-extern int foo;
-extern char *bar;
-
-/* Function declarations */
-int make_foo(void);
-char *make_bar(int _foobar);
-
-* Run-time behaviors
-
-Use assert() to check "can't happen" conditions internal to CVS.  We
-realize that there are functions in CVS which instead return NULL or
-some such value (thus confusing the meaning of such a returned value),
-but we want to fix that code.  Of course, bad input data, a corrupt
-repository, bad options, etc., should always print a real error
-message instead.
-
-Do not use arbitrary limits (such as PATH_MAX) except perhaps when the
-operating system or some external interface requires it.  We spent a
-lot of time getting rid of them, and we don't want to put them back.
-If you find any that we missed, please report it as with other bugs.
-In most cases such code will create security holes (for example, for
-anonymous read-only access via the CVS protocol, or if a WWW cgi script
-passes client-supplied arguments to CVS).
-
-Although this is a long-term goal, it also would be nice to move CVS
-in the direction of reentrancy.  This reduces the size of the data
-segment and will allow a multi-threaded server if that is desirable.
-It is also useful to write the code so that it can be easily be made
-reentrant later.  For example, if you need to pass data to some functions,
-you need a static variable, but use a single pointer so that when the function
-is fixed to pass along the argument, then the code can easily use that
-argument.
-
-* Coding standards in general
-
-Generally speaking the GNU coding standards are mostly used by CVS
-(but see the exceptions mentioned above, such as indentation style,
-and perhaps an exception or two we haven't mentioned).  This is the
-file standards.text at the GNU FTP sites. The primary URL for this
-information is http://www.gnu.org/prep/standards/ which contains links
-to many different formats of the standards.
-
-* Regenerating Build Files (UNIX)
-
-On UNIX, if you wish to change the build files, you will need Autoconf and
-Automake.
-
-Some combinations of Automake and Autoconf versions may break the
-CVS build if file timestamps aren't set correctly and people don't
-have the same versions the developers do, so the rules to run them
-automatically aren't included in the generated Makefiles unless you run
-configure with --enable-maintainer-mode.
-
-The CVS Makefiles and configure script were built using Automake 1.9.6 and
-Autoconf 2.59, respectively.
-
-There is a known bug in Autoconf 2.57 that will prevent the configure
-scripts it generates from working on some platforms.  Other combinations of
-autotool versions may or may not work.  If you get other versions to work,
-please send a report to <bug-cvs@nongnu.org>.
-
-* Regenerating Build Files (Windows)
-
-If for some reason you end up regenerating the *.mak files to submit a patch,
-please run windows-NT/fix-msvc-mak.pl to remove the absolute paths from the
-generated *.mak files before generating any patches.
-
-* Rebuilding Yacc sources
-
-The lib/getdate.y file requires GNU Bison 1.875 to rebuild lib/getdate.c.  Not
-having GNU Bison 1.875 should not stop the build unless the lib/getdate.c file
-is actually missing, perhaps deleted via `make maintainerclean'.
-
-* Writing patches (strategy)
-
-Only some kinds of changes are suitable for inclusion in the
-"official" CVS.  Bugfixes, where CVS's behavior contradicts the
-documentation and/or expectations that everyone agrees on, should be
-OK (strategically).  For features, the desirable attributes are that
-the need is clear and that they fit nicely into the architecture of
-CVS.  Is it worth the cost (in terms of complexity or any other
-tradeoffs involved)?  Are there better solutions?
-
-If the design is not yet clear (which is true of most features), then
-the design is likely to benefit from more work and community input.
-Make a list of issues, or write documentation including rationales for
-how one would use the feature.  Discuss it with coworkers, a
-newsgroup, or a mailing list, and see what other people think.
-Distribute some experimental patches and see what people think.  The
-intention is arrive at some kind of rough community consensus before
-changing the "official" CVS.  Features like zlib, encryption, and
-the RCS library have benefited from this process in the past.
-
-If longstanding CVS behavior, that people may be relying on, is
-clearly deficient, it can be changed, but only slowly and carefully.
-For example, the global -q option was introduced in CVS 1.3 but the
-command -q options, which the global -q replaced, were not removed
-until CVS 1.6.
-
-* Writing patches (tactics)
-
-When you first distribute a patch it may be suitable to just put forth
-a rough patch, or even just an idea.  But before the end of the
-process the following should exist:
-
-  - ChangeLog entry (see the GNU coding standards for details).
-
-  - Changes to the NEWS file and cvs.texinfo, if the change is a
-    user-visible change worth mentioning.
-
-  - Somewhere, a description of what the patch fixes (often in
-    comments in the code, or maybe the ChangeLog or documentation).
-
-  - Most of the time, a test case (see TESTS).  It can be quite
-    frustrating to fix a bug only to see it reappear later, and adding
-    the case to the testsuite, where feasible, solves this and other
-    problems.  See the TESTS file for notes on writing new tests.
-
-If you solve several unrelated problems, it is generally easier to
-consider the desirability of the changes if there is a separate patch
-for each issue.  Use context diffs or unidiffs for patches.
-
-Include words like "I grant permission to distribute this patch under
-the terms of the GNU Public License" with your patch.  By sending a
-patch to bug-cvs@nongnu.org, you implicitly grant this permission.
-
-Submitting a patch to bug-cvs is the way to reach the people who have
-signed up to receive such submissions (including CVS developers), but
-there may or may not be much (or any) response.  If you want to pursue
-the matter further, you are probably best off working with the larger
-CVS community.  Distribute your patch as widely as desired (mailing
-lists, newsgroups, web sites, whatever).  Write a web page or other
-information describing what the patch is for.  It is neither practical
-nor desirable for all/most contributions to be distributed through the
-"official" (whatever that means) mechanisms of CVS releases and CVS
-developers.  Now, the "official" mechanisms do try to incorporate
-those patches which seem most suitable for widespread usage, together
-with test cases and documentation.  So if a patch becomes sufficiently
-popular in the CVS community, it is likely that one of the CVS
-developers will eventually try to do something with it.  But dealing
-with the CVS developers may be the last step of the process rather
-than the first.
-
-* What is the schedule for the next release?
-
-There isn't one.  That is, upcoming releases are not announced (or
-even hinted at, really) until the feature freeze which is
-approximately 2 weeks before the final release (at this time test
-releases start appearing and are announced on info-cvs).  This is
-intentional, to avoid a last minute rush to get new features in.
-
-* Mailing lists
-
-In addition to the mailing lists listed in the README file, developers should
-take particular note of the following mailling lists:
-
-    bug-cvs:  This is the list which users are requested to send bug reports
-      to.  General CVS development and design discussions also take place on
-      this list.
-    info-cvs:  This list is intended for user questions, but general CVS
-      development and design discussions sometimes take place on this list.
-    cvs-cvs:  The only messages sent to this list are sent
-      automatically, via the CVS `loginfo' mechanism, when someone
-      checks something in to the master CVS repository.
-    cvs-test-results:  The only messages sent to this list are sent
-      automatically, daily, by a script which runs "make check"
-      and "make remotecheck" on the master CVS sources.
-
-To subscribe to any of these lists, send mail to <list>-request@nongnu.org
-or visit http://savannah.nongnu.org/mail/?group=cvs and follow the instructions
-for the list you wish to subscribe to.
diff --git a/contrib/cvs-1.12/INSTALL b/contrib/cvs-1.12/INSTALL
deleted file mode 100644 (file)
index 56b077d..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
-Software Foundation, Inc.
-
-This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
-These are generic installation instructions.
-
-   The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation.  It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
-   It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring.  (Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.)
-
-   If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
-   The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'.  You only need
-`configure.ac' if you want to change it or regenerate `configure' using
-a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
-  1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.  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.
-
-     Running `configure' takes awhile.  While running, it prints some
-     messages telling which features it is checking for.
-
-  2. Type `make' to compile the package.
-
-  3. Optionally, type `make check' to run any self-tests that come with
-     the package.
-
-  4. Type `make install' to install the programs and any data files and
-     documentation.
-
-  5. You can remove the program binaries and object files from the
-     source code directory by typing `make clean'.  To also remove the
-     files that `configure' created (so you can compile the package for
-     a different kind of computer), type `make distclean'.  There is
-     also a `make maintainer-clean' target, but that is intended mainly
-     for the package's developers.  If you use it, you may have to get
-     all sorts of other programs in order to regenerate files that came
-     with the distribution.
-
-Compilers and Options
-=====================
-
-Some systems require unusual options for compilation or linking that the
-`configure' script does not know about.  Run `./configure --help' for
-details on some of the pertinent environment variables.
-
-   You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment.  Here
-is an example:
-
-     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
-
-   *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, 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
-the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
-   If you have to use a `make' that does not support the `VPATH'
-variable, you have to compile the package for one architecture at a
-time in the source code directory.  After you have installed the
-package for one architecture, use `make distclean' before reconfiguring
-for another architecture.
-
-Installation Names
-==================
-
-By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc.  You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PREFIX'.
-
-   You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PREFIX', the package will
-use PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
-   In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
-   If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
-Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System).  The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
-   For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
-There may be some features `configure' cannot figure out automatically,
-but needs to determine by the type of machine the package will run on.
-Usually, assuming the package is built to be run on the _same_
-architectures, `configure' can figure that out, but if it prints a
-message saying it cannot guess the machine type, give it the
-`--build=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
-     CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
-     OS KERNEL-OS
-
-   See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
-   If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
-produce code for.
-
-   If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-If you want to set default values for `configure' scripts to share, you
-can create a site shell script called `config.site' that gives default
-values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists.  Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-Variables not defined in a site shell script can be set in the
-environment passed to `configure'.  However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost.  In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'.  For example:
-
-     ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).  Here is a another example:
-
-     /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
-configuration-related scripts to be executed by `/bin/bash'.
-
-`configure' Invocation
-======================
-
-`configure' recognizes the following options to control how it operates.
-
-`--help'
-`-h'
-     Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`--cache-file=FILE'
-     Enable the cache: use and save the results of the tests in FILE,
-     traditionally `config.cache'.  FILE defaults to `/dev/null' to
-     disable caching.
-
-`--config-cache'
-`-C'
-     Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
-     Do not print messages saying which checks are being made.  To
-     suppress all normal output, redirect it to `/dev/null' (any error
-     messages will still be shown).
-
-`--srcdir=DIR'
-     Look for the package's source code in directory DIR.  Usually
-     `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options.  Run
-`configure --help' for more details.
-
diff --git a/contrib/cvs-1.12/MINOR-BUGS b/contrib/cvs-1.12/MINOR-BUGS
deleted file mode 100644 (file)
index 9eb0e7b..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-Low-priority bugs go here.  Actually, most every documented bug is
-"low-priority"--in the sense that if it is documented it means noone
-has gotten around to fixing it.
-
-
-* "cvs update -ko -p -r REV file" doesn't seem to pay attention to the
-  '-ko', at least in client/server mode.  A simple work around is to
-  temporarily change the db file with "cvs admin -ko file", then switch
-  it back to the original modes after the checkout (probably '-kkv').
-
-* "cvs status" has a difference in its output between local and
-  client/server mode.  Namely there's a tab character followed by a
-  ctime(3)-style date string at the end of the "Working revision:"
-  field.
-
-* commands which don't work in a local working directory should probably
-  ignore any CVS/Root values and revert to using CVSROOT alone.  The
-  current use of CVS/Root can be very confusing if you forget you're in
-  a working directory for a remote module -- something that's very easy
-  to do since CVS hides the client operation very well, esp. for
-  commands which fail for this reason.  The only clue might be the word
-  "server" in a message such as this:
-       cvs server: cannot find module `patch' - ignored
-
-* cvs init may gave a strange error at times:
-       ttyp4:<woods@clapton> $ cvs -d /local/src-CVS init
-       cvs [init aborted]: cannot open CVS/Root: No such file or directory
-  but it seemed to work just the same....  Note that at the time CVSROOT
-  was set to point to a CVS server using the ":server:" option.
-
-* If a ~/CVS/Root file exists on the server and you are using rsh to
-connect to the server, CVS may loose its mind (this was reported in
-May 1995 and I suspect the symptoms have changed, but I have no
-particular reason to think the bug is fixed -kingdon, Sep 96).
-
-* (Jeff Johnson <jbj@jbj.org>)
-  I tried a "cvs status -v" and received the following:
-
-  ? CVS
-  ? programs/CVS
-  ? tests/CVS
-  cvs server: Examining .
-  ===================================================================
-  File: Install.dec            Status: Up-to-date
-  ...
-  
-  I claim that CVS dirs should be ignored.
-  (This reportedly happens if "cvs add CVS" (or "cvs add *")
-  is followed by "cvs status", in client/server mode - CVS 1.9).
-
-* On remote checkout, files don't have the right time/date stamps in
-  the CVS/Entries files.  Doesn't look like the C/S protocol has any
-  way to send this information along (according to cvsclient.texi).
-  Perhaps we can spiff it up a bit by using the conflict field for the
-  stamp on the checkout/update command.  Please note that this really
-  doesn't do very much for us even if we get it done.
-
-* Does the function that lists the available modules in the repository
-  belong under the "checkout" function?  Perhaps it is more logically
-  grouped with the "history" function or we should create a new "info"
-  function?
diff --git a/contrib/cvs-1.12/NEWS b/contrib/cvs-1.12/NEWS
deleted file mode 100644 (file)
index 732099b..0000000
+++ /dev/null
@@ -1,2140 +0,0 @@
-Changes since 1.12.12:
-**********************
-
-SECURITY FIXES
-
-* CVS now uses version 1.2.3 of the ZLib compression libraries in order to
-  avoid two recently announced security vulnerabilities in them.  Both may be
-  used for denial of service attacks and one may reportedly allow execution of
-  arbitrary code, though this is not confirmed.  Please see the CERT
-  vulnerabilities advisories #238678 <http://www.kb.cert.org/vuls/id/238678> &
-  #680620 <http://www.kb.cert.org/vuls/id/680620> for more.
-
-NEW FEATURES
-
-* Thanks to Conrad Pino <conrad@pino.com>, a hang in the Windows client, which
-  had pretty much rendered the client useless, has been fixed.
-
-* A minor problem preventing build of the Kerberos4 client has been fixed.
-
-* The path to the config file may be set as an argument to the CVS server
-  commands.
-
-* Sections of directives specific to one or more repositories and not others
-  may now be specified in the config file.
-
-* %{sV} format strings are now available to the verifymsg trigger, similar to
-  the %{stVv} available to loginfo.
-
-* `cvs watch add' on an empty directory no longer clears watchers, and
-  specifying a directory for `cvs watch add' now (correctly) sets default
-  attributes.
-
-* Missing CVSROOT/history files will now cause CVS to attempt to create one.
-  To suppress history logging, set LogHistory equal to the empty string in
-  CVSROOT/config.
-
-* There are several new options available in CVSROOT/config.  These are
-  TmpDir, HistoryLogPath, HistorySearchPath, MinCompressionLevel, &
-  MaxCompressionLevel.  Please see the manual for more.
-
-* CVS on Solaris 10 was refusing to parse command options.  This has been
-  fixed.
-
-* The Windows client now creates locks compatible with older versions of CVS by
-  default.  This should only be relevant if your client is accessing a local
-  repository concurrently with another, older client.  If you would like to
-  disable compatibility mode (because it is slightly faster), edit the
-  LOCK_COMPATIBILITY flag in windows-NT/config.h and recompile.
-
-* Misc efficiency and portability improvements.
-
-BUG FIXES
-
-* Thanks to Serguei E. Leontiev <lse@CryptoPro.ru>, CVS with Kerberos 5 GSSAPI
-  should automatically link on FreeBSD 5.x. (bug #14639).
-
-* Thanks to Rahul Bhargava <rahul@wandisco.com>, heavily loaded systems
-  suffering from a disk crash or power failure will not lose data they claimed
-  to have committed.
-
-* CVS server now handles conflict markers in Entry requests as documented.
-
-* CVS now remembers that binary file merge conflicts occurred until the
-  timestamp of the updated binary file changes.
-
-* CVS client now saves some bandwidth by not sending the contents of files
-  with conflicts to the server when it isn't needed.
-
-* CVS now does correct locking during import.
-
-* A problem where the server could block indefinitely waiting for an EOF from
-  the client when compression was enabled has been fixed.
-
-* `cvs diff' no longer splits its arguments on spaces.
-
-* Thanks to an old report and patch from Stewart Brodie <stewart@eh.org>, a
-  potential crash in response to a corrupt RCS file has been fixed.
-
-* CVS now locks the history and val-tags files before writing to them.
-  Especially with large repositories, users should no longer see new warnings
-  about corrupt history records when using the `cvs history' command.  Existing
-  corrupt history records will still need to be removed manually.  val-tags
-  corruption should have had less obvious effects, but removing the
-  CVSROOT/val-tags file and allowing a 1.11.21 or later version of CVS to
-  regenerate it may eliminate a few odd behaviors and possibly cause a slight
-  speed up of read transactions in large repositories over time.
-
-BUILD ISSUES
-
-* The RPM spec file works again with the most modern versions of `rpm'.  It
-  also finds the correct version of install-sh when building the CVS with
-  GSSAPI.
-
-DEVELOPER ISSUES
-
-* We've standardized on Automake 1.9.6 to get some at new features that make
-  our jobs easier.  See the HACKING file for more on using the autotools with
-  CVS.
-
-Changes from 1.12.11 to 1.12.12:
-********************************
-
-SERVER SECURITY FIXES
-
-* Thanks to a report from Alen Zukich <alen.zukich@klocwork.com>, several minor
-  security issues have been addressed.  One was a buffer overflow that is
-  potentially serious but which may not be exploitable, assigned CAN-2005-0753
-  by the Common Vulnerabilities and Exposures Project
-  <http://www.cve.mitre.org>.  Other fixes resulting from Alen's report include
-  repair of an arbitrary free with no known exploit and several plugged memory
-  leaks and potentially freed NULL pointers which may have been exploitable for
-  a denial of service attack.
-
-* Thanks to a report from Craig Monson <craig@malachiarts.com>, minor
-  potential vulnerabilities in the contributed Perl scripts have been fixed.
-  The confirmed vulnerability could allow the execution of arbitrary code on
-  the CVS server, but only if a user already had commit access and if one of
-  the contrib scripts was installed improperly, a condition which should have
-  been quickly visible to any administrator.  The complete description of the
-  problem is here: <https://ccvs.cvshome.org/issues/show_bug.cgi?id=224>.  If
-  you were making use of any of the contributed trigger scripts on a CVS
-  server, you should probably still replace them with the new versions, to be
-  on the safe side.
-
-  Unfortunately, our fix is incomplete.  Taint-checking has been enabled in all
-  the contributed Perl scripts intended to be run as trigger scripts, but no
-  attempt has been made to ensure that they still run in taint mode.  You will
-  most likely have to tweak the scripts in some way to make them run.  Please
-  send any patches you find necessary back to <bug-cvs@nongnu.org> so that we
-  may again ship fully enabled scripts in the future.
-
-  You should also make sure that any home-grown Perl scripts that you might
-  have installed as CVS triggers also have taint-checking enabled.  This can be
-  done by adding `-T' on the scripts' #! lines.  Please try running
-  `perldoc perlsec' if you would like more information on general Perl security
-  and taint-checking.
-
-NEW FEATURES
-
-* Thanks to a report from Ian Abbott <abbotti@mev.co.uk>, a problem that caused
-  CVS to stop with broken assertions in certain time zones when daylight
-  savings is in effect has been fixed.
-
-* A problem where a proxy server could fail to notice that its primary closed
-  the connection has been fixed.
-
-* Failures to open the CVS_CLIENT_LOG, CVS_SERVER_LOG, and CVS_SECONDARY_LOG
-  are no longer fatal.
-
-* CVS's client and server IO buffers now rely on a GNULIB modules for memory
-  management rather than taking on the task themseleves.  This should be faster
-  on any system but may increase memory usage noticably on systems without the
-  POSIX mmap() function.  Benchmark reports to <bug-cvs@gnulib.org> would be
-  welcome.
-
-* Some more GNULIB functions have been imported and/or updated for portability
-  reasons.  This change should not be visible to most users, though CVS may now
-  compile on a few more platforms.
-
-* CVS creates a unique session id that gets written to the RCS files during
-  import and commit. When committing several files at once, they all get the
-  same 'commitid'. The commitid becomes visible with log and status commands,
-  and is derived and compatible with the cvsnt project.
-
-* CVS once again compiles correctly configured with various combinations of
-  --disable-client, --disable-server, and --disable-proxy.
-
-* CVS now accepts the <tag>:<date> format, which has long been acceptable as an
-  argument to -j options, in most places where <tag> used to be acceptable.  An
-  empty tag in this format (e.g. ":<date>"), which used to be rejected, is now
-  interpreted as specifying a date on the trunk.
-
-* CVS now uses ZLib 1.2.2.  This fixes the minor vulnerability described here:
-  <http://www.kb.cert.org/vuls/id/238678>, as well as some other minor bugs we
-  are not aware of bug reports for in conjunction with CVS.
-
-* `cvs -n release' now does what it should (see changes to the info-cleanup-0
-  test in sanity.sh for more).
-
-* The configure script now prefers `ssh' to `rsh' when determining a default
-  executable to use when connecting via the :ext: method.
-
-* A problem in the compression buffer that was causing some incompatibility
-  with some 3rd party CVS clients when compression was enabled has been fixed.
-
-* Some files missing from the distribution have been added or readded.  The
-  missing files were mostly development support files, with a few docs and
-  .cvsignore files thrown in.
-
-* The incomplete Brazillian Portugese translation of the CVS manual is now
-  included in the distribution.
-
-BUG FIXES
-
-* Misc bug and documentation fixes.
-
-* CVS now detects write errors on standard output.  Before, e.g.,
-  `cvs update -p FILE > /dev/full' would fail to report the write error.
-
-* Thanks to a report and a patch from Georg Scwharz <georg.scwarz@freenet.de>
-  CVS now builds without error on IRIX 5.3
-
-DEVELOPER ISSUES
-
-* We've standardized on Automake 1.9.5 to get some at new features that make
-  our jobs easier.  See the HACKING file for more on using the autotools with
-  CVS.
-
-Changes from 1.12.10 to 1.12.11:
-********************************
-
-NEW FEATURES
-
-* Thanks to Conrad Pino <conrad@pino.com>, the Windows build works once again.
-
-* CVSROOT methods and option names are now case insensitive
-
-* CVSROOT methods :ext: and :fork: now support the CVS_SERVER option.
-
-* CVSROOT method :ext: now supports the CVS_RSH and Redirect options.
-
-* Date handling has been improved slightly.
-
-* Miscellaneous bug fixes.
-
-* Miscellaneous documentation fixes.
-
-BUG FIXES
-
-* An intermittant assertion failure in checkout has been fixed.
-
-* Thanks to a report from Chris Bohn <cbohn@rrinc.com>, all the source files
-  needed to build on Windows are now included in the source distribution.
-
-Changes from 1.12.9 to 1.12.10:
-*******************************
-
-NEW FEATURES
-
-* The date formats which CVS accepts are now documented more fully in the
-  manual.
-
-* CVS commands which accept dates now understand some more time zones,
-  including those which are some hours plus some fraction of an hour off of
-  universal coordinated time.
-
-* `cvs ls filename' no longer causes an assertion failure.
-
-* The maximum length of the discovered comment leader used in a Log keyword
-  substitution is now limited to 20 characters by default.  If a longer leader
-  is discovered, then the keyword is not expanded.  This default behavior may
-  be altered using the new MaxCommentLeaderLength & UseArchiveCommentLeader
-  config options.
-
-* Commit messages once again include the full relative path to the file being
-  committed.
-* Thanks to funding from Juniper Networks <http://juniper.net>, "write proxy"
-  functionality has been added to the CVS server.  Write proxy functionality
-  allows any of multiple, read-only "secondary" servers to relay write requests
-  from clients to a single primary CVS server, allowing for a massive
-  redistribution of server load which is transparent to all known CVS clients.
-
-* Thanks to funding from Juniper Networks <http://juniper.net>, some code has
-  been added which second-guesses the system file cache for a performance
-  boost.
-
-* The loginfo scripting hook now runs after the administrative files in CVSROOT
-  are rebuilt, rather than before.
-
-* Misc error message improvements.
-
-* Thanks to funding from Juniper Networks <http://juniper.net>, new scripting
-  hooks have been added to the CVS server.  These are the postadmin, posttag,
-  and postwatch hooks.  See the manual for more info.
-
-* Thanks to funding from Juniper Networks <http://juniper.net>, all the
-  existing scripting hooks may now optionally be passed a command name
-  argument.
-
-* Thanks to funding from Juniper Networks <http://juniper.net>, new tags are
-  cached in the val-tags file at the time of tag creation.
-
-* Thanks to a patch from Brian Murphy <brian@murphy.dk>, CVS now supports PAM
-  session management.
-
-* Thanks to a report from Brian Murphy <brian@murphy.dk>, the demo PAM
-  configuration files mentioned in the manual are actually being distributed.
-
-* Thanks again to Bart Robinson <lomew@pobox.com>, `cvs log' & `cvs ls' now
-  actually output local times when the server is version 1.12.9 or greater and
-  the client is version  1.12.10 or greater.  
-
-* The CVS server now sends paths to files relative to the repository.  CVS
-  clients have been able to handle this since at least the 10 year old
-  CVS 1.9.2 release, so no attempt at verifying compatibility of clients has
-  been made.  This saves a small amount of bandwidth and may enable some future
-  functionality.
-
-* The CVS client will send relative Directory requests if the server claims to
-  support it.  This saves a very small amount of bandwidth but may enable some
-  future functionality.
-
-* "cvs import" now has a new option, `-X', which causes new files to be
-  imported in a way that they appear only on the vendor branch, and do not
-  automatically appear on the main trunk.
-
-  This option may be made the default on a repository-wide basis
-  using the new ImportNewFilesToVendorBranchOnly=yes option in
-  CVSROOT/config.
-
-* contrib/cvs_acls.in has been revised. Users of the old version will
-  want to upgrade to use the new format. See the documentation in
-  contrib/cvs_acls.html for more information.
-
-* Thanks to Dan Peterson <dbpete@aol.com>, the contrib/validate_repo script now
-  accepts and logs corrupted revision numbers in RCS archives.
-
-BUG FIXES
-
-* Thanks to a report from Gottfried Ganssauge <gotti@cvshome.org>, CVS no
-  longer exits when it encounters links pointing to paths containing more
-  than 128 characters.
-
-* Thanks to a report from Dan Peterson <dbpete@aol.com>, error messages from
-  GSSAPI servers are no longer truncated.
-
-* Thanks to a report from Dan Peterson <dbpete@aol.com>, attempts to resurrect
-  a file on the trunk that was added on a branch no longer causes an assertion
-  failure.
-
-* Thanks to a report from Dan Peterson <dbpete@aol.com>, imports to branches
-  like "1.1." no longer create corrupt RCS archives.
-
-* Thanks to a report from Chris Bohn <cbohn@rrinc.com>, links from J.C. Hamlin
-  <jchamlin@ibsys.com>, and code posted by Jonathan Gilligan, we think we have
-  finally corrected the Windows "red-file" (daylight savings time) bug once and
-  for all.
-
-* Thanks to a patch from Jeroen Ruigrok/asmodai <asmodai@wxs.nl>, the
-  log_accum.pl script should no longer elicit warnings from Perl 5.8.5.
-
-* The r* commands (rlog, rls, etc.) can once again handle requests to run
-  against the entire repository (e.g. `cvs rlog .').  Thanks go to Dan Peterson
-  <dbpete@aol.com> for the report.
-
-* A problem where the attempted access of files via tags beginning with spaces
-  could cause the CVS server to hang has been fixed.  This was a particular
-  problem with WinCVS clients because users would sometimes accidentally
-  include spaces in tags pasted into a dialog box.  This fix also altered some
-  of the error messages generated by the use of invalid tags.  Thanks go to Dan
-  Peterson <dbpete@aol.com> for the report.
-
-* Thanks to James E Wilson <wilson@specifixinc.com> for a bug fix to
-  modules processing "gcc-core -a !gcc/f gcc" will no longer exclude
-  gcc/fortran by mistake.
-
-* Thanks to Conrad Pino <conrad@pino.com>, the Windows build works once again.
-
-* Misc updates to the manual.
-
-DEVELOPER ISSUES
-
-* We've standardized on Automake 1.9.3 to get some at new features that make
-  our jobs easier.  See the note below on the Autoconf upgrade for more
-  details.
-
-* We've standardized on Autoconf version 2.59 to get presumed bug fixes and
-  features, but nothing specific.  Mostly, once we decide to upgrade one of the
-  autotools we just figure it'll save time later to grab the most current
-  versions of the others too.  See the HACKING file for more on using the
-  autotools with CVS.
-
-Changes from 1.12.8 to 1.12.9:
-******************************
-
-SERVER SECURITY FIXES
-
-* Thanks to Stefan Esser & Sebastian Krahmer, several potential security
-  problems have been fixed.  The ones which were considered dangerous enough
-  to catalogue were assigned issue numbers CAN-2004-0416, CAN-2004-0417, &
-  CAN-2004-0418 by the Common Vulnerabilities and Exposures Project.  Please
-  see <http://www.cve.mitre.org> for more information.
-
-* A potential buffer overflow vulnerability in the server has been fixed.
-  This addresses the Common Vulnerabilities and Exposures Project's issue
-  #CAN-2004-0414.  Please see <http://www.cve.mitre.org> for more information.
-
-NEW FEATURES
-
-* `cvs log' & `cvs ls' now output local times when both the server and client
-  are 1.12.9 or greater.  (Thanks to Bart Robinson <lomew@pobox.com>.)
-
-DEVELOPER NOTES
-
-* The windows-NT/config.h.in file is now generated dynamically from the
-  root config.h.in file and a few inputs in the windows-NT directory in hopes
-  of keeping it more in sync with the root config.h.in file.
-
-Changes from 1.12.7 to 1.12.8:
-******************************
-
-SERVER SECURITY FIXES
-
-* A potential buffer overflow vulnerability in the server has been fixed.
-  Prior to this patch, a malicious client could potentially use carefully
-  crafted server requests to run arbitrary programs on the CVS server machine.
-  This addresses the Common Vulnerabilities and Exposures Project's issue
-  #CAN-2004-0396.  Please see <http://www.cve.mitre.org> for more information.
-
-NEW FEATURES
-
-* Some redundant output generated by the `cvs commit' command has been removed.
-
-* Most output from the `cvs commit' command is suppressed when the -Q global
-  option is specified.
-
-* Repository directory browsing via `cvs rls' & `cvs ls' commands.  Expect
-  changes in the long format output soon.  The "entries" format output should
-  remain fairly stable for automated parsers.
-
-* Glob matches, as specified in ignore lists and wrapper options, now conform
-  to the POSIX.2 specification for fnmatch on all platforms.
-
-* The Windows MS Visual C++ project files, including the nmake build files,
-  are now generated with MSVC++ 6.0, but should still work with MSVC++ 5.0.
-
-BUG FIXES
-
-* The cvs.1 man page is now generated automatically from a section of the CVS
-  Manual.
-
-* Thanks to a report from Mark Andrews at the Internet Systems Consortium, the
-  :ext: connection method no longer relies on a transparent transport that uses
-  an argument processor that can handle arbitrary ordering of options and other
-  arguments when using a username other than the caller's.
-
-* Thanks to Ken Raeburn at MIT, directory deletion, whether via `cvs release'
-  or empty directory pruning, now works on network shares under Windows XP.
-
-Changes from 1.12.6 to 1.12.7:
-******************************
-
-SERVER SECURITY ISSUES
-
-* Piped checkouts of paths above $CVSROOT no longer work.  Previously, clients
-  could have requested the contents of RCS archive files anywhere on a CVS
-  server.  This addresses CVE issue CAN-2004-0405.  Please see
-  <http://www.cve.mitre.org> for more information.
-
-CLIENT SECURITY ISSUES
-
-* Clients now check paths from the server to verify that they are within one of
-  the sandboxes the user requested be updated.  Previously, a trojan server
-  could have written or overwritten files anywhere the user had access,
-  presenting a serious security risk.  This addresses CVE issue CAN-2004-1080.
-  Please see <http://www.cve.mitre.org> for more information.
-
-GENERAL USER ISSUES
-
-* Imported the most recent version of regex from GNULIB, which actually means
-  some systems will use now their native regex functions instead of compiling
-  CVS's.  Users should notice no changes in CVS responses to regular
-  expressions.  If you do, please report them to <bug-cvs@gnu.org>.
-
-* CVS now accepts the location of HTTP tunnel web proxies as part of the
-  CVSROOT string.  Actually using a proxy remains untested.  Please report
-  problems and successes to <bug-cvs@gnu.org>.
-
-* Configure no longer checks the $TMPDIR, $TMP, & $TEMP variables to set the
-  default temporary directory.
-
-* CVS on Cygwin correctly handles X:\ style paths.
-
-* Import now uses backslash rather than slash on Windows when checking for
-  "CVS" directories to ignore in import commands.
-
-* Relative paths containing up-references (`..') should now work in
-  client/server mode (client fix).
-
-* A race condition between the ordering of messages from CVS and messages from
-  called scripts in client/server mode has been removed (server fix).
-
-* The check_cvs and cvscheck scripts in the contrib directory have been renamed
-  validate_repo and sandbox_status, respectively, in the interests of clarity.
-
-* The Windows MS Visual C++ 6.0 project files have been brought up to date.
-  The nmake build files were regenerated from these files with MSVC++ 5.0.
-
-* A memory allocation bug on Windows that could cause at least executions of
-  `cvs status' to fail has been fixed (client fix).
-
-* Resurrected files now get their modes and timestamps set correctly and a
-  longstanding bug involving resurrection of an uncommitted removal has been
-  fixed (server fix).
-
-* Some resurrection (cvs add) status messages have changed slightly.
-
-* `cvs release' now works with Kerberos or GSSAPI encryption enabled (server
-  fix).
-
-* File resurrection from a previously existing revision no longer just reports
-  that it works (server fix).
-
-* Misc error & status message corrections.
-
-* Diffing of locally added files against arbitrary revisions in an RCS archive
-  is now allowed when a file of the same name exists or used to exist on some
-  branch (server fix).
-
-* Some user messages have been updated for consistency and spelling.
-
-DEVELOPER ISSUES
-
-* The message source differentiation in the test suite between client and
-  server executables has been repaired.
-
-Changes from 1.12.5 to 1.12.6:
-******************************
-
-GENERAL USER ISSUES
-
-* CVSROOT/*info scripts may not work as expected with executables compiled
-  using VC++ under Windows since all quoting is currently done according to
-  Bourne Shell rules, which probably don't look like command.com rules.
-  Patches gratefully accepted.
-
-* Imports will now always ignore directories and files named `CVS' to avoid
-  violating assumptions made by other parts of CVS.
-
-* Directories specified to `checkout -d' are no longer required to exist.  This
-  consolidates some behavior between `-d' options specified in the modules file
-  and `checkout -d' as well as removing some prior differences between local
-  and client/server mode operation.
-
-* A problem with `cvs release' of subdirs that could corrupt CVS/Entries files
-  has been fixed (client/server).
-
-* The CVS server's protocol check for unused data from the client is no longer
-  called automatically at program exit in order to avoid potential recursive
-  calls to error when the first close is due to memory allocation or similar
-  problems that cause calls to error() to fail.  The check is still made when
-  the server program exits normally.
-
-* The CVSROOT/*info files want a new command format and the old style strings
-  have been deprecated.  Please see the manual for more information on the new
-  format.
-
-* The spec file has been updated to work with more recent versions of RPM.
-
-* Some more GNULIB functions have been imported and/or updated for portability
-  reasons.
-
-* Several memory leaks have been plugged.
-
-* A seg fault which always occurred after waiting on another process's lock
-  in order to establish a promotable lock is now avoided.
-
-* An unlikely potential segfault when using the :fork: connection method has
-  been fixed.
-
-* The CVS server has had the protocol check for unused data from the client
-  partially restored.
-
-* A fix has been included that should avoid a very rare race condition that
-  could cause a CVS server to exit with a "broken pipe" message.
-
-* Infinite alias loops in the modules file are now checked for and avoided.
-
-* Clients on case insensitive systems now preserve the case of directories in
-  CVS/Entries, in addition to files, for use in communications with the CVS
-  server.
-
-* Misc status message fixes for consistency.
-
-* Some previously untested behavior is now being tested.
-
-* Server no longer claims to support the "Case" request.
-
-* Case insensitive clients once again preserve the case of filenames in
-  CVS/Entries for communication with the server, as specified in the CVS
-  client/server protocol spec.  Note that all CVS _servers_ still lack support
-  for case insensitive clients - servers are relying on the client to preserve
-  the case of checked out files.
-
-* Thanks to Ville Skytt√§ the man page has a few less spelling errors and is
-  slightly more accurate.
-
-* Thanks to Ville Skytt√§ some unused variables were removed from the log_accum
-  Perl script in contrib.
-
-* Thanks to Alexey Mahotkin, a bug that prevented CVS from being compiled with
-  Kerberos 4 authentication enabled has been fixed.
-
-* A minor bug that caused CVS to fail to report an inifinte alias loop in the
-  modules file when portions of the alias definition contained trailing slashes
-  has been fixed.
-
-* A bug in the gzip code that could cause heap corruption and segfaults in CVS
-  servers talking to clients less than 1.8 and some modern third-party CVS
-  clients has been fixed.
-
-* mktemp.sh is now included with the source distribution so that the rcs2log
-  and cvsbug executables may be run on systems which do not contain an
-  implementation of mktemp.
-
-* Misc documentation fixes.
-
-DEVELOPER ISSUES
-
-* xmalloc, xstrdup, & some other memory allocating functions are now available
-  vi GNULIB versions imported into lib.
-
-* The asnprintf() & vasnprintf() functions are now available due to a GNULIB
-  implementation.
-
-* Misc cosmetic, readability, and commenting fixes.
-
-Changes between 1.12.4 and 1.12.5:
-**********************************
-
-SERVER SECURITY ISSUES
-
-* pserver can no longer be configured to run as root via the
-  $CVSROOT/CVSROOT/passwd file, so if your passwd file is compromised, it no
-  longer leads directly to a root hack.  Attempts to root will also be logged
-  via the syslog.
-
-GENERAL USER ISSUES
-
-* The Windows build files were updated to allow building of the current version
-  under Windows.
-
-Changes between 1.12.3 and 1.12.4:
-**********************************
-
-GENERAL USER ISSUES
-
-* The CVS server no longer locks more than a directory at a time for write, so
-  large commits & tags should now have a much harder time blocking other
-  operations.
-
-* Add support for large files. Use --disable-largefile to omit support
-  for large files.
-
-Changes between 1.12.2 and 1.12.3:
-**********************************
-
-SERVER SECURITY ISSUES
-
-* Malformed module requests could cause the CVS server to attempt to create
-  directories and possibly files at the root of the filesystem holding the CVS
-  repository.  Filesystem permissions usually prevent the creation of these
-  misplaced directories, but nevertheless, the CVS server now rejects the
-  malformed requests.
-
-GENERAL USER ISSUES
-
-* Support for case insensitive clients has been removed.  This is not as
-  drastic as it sounds, as all of the current tests still pass without
-  modification when run from a case insensitive client to a case sensitive
-  server.  In the end this should provide a major stability improvement.
-
-* A minor problem that prevented the correct version of a system ZLIB from
-  being detected on some platforms has been fixed.
-
-* Attempts to use the global `-l' option, removed from both client and server
-  as of version 1.12.1, will now elicit a warning rather than a fatal error
-  from the server.
-
-* The configure script now tests whether it is building CVS on a case
-  insensitive file system.  If it is, CVS assumes that all file systems on this
-  platform will be case insensitive.  This is useful for getting the case
-  insensitivity flag set correctly when compiling on Mac OS X and under Cygwin
-  on Windows.  Autodetection can be overridden using the
-  --disable-case-sensitivity and --enable-case-sensitivity arguments to
-  configure.
-
-DEVELOPER ISSUES
-
-* A new set of tests to test issues specific to case insensitive clients and
-  servers has also been added.
-
-* Support has been added to the test suite to support testing over a :ext: link
-  to another machine, subject to some stringent requirements.  This support can
-  be used, for instance, to test the operation of a case insensitive client
-  against a case sensitive server.  Please see the comments in TEST and the
-  src/sanity.sh test script itself for more.
-
-* We've standardized on Automake 1.7.9 to get a bug fix.  See the note below
-  on the Autoconf upgrade for more details.
-
-* We've standardized on Autoconf version 2.58 to avoid a bug and get at a few
-  new macros.  Again, this should only really affect developers, though it is
-  possible that CVS will now compile on a few new platforms.  Please see the
-  section of the INSTALL file about using the autotools if you are compiling
-  CVS yourself.
-
-Changes between 1.12.1 and 1.12.2:
-
-* Misc cleanup, reorganization, and other minor fixes.
-
-* A behavior change in `cvs up -jrev1 -jrev2' for modified files with a base
-  revision of rev2 (ie, checked-out version matches rev2 and file has been
-  modified).  The operation is no longer ignored and instead is passed to
-  diff3.  This will potentially re-apply the diffs between the two revisions to
-  a modified local file.  Status messages like from a standard merge have also
-  been added when the file would not or does not change due to this merge
-  request ("[file] already contains the changes between [revisions]...").
-
-* A build problem that caused warnings and slower builds on systems without a
-working getline() function (e.g. Mac OS X 10.1) has been fixed.
-
-* A build problem that prevented the CVS executable from being built on systems
-with the gettext library installed has been fixed.
-
-* A bug which could stop `cvs admin -mTAG:message' from recursing has been
-  fixed.
-
-* Misc documentation cleanup and fixes.
-
-* Some of the contrib scripts, some of the documentation, and sanity.sh were
-  modified to use and recommend more portable commands rather than using and
-  recommending commands which were not compatible with the POSIX 1003.1-2001
-  specification.
-
-* CVS now knows how to report, as well as record, `P' record types.
-
-* When running the `cvs history' command, clients will now send the
-  long-accepted `-e' option, for all records, rather than explicitly requesting
-  `P' record types, a request which servers prior to 1.11.7 will reject with a
-  fatal error message.
-
-* A problem with locating files requested by case insensitive clients which was
-  accidentally introduced in 1.11.6 as part of a fix for a data loss problem
-  involving `cvs add's from case insensitive clients has been fixed.  The
-  relevant error message was `cvs [<command> aborted]: filE,v is ambiguous;
-  could mean FILE,v or file,v'.
-
-* A problem in the CVS getpass library that could cause passwords to echo on
-  some systems has been fixed.
-
-* A segfault that could occur in very rare cases where the stat of a file
-  failed during a diff has been fixed.
-
-* Any user with write privleges to the CVSROOT/checkoutlist file could pass
-arbitrary format strings directly through to a printf function.  This was
-probably bad and has been fixed.  White space at the beginning of error strings
-in checkoutlist is now ignored properly.
-
-* A chmod 0600 that CVS performed on temp files it created designed to work
-around a bug in versions of GLIBC eariler than 2.0.7 has been removed since it
-still left a race condition open to exploitation and provided a false sense of
-security.  If you are linking CVS against a version of GLIBC prior to 2.0.7,
-you should consider upgrading GLIBC.
-
-* The CVSROOT/editinfo file is no longer referenced by CVS.  This funcitonality
-has been deprecated for over six years and removing it will presumably not
-cause anyone any problems.
-
-* In client/server mode, most messages from CVS now contain the actual
-command name rather than the generic "server".
-
-* A long-standing bug that prevented most client/server updates from being
-logged in the history file has been fixed.
-
-* Updates done via a patch ("P" status) are now logged in the history file
-by default and the corresponding "P" history record type is now documented.
-If you're setting the LogHistory option in your CVSROOT/config file, you may
-want to add "P" to the list of record types.
-
-* CVS now will always compile its own getpass() function (originally from
-GNULIB) in favor of any system one that may exist.  This avoids some problems
-with long passwords on some systems and updates us to POSIX.2 compliance, since
-getpass() was removed from the POSIX.2 specification.
-
-* Support for pre-ANSI compilers has been removed.  Our minimum support level
-now assumes at least a freestanding C89 compilers.  See the HACKING file for
-more information.  If you *really* need K&R support, our Makefile.am files
-should only need minor tweaking to get them to run the ansi2knr script from the
-Automake project.  If you get this working, please send a patch to
-<bug-cvs@gnu.org>.
-
-* Experimental support for Pluggable Authentication Modules (PAM) has been
-added, though it is not compiled by default.  If you like this feature (or
-don't), please send us feedback.  See the Cederqvist, `./configure --help',
-and the INSTALL file for more.
-
-* Command line keyword expansion modes no longer override binary keyword
-expansion modes.
-
-* New LocalKeyword and KeywordExpand options to CVSROOT/config which
-FreeBSD, OpenBSD, and NetBSD users may find familiar as the "tag" and
-"tagexpand" options used for many years. The CVSHeader keyword has
-also been added to the mixture.
-
-* A bug that allowed a write lock to be created in a directory despite
-there being existing read locks when using LockDir in CVSROOT/config has
-been fixed.
-
-* A bug with short patches (`rdiff -s') which caused rdiff to sometimes report
-differences that did not exist has been fixed.
-
-* Some minor corrections were made to the diff code to keep diff & rdiff from
-printing diff headers with empty change texts when two files have different
-revision numbers but the same content.
-
-* The global '-l' option, which suppressed history logging, has been removed
-from both client and server.
-
-Changes from 1.11.5 to 1.12.1:
-
-* The new --with-external-zlib option can be passed to configure to compile
-CVS against an external installed zlib.
-
-* A warning message is now issued if an administrative file contains
-more than one DEFAULT entry.
-
-* An error running a verifymsg script (such as referencing an unset user
-variable or the script not existing) now causes the verification to
-fail.
-
-* Errors in administrative files commands (like unset user variables)
-are no longer reported unless the command is actually executed.
-
-* When a file is initially checked out, its last access time is now set
-to the current time rather than being set to the time the file was last
-checked in like the modification time is.
-
-* The Checkin.prog and Update.prog functionality has been removed.  This
-fuctionality previously allowed executables to be specified in the modules file
-to be run at update and checkin time, but users could edit these files on a per
-workspace basis, creating a security hole.
-
-* CVSROOTs which contain a symlink to a real repository should work.
-
-* contrib/rcs2log and src/cvsbug now use the BSD mktemp program to create
-their temp files and directories on systems which provide it.
-
-* Added a UserAdminOptions configuration option to CVSROOT/config to
-control which `cvs admin' commands are not restricted to the `cvsadmin'
-group.
-
-* If the rcsinfo specified template changes after a user has checked
-out a tree, the template in the users' tree will be updated rather
-than remaining static from the time of the original checkout.
-
-* Added a CVSREADONLYFS environment variable and `-R' cvs global
-option to turn on read-only repository mode for local repositories.
-This allows users to checkout from a CDROM repository or other
-read-only filesystem.
-
-* There is a new CVS_LOCAL_BRANCH_NUM environment variable, which
-may be used to give control over the branch number to be used next.
-Useful for having local changes in a CVSup mirrored repository.
-
-* Miscellaneous documentation corrections.
-
-* Corrected the path in a failed write error message.
-
-* Autoconf and Automake are no longer run automatically unless you run
-configure with --enable-maintainer-mode.  Accordingly, noautomake.sh is
-no longer needed and has been removed.
-
-* We've standardized on Automake version 1.7.5 and Autoconf version 2.57 to get
-at a few new macros.  Again, this should only really affect developers.  See
-the section of the INSTALL file about using the autotools if you are compiling
-CVS yourself.
-
-Changes from 1.11.4 to 1.11.5:
-
-* Fixed a security hole in the CVS server by which users with read only access
-could gain write access.  This issue does not affect client builds.  The
-Common Vulnerabilities and Exposures project (cve.mitre.org) has assigned the
-name CAN-2003-0015 to this issue.  See
-<http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2003-0015> for more
-information.
-
-* Fixed some bugs where revision numbers starting with 0 (like 0.3)
-weren't correctly handled.  (CVS doesn't normally use such revision
-numbers, but users may be able to force it to do so and old RCS files
-might.)
-
-Changes from 1.11.3 to 1.11.4:
-
-* Some minor changes to allow the code to compile on Windows platforms.
-
-Changes from 1.11.2 to 1.11.3:
-
-* The tag/rtag code has been fixed to once again lock just a single
-directory at a time.
-
-* There was a bug where certain error conditions could cause the server
-to go into an infinite loop.  There was also a bug that caused a
-compressed connection from an older client to hang on shutdown.  These
-bugs have been fixed.
-
-* Fixed a bug that caused the server to reject most watch commands.
-
-* When waiting for another user's lock, the message timestamps are now
-in UTC rather than the server's local time.
-
-* The options.h file is no longer used.  This fixes a bug that occurred when
-1.11.2 was compiled on Windows platforms.
-
-* We've standardized on Automake version 1.6.3 and Autoconf version 2.53.
-They are cleaner, less bug prone, and will hopfully allow me to start updating
-sanity.sh to use Autotest and Autoshell.  Again, this should only really affect
-developers.  See the section of the INSTALL file about using the autotools if
-you are compiling CVS yourself.
-
-* Fixed a bug in the log/rlog code when a revision range crosses a
-branch point.
-
-* Fixed a bug where filenames starting with - would be misinterpreted as
-options when using client/server mode.
-
-Changes from 1.11.1p1 to 1.11.2:
-
-* There is a new feature, enabled by RereadLogAfterVerify in CVSROOT/config,
-which tells CVS to reread the log message after running the verifymsg
-script.  This allows the verifymsg script to reformat or otherwise
-modify the log message.
-
-* The interpretation of revision ranges using :: in "log" and "rlog"
-has changed: a::b now excludes the log message from revision a but
-includes the log message from revision b.  Also, revision ranges that
-cross branch points should now work.
-
-* zlib has been updated to version 1.4.  There is a security advisory
-out in regards to 1.3.  This should fix that problem.
-
-* The "log" and "rlog" commands now have a -S option to suppress the
-header information when no revisions are selected.
-
-* A serious error that allowed read-only users to tag files has been
-corrected.
-
-* The "annotate" command will no longer annotate binary files unless
-you specify the new -F option.
-
-* The "tag" and "rtag" commands will no longer move or delete branch
-tags unless you use the new -B option.  (This prevents accidental
-changes to branch tags that are hard to undo.)
-
-* We've standardized on the 1.5 Automake release for the moment.  Again, this
-should only really affect developers.  See the section of the INSTALL file
-about using the autotools if you are compiling CVS yourself.
-
-Changes from 1.11.1 to 1.11.1p1:
-
-* Read only access was broken - now fixed.
-
-Changes from 1.11 to 1.11.1:
-
-* There was a locking bug in the tag/rtag code that could lose changes
-made to a file while the tag operation was in progress.  This has been
-fixed, but all of the directories being tagged are now locked for the
-entire duration of the tag operation rather than only one directory at a
-time.
-
-* The "cvs diff" command now accepts the -y/--side=by-side and -T/
---initial-tab options.  (To use these options with a remote repository,
-both the client and the server must support them.)
-
-* The expansion of the loginfo format string has changed slightly. 
-Previously, the expansion was surrounded by single quotes ('); if a file
-name contained a single quote character, the string would not be parsed
-as a single entity by the Unix shell (and it would not be possible to
-parse it unambiguously).  Now the expansion is surrounded by double
-quotes (") and any embedded dollar signs ($), backticks (`), backslashes
-(\), and double quotes are preceded by a backslash.  This is parsed as a
-single entity by the shell reguardless of content.  This change should
-not be noticable unless you're not using a Unix shell or you have
-embedded the format string inside a double quoted string.
-
-* There was a bug in the diff code which sometimes caused conflicts to
-be flagged which shouldn't have been.  This has been fixed.
-
-* New "cvs rlog" and "cvs rannotate" commands have been added to get log
-messages and annotations without having to have a checked-out copy.
-
-* Exclusive revision ranges have been added to "cvs log" using ::
-(similar to "cvs admin -o").
-
-* The VMS client now accepts wildcards if you're running VMS 7.x.
-
-* ZLIB has been updated to version 1.1.3, the most current version.  This
-includes mostly some optimizations and minor bug fixes.
-
-* The ~/.cvspass file has a slightly modified format.  CVSROOTs are now
-stored in a new canonical form - hostnames are now case insensitive and
-port numbers are always stored in the new format.  Until a new login for
-a particular CVSROOT is performed with the new version of CVS, new and
-old versions of CVS should interoperate invisibly.  After that point, an
-extra login using the old version of CVS may be necessary to continue to
-allow the new and old versions of CVS to interoperate using the same
-~/.cvspass file and CVSROOT. The exception to this rule occurs when the
-CVSROOTs used with the different versions use case insensitively
-different hostnames, for example, "empress", and "empress.2-wit.com".
-
-* A password and a port number may now be specified in CVSROOT for
-pserver connections.  The new format is:
-
-    :pserver:[[user][:password]@]host[:[port]]/path
-
-Note that passwords specified in a checkout command will be saved in the
-clear in the CVS/Root file in each created directory, so this is not
-recommended, except perhaps when accessing anonymous repositories or the
-like.
-
-* The distribution has been converted to use Automake.  This shouldn't
-affect most users except to ease some portability concerns, but if you
-are building from the repository and encounter problems with the
-makefiles, you might try running ./noautomake.sh after a fresh update
--AC.
-
-Changes from 1.10 to 1.11:
-
-* The "cvs update" command has a new -C option to get clean copies from
-the repository, abandoning any local changes.
-
-* The new "cvs version" command gives a short version message.  If
-the repository is remote, both the client and server versions are
-reported.
-
-* "cvs admin -t" now works correctly in client/server mode.
-
-* The "cvs history" command output format has changed -- the date
-now includes the year and is given is ISO 8601 format (yyyy-mm-dd).
-Also, the new LogHistory option in CVSROOT/config can be used to
-control what information gets recorded in the log file and code has
-been added to record file removals.
-
-* The buggy PreservePermissions code has been disabled.
-
-* Anonymous read-only access can now be done without requiring a
-password.  On the server side, simply give that user (presumably
-`anonymous') an empty password in the CVSROOT/passwd file, and then
-any received password will authenticate successfully.
-
-* There is a new access method :fork: which is similar to :local:
-except that it is implemented via the CVS remote protocol, and thus
-has a somewhat different set of quirks and bugs.
-
-* The -d command line option no longer updates the CVS/Root file.  For
-one thing, the CVS 1.9/1.10 behavior never had updated CVS/Root in
-subdirectories, and for another, it didn't seem that popular in
-general.  So this change restores the CVS 1.8 behavior (which is also
-the CVS 1.9/1.10 behavior if the environment variable
-CVS_IGNORE_REMOTE_ROOT is set; with this change,
-CVS_IGNORE_REMOTE_ROOT no longer has any effect).
-
-* It is now possible for a single CVS command to recurse into several
-CVS roots.  This includes roots which are located on several servers,
-or which are both remote and local.  CVS will make connections to as
-many servers as necessary.
-
-* It is now possible to put the CVS lock files in a directory
-set by the new LockDir option in CVSROOT/config.  The default
-continues to be to put the lock files in the repository itself.
-
-Changes from 1.9 to 1.10:
-
-* A bug was discovered in the -t/-f wrapper support that can cause
-serious data loss.  Because of this (and also the fact that it doesn't
-work at all in client/server mode), the -t/-f wrapper code has been
-disabled until it can be fixed.
-
-* There is a new feature, enabled by TopLevelAdmin in CVSROOT/config,
-which tells CVS to modify the behavior of the "checkout" command.  The
-command now creates a CVS directory at the top level of the new
-working directory, in addition to CVS directories created within
-checked-out directories.  See the Cederqvist for details.
-
-* There is an optional set of features, enabled by PreservePermissions
-in CVSROOT/config, which allow CVS to store unix-specific file
-information such as permissions, file ownership, and links.  See the
-Cederqvist for details.
-
-* One can now authenticate and encrypt using the GSSAPI network
-security interface.  For details see the Cederqvist's description of
-specifying :gserver: in CVSROOT, and the -a global option.
-
-* All access to RCS files is now implemented internally rather than by
-calling RCS programs.  The main user-visible consequence of this is
-that there is no need to worry about making sure that CVS finds the
-correct version of RCS.  The -b global option and the RCSBIN setting
-in CVSROOT/config are still accepted but don't do anything.  The
-$RCSBIN internal variable in administrative files is no longer
-accepted.
-
-* There is a new syntax, "cvs admin -orev1::rev2", which collapses the
-revisions between rev1 and rev2 without deleting rev1 or rev2
-themselves.
-
-* There is a new administrative file CVSROOT/config which allows one
-to specify miscellaneous aspects of CVS configuration.  Currently
-supported here:
-
-  - SystemAuth, allows you to prevent pserver from checking for system
-  usernames/passwords.
-
-For more information see the "config" section of cvs.texinfo.
-
-* When setting up the pserver server, one now must specify the
-allowable CVSROOT directories in inetd.conf.  See the Password
-authentication server section of cvs.texinfo for details.  Note that
-this implies that everyone who is running a pserver server must edit
-inetd.conf when upgrading their CVS.
-
-* The client no longer needs an external patch program (assuming both
-the client and the server have been updated to the new version).
-
-* "cvs admin [options]" will now recurse.  In previous versions of
-CVS, it was an error and one needed to specify "cvs admin [options] ."
-to recurse.  This change brings admin in line with the other CVS
-commands.
-
-* New "logout" command to remove the password for a remote cvs
-repository from the cvspass file.
-
-* Read-only repository access is implemented for the
-password-authenticated server (other access methods are just governed
-by Unix file permissions, since they require login access to the
-repository machine anyway).  See the "Repository" section of
-cvs.texinfo for details, including a discussion of security issues.
-Note that the requirement that read-only users be able to create locks
-and write the history file still applies.
-
-* There is a new administrative file verifymsg which is like editinfo
-but merely validates the message, rather than also getting it from the
-user.  It therefore works with client/server CVS or if one uses the -m
-or -F options to commit.  See the verifymsg section of cvs.texinfo for
-details.
-
-* The %s format formerly accepted in loginfo has been extended to
-formats such as %{sVv}, so that loginfo scripts have access to the
-version numbers being changed.  See the Loginfo section of cvs.texinfo
-for details.
-
-* The postscript documentation (doc/cvs.ps) shipped with CVS is now
-formatted for US letter size instead of A4.  This is not because we
-consider this size "better" than A4, but because we believe that the
-US letter version will print better on A4 paper than the other way
-around.
-
-* The "cvs export" command is now logged in the history file and there
-is a "cvs history -x E" command to select history file entries
-produced by export.
-
-* CVS no longer uses the CVS_PASSWORD environment variable.  Storing
-passwords in cleartext in an environment variable is a security risk,
-especially since (on BSD variants) any user on the system can display
-any process's environment using 'ps'.  Users should use the 'cvs
-login' command instead.
-
-
-Changes from 1.8 to 1.9:
-
-* Windows NT client should now work on Windows 95 as well.
-
-* New option "--help-synonyms" prints a list of all recognized command
-synonyms.
-
-* The "log" command is now implemented internally rather than via the
-RCS "rlog" program.  The main user-visible consequence is that
-symbolic branch names now work (for example "cvs log -rbranch1").
-Also, the date formats accepted by -d have changed.  They previously
-had been a bewildering variety of poorly-documented date formats.  Now
-they are the same as the date formats accepted by the -D options to
-the other CVS commands, which is also a (different) bewildering
-variety of poorly-documented date formats, but at least we are
-consistently bewildering :-).
-
-* Encryption is now supported over a Kerberos client/server
-connection.  The new "-x" global option requests it.  You must
-configure with the --enable-encryption option in order to enable
-encryption.
-
-* The format of the CVS commit message has changed slightly when
-committing changes on a branch.  The tag on which the commit is
-ocurring is now reported correctly in all cases.
-
-* New flag -k in wrappers allows you to specify the keyword expansion
-mode for added files based on their name.  For example, you can
-specify that files whose name matches *.exe are binary by default.
-See the Wrappers section of cvs.texinfo for more details.
-
-* Remote CVS with the "-z" option now uses the zlib library (included
-with CVS) to compress all communication between the client and the
-server, rather than invoking gzip on each file separately.  This means
-that compression is better and there is no need for an external gzip
-program (except to interoperate with older version of CVS).
-
-* The "cvs rlog" command is deprecated and running it will print a
-warning; use the synonymous "cvs log" command instead.  It is
-confusing for rlog to mean the same as log because some other CVS
-commands are in pairs consisting of a plain command which operates on
-a working directory and an "r" command which does not (diff/rdiff;
-tag/rtag).
-
-* "cvs diff" has a bunch of new options, mostly long options.  Most of
-these work only if rcsdiff and diff support them, and are named the
-same as the corresponding options to diff.
-
-* The -q and -Q command options to "cvs diff" were removed (use the
-global options instead).  This brings "cvs diff" into line with the
-rest of the CVS commands.
-
-* The "annotate" command can now be used to annotate a revision other
-than the head revision on the trunk (see the -r, -D, and -f options in
-the annotate node of cvs.texinfo for details).
-
-* The "tag" command has a new option "-c" which checks that all files
-  are not locally modified before tagging.
-
-* The -d command line option now overrides the cvsroot setting stored
-in the CVS/Root file in each working directory, and specifying -d will
-cause CVS/Root to be updated.
-
-* Local (non-client/server) CVS now runs on Windows NT.  See
-windows-NT/README for details.
-
-* The CVSROOT variable specification has changed to support more
-access methods.  In addition to "pserver," "server" (internal rsh
-client), "ext" (external rsh client), "kserver" (kerberos), and
-"local" (local filesystem access) can now be specified.  For more
-details on each method, see cvs.texinfo (there is an index entry for
-:local: and each of the other access methods).
-
-* The "login" command no longer prompts the user for username and
-hostname, since one will have to provide that information via the `-d'
-flag or by setting CVSROOT.
-
-Changes from 1.7 to 1.8:
-
-* New "cvs annotate" command to display the last modification for each
-line of a file, with the revision number, user checking in the
-modification, and date of the modification.  For more information see
-the `annotate' node in cvs.texinfo.
-
-* The cvsinit shell script has been replaced by a cvs init command.
-The cvs init command creates some example administrative files which
-are similar to the files found in the examples directory (and copied
-by cvsinit) in previous releases.
-
-* Added the patterns *.olb *.exe _$* *$ to default ignore list.
-
-* There is now a $USER internal variable for *info files.
-
-* There is no longer a separate `mkmodules' program; the functionality
-is now built into `cvs'.  If upgrading an old repository, it is OK to
-leave in the lines in the modules file which run mkmodules (the
-mkmodules actions will get done twice, but that is harmless); you will
-probably want to remove them once you are no longer using the old CVS.
-
-* One can now specify user variables in *info files via the
-${=varname} syntax; there is a -s global option to set them.  See the
-Variables node in cvs.texinfo for details.
-
-Changes from 1.6 to 1.7:
-
-* The default ignore list has changed slightly: *.obj has been added
-and CVS* has been changed to CVS CVS.adm.
-
-* CVS now supports password authentication when accessing remote
-repositories; this is useful for sites that can't use rsh (because of
-a firewall, for example), and also don't have kerberos.  See node
-"Password authenticated" (in "Remote repositories", in
-doc/cvs.texinfo) for more details.  Note: This feature requires both
-the client and server to be upgraded.
-
-* Using the -kb option to specify binary files now works--most cases
-did not work before.  See the "Binary files" section of
-doc/cvs.texinfo for details.
-
-* New developer communication features.  See the "Watches" section of
-doc/cvs.texinfo for details.
-
-* RCS keyword "Name" supported for "cvs update -r <tag>" and "cvs
-checkout -r <tag>".
-
-* If there is a group whose name matches a compiled in value which
-defaults to "cvsadmin", only members of that group can use "cvs
-admin".  This replaces the CVS_NOADMIN option.
-
-* CVS now sets the modes of files in the repository based on the
-CVSUMASK environment variable or a compiled in value defaulting to
-002.  This way other developers will be able to access the files in
-the repository regardless of the umask of the developer creating them.
-
-* The command names in .cvsrc now match the official name of the
-command, not the one (possibly an alias) by which it was invoked.  If
-you had previously relied on "cvs di" and "cvs diff" using different
-options, instead use a shell function or alias (for example "alias
-cvsdi='cvs diff -u'").  You also can specify global CVS options (like
-"-z") using the command name "cvs".
-
-Changes from 1.5 to 1.6:
-
-* Del updated the man page to include all of the new features
-of CVS 1.6.
-
-* "cvs tag" now supports a "-r | -D" option for tagging an already
-tagged revision / specific revision of a file.
-
-* There is a "taginfo" file in CVSROOT that supports filtering and
-recording of tag operations.
-
-* Long options support added, including --help and --version options.
-
-* "cvs release" no longer cares whether or not the directory being
-released has an entry in the `modules' file.
-
-* The modules file now takes a -e option which is used instead of -o
-for "cvs export".  If your modules file has a -o option which you want
-to be used for "cvs export", change it to specify -e as well as -o.
-
-* "cvs export" now takes a -k option to set RCS keyword expansion.
-This way you can export binary files.  If you want the old behavior,
-you need to specify -kv.
-
-* "cvs update", "cvs rdiff", "cvs checkout", "cvs import", "cvs
-release", "cvs rtag", and "cvs tag" used to take -q and -Q options
-after the command name (e.g. "cvs update -q").  This was confusing
-because other commands, such as "cvs ci", did not.  So the options
-after the command name have been removed and you must now specify, for
-example, "cvs -q update", which has been supported since CVS 1.3.
-
-* New "wrappers" feature.  This allows you to set a hook which
-transforms files on their way in and out of cvs (apparently on the
-NeXT there is some particular usefulness in tarring things up in the
-repository).  It also allows you to declare files as merge-by-copy
-which means that instead of trying to merge the file, CVS will merely
-copy the new version.  There is a CVSROOT/cvswrappers file and an
-optionsl ~/.cvswrappers file to support this feature.
-
-* You can set CVSROOT to user@host:dir, not just host:dir, if your
-username on the server host is different than on the client host.
-
-* VISUAL is accepted as well as EDITOR.
-
-* $CVSROOT is expanded in *info files.
-
-Changes from 1.4A2 to 1.5:
-
-* Remote implementation.  This is very helpful when collaborating on a
-project with someone across a wide-area network.  This release can
-also be used locally, like other CVS versions, if you have no need for
-remote access.
-
-Here are some of the features of the remote implementation:
-- It uses reliable transport protocols (TCP/IP) for remote repository
-  access, not NFS.  NFS is unusable over long distances (and sometimes
-  over short distances)
-- It transfers only those files that have changed in the repository or
-  the working directory.  To save transmission time, it will transfer
-  patches when appropriate, and can compress data for transmission.
-- The server never holds CVS locks while waiting for a reply from the client;
-  this makes the system robust when used over flaky networks.
-
-The remote features are documented in doc/cvsclient.texi in the CVS
-distribution, but the main doc file, cvs.texinfo, has not yet been
-updated to include the remote features.
-
-* Death support.  See src/README-rm-add for more information on this.
-
-* Many speedups, especially from jtc@cygnus.com.
-
-* CVS 1.2 compatibility code has been removed as a speedup.  If you
-have working directories checked out by CVS 1.2, CVS 1.3 or 1.4A2 will
-try to convert them, but CVS 1.5 and later will not (if the working
-directory is up to date and contains no extraneous files, you can just
-remove it, and then check out a new working directory).  Likewise if
-your repository contains a CVSROOT.adm directory instead of a CVSROOT
-directory, you need to rename it.
-
-Fri Oct 21 20:58:54 1994  Brian Berliner  <berliner@sun.com>
-
-       * Changes between CVS 1.3 and CVS 1.4 Alpha-2
-
-       * A new program, "cvsbug", is provided to let you send bug reports
-       directly to the CVS maintainers.  Please use it instead of sending
-       mail to the info-cvs mailing list.  If your build fails, you may
-       have to invoke "cvsbug" directly from the "src" directory as
-       "src/cvsbug.sh".
-
-       * A new User's Guide and Tutorial, written by Per Cederqvist
-       <ceder@signum.se> of Signum Support.  See the "doc" directory.  A
-       PostScript version is included as "doc/cvs.ps".
-
-       * The Frequesntly Asked Questions file, FAQ, has been added to the
-       release.  Unfortunately, its contents are likely out-of-date.
-
-       * The "cvsinit" shell script is now installed in the $prefix/bin
-       directory like the other programs.  You can now create new
-       CVS repositories with great ease.
-
-       * Index: lines are now printed on output from 'diff' and 'rdiff',
-       in order to facilitate application of patches to multiple subdirs.
-
-       * Support for a ~/.cvsrc file, which allows you to specify options
-       that are always supposed to be given to a specific command.  This
-       feature shows the non-orthogonality of the option set, since while
-       there may be an option to turn something on, the option to turn
-       that same thing off may not exist.
-
-       * You can now list subdirectories that you wish to ignore in a
-       modules listing, such as:
-
-               gcc  -a gnu/gcc, !gnu/gcc/testsuites
-
-       which will check out everything underneath gnu/gcc, except
-       everything underneath gnu/gcc/testsuites.
-
-       * It is now much harder to accidentally overwrite an existing tag
-       name, since attempting to move a tag name will result in a error,
-       unless the -F (force) flag is given to the tag subcommands.
-
-       * Better error checking on matching of the repository used to
-       check code out from against the repository the current cvs
-       commnands would use. (Thanks to Mark Baushke <mdb@cisco.com>)
-
-       * Better support for sites with multiple CVSROOT repositories has
-       been contributed.  The file "CVS/Root" in your working directory
-       is created to hold the full path to the CVS repository and a
-       simple check is made against your current CVSROOT setting.
-
-       * You can now specify an RCS keyword substitution value when you
-       import files into the repository.
-
-       * Uses a much newer version of Autoconf, and conforms to the GNU
-       coding standards much more closely.  No, it still doesn't have
-       long option names.
-
-       * Code cleanup.  Many passes through gcc -Wall helped to identify
-       a number of questionable constructs.  Most arbitrary length limits
-       were removed.
-
-       * Profiling to determine bottlenecks helped to identify the best
-       places to spend time speeding up the code, which was then done.  A
-       number of performance enhancements in filename matching have sped
-       up checkouts.
-
-       * Many more contributions have been added to the "contrib"
-       directory.  See the README file in that directory for more
-       information.
-
-       * "cvs commit" will try harder to not change the file's
-       modification time after the commit.  If the file does not change
-       as a result of the commit operation, CVS will preserve the
-       original modification time, thus speeding up future make-type
-       builds.
-
-       * "cvs commit" now includes any removed files in the (optional)
-       pre-commit checking program that may be invoked.  Previously, only
-       added and modified files were included.
-
-       * It is now possible to commit a file directly onto the trunk at a
-       specific revision level by doing "cvs commit -r3.0 file.c", where
-       "3.0" specifies the revision you wish to create.  The file must be
-       up-to-date with the current head of the trunk for this to succeed.
-
-       * "cvs commit" will now function with a pre-commit program that
-       has arguments specified in the "commitinfo" file.
-
-       * The "mkmodules" program will now look within the
-       $CVSROOT/CVSROOT/checkoutlist" file for any additional files that
-       should be automatically checked out within CVSROOT; mkmodules also
-       tries harder to preserve any execute bits the files may have
-       originally had.
-
-       * "cvs diff" is much more accurate about its exit status now.  It
-       now returns the maximum exit status of any invoked diff.
-
-       * The "-I !" option is now supported for the import and update
-       commands correctly.  It will properly clear the ignore list now.
-
-       * Some problems with "cvs import" handling of .cvsignore have been
-       fixed; as well, some rampant recursion problems with import have
-       also been fixed.
-
-       * "cvs rdiff" (aka "cvs patch") now tries to set the modify time
-       of any temporary files it uses to match those specified for the
-       particular revision.  This allows a more accurate patch image to
-       be created.
-
-       * "cvs status" has improved revision descriptions.  "Working
-       revision" is used for the revision of the working file that you
-       edit directly; "Repository revision" is the revision of the file
-       with the $CVSROOT source repository.  Also, the output is clearer
-       with regard to sticky and branch revisions.
-
-       * CVS no longer dumps core when given a mixture of directories and
-       files in sub-directories (as in "cvs ci file1 dir1/file2").
-       Instead, arguments are now clumped into their respective directory
-       and operated on in chunks, together.
-
-       * If the CVSEDITOR environment variable is set, that editor is
-       used for log messages instead of the EDITOR environment variable.
-       This makes it easy to substitute intelligent programs to make more
-       elaborate log messages.  Contributed by Mark D Baushke
-       (mdb@cisco.com).
-
-       * Command argument changes:
-       cvs:                    The "-f" option has been added to ignore
-                               the ~/.cvsrc file.
-       commit:                 Renamed the "-f logfile" option to the
-                               "-F logfile" option.  Added the "-f"
-                               option to force a commit of the specified
-                               files (this disables recursion).
-       history:                Added "-t timezone" option to force any
-                               date-specific output into the specified
-                               timezone.
-       import:                 Added "-d" option to use the file's
-                               modification time as the time of the
-                               import. Added "-k sub" option to set the
-                               default RCS keyword substitution mode for
-                               newly-created files.
-       remove:                 Added "-f" option to force the file's
-                               automatic removal if it still exists in
-                               the working directory (use with caution).
-       rtag:                   Added "-F" option to move the tag if it
-                               already exists -- new default is to NOT
-                               move tags automatically.
-       tag:                    Added "-F" option to move the tag if it
-                               already exists -- new default is to NOT
-                               move tags automatically.
-
-Tue Apr  7 15:55:25 1992  Brian Berliner  (berliner at sun.com)
-
-       * Changes between CVS 1.3 Beta-3 and official CVS 1.3!
-
-       * A new shell script is provided, "./cvsinit", which can be run at
-       install time to help setup your $CVSROOT area.  This can greatly
-       ease your entry into CVS usage.
-
-       * The INSTALL file has been updated to include the machines on
-       which CVS has compiled successfully.  I think CVS 1.3 is finally
-       portable.  Thanks to all the Beta testers!
-
-       * Support for the "editinfo" file was contributed.  This file
-       (located in $CVSROOT/CVSROOT) can be used to specify a special
-       "editor" to run on a per-directory basis within the repository,
-       instead of the usual user's editor.  As such, it can verify that
-       the log message entered by the user is of the appropriate form
-       (contains a bugid and test validation, for example).
-
-       * The manual pages cvs(1) and cvs(5) have been updated.
-
-       * The "mkmodules" command now informs you when your modules file
-       has duplicate entries.
-
-       * The "add" command now preserves any per-directory sticky tag when
-       you add a new directory to your checked-out sources.
-
-       * The "admin" command is now a fully recursive interface to the
-       "rcs" program which operates on your checked-out sources.  It no
-       longer requires you to specify the full path to the RCS file.
-
-       * The per-file sticky tags can now be effectively removed with
-       "cvs update -A file", even if you had checked out the whole
-       directory with a per-directory sticky tag.  This allows a great
-       deal of flexibility in managing the revisions that your checked-out
-       sources are based upon (both per-directory and per-file sticky
-       tags).
-
-       * The "cvs -n commit" command now works, to show which files are
-       out-of-date and will cause the real commit to fail, or which files
-       will fail any pre-commit checks.  Also, the "cvs -n import ..."
-       command will now show you what it would've done without actually
-       doing it.
-
-       * Doing "cvs commit modules" to checkin the modules file will no
-       properly run the "mkmodules" program (assuming you have setup your
-       $CVSROOT/CVSROOT/modules file to do so).
-
-       * The -t option in the modules file (which specifies a program to
-       run when you do a "cvs rtag" operation on a module) now gets the
-       symbolic tag as the second argument when invoked.
-
-       * When the source repository is locked by another user, that user's
-       login name will be displayed as the holder of the lock.
-
-       * Doing "cvs checkout module/file.c" now works even if
-       module/file.c is in the Attic (has been removed from main-line
-       development).
-
-       * Doing "cvs commit */Makefile" now works as one would expect.
-       Rather than trying to commit everything recursively, it will now
-       commit just the files specified.
-
-       * The "cvs remove" command is now fully recursive.  To schedule a
-       file for removal, all you have to do is "rm file" and "cvs rm".
-       With no arguments, "cvs rm" will schedule all files that have been
-       physically removed for removal from the source repository at the
-       next "cvs commit".
-
-       * The "cvs tag" command now prints "T file" for each file that was
-       tagged by this invocation and "D file" for each file that had the
-       tag removed (as with "cvs tag -d").
-
-       * The -a option has been added to "cvs rtag" to force it to clean
-       up any old, matching tags for files that have been removed (in the
-       Attic) that may not have been touched by this tag operation.  This
-       can help keep a consistent view with your tag, even if you re-use
-       it frequently.
-
-Sat Feb 29 16:02:05 1992  Brian Berliner  (berliner at sun.com)
-
-       * Changes between CVS 1.3 Beta-2 and CVS 1.3 Beta-3
-
-       * Many portability fixes, thanks to all the Beta testers!  With any
-       luck, this Beta release will compile correctly on most anything.
-       Hey, what are we without our dreams.
-
-       * CVS finally has support for doing isolated development on a
-       branch off the current (or previous!) revisions.  This is also
-       extremely nice for generating patches for previously released
-       software while development is progressing on the next release.
-       Here's an example of creating a branch to fix a patch with the 2.0
-       version of the "foo" module, even though we are already well into
-       the 3.0 release.  Do:
-
-               % cvs rtag -b -rFOO_2_0 FOO_2_0_Patch foo
-               % cvs checkout -rFOO_2_0_Patch foo
-               % cd foo
-               [[ hack away ]]
-               % cvs commit
-
-       A physical branch will be created in the RCS file only when you
-       actually commit the change.  As such, forking development at some
-       random point in time is extremely light-weight -- requiring just a
-       symbolic tag in each file until a commit is done.  To fork
-       development at the currently checked out sources, do:
-
-               % cvs tag -b Personal_Hack
-               % cvs update -rPersonal_Hack
-               [[ hack away ]]
-               % cvs commit
-
-       Now, if you decide you want the changes made in the Personal_Hack
-       branch to be merged in with other changes made in the main-line
-       development, you could do:
-
-               % cvs commit                 # to make Personal_Hack complete
-               % cvs update -A              # to update sources to main-line
-               % cvs update -jPersonal_Hack # to merge Personal_Hack
-
-       to update your checked-out sources, or:
-
-               % cvs checkout -jPersonal_Hack module
-
-       to checkout a fresh copy.
-
-       To support this notion of forked development, CVS reserves
-       all even-numbered branches for its own use.  In addition, CVS
-       reserves the ".0" and ".1" branches.  So, if you intend to do your
-       own branches by hand with RCS, you should use odd-numbered branches
-       starting with ".3", as in "1.1.3", "1.1.5", 1.2.9", ....
-
-       * The "cvs commit" command now supports a fully functional -r
-       option, allowing you to commit your changes to a specific numeric
-       revision or symbolic tag with full consistency checks.  Numeric
-       tags are useful for bringing your sources all up to some revision
-       level:
-
-               % cvs commit -r2.0
-
-       For symbolic tags, you can only commit to a tag that references a
-       branch in the RCS file.  One created by "cvs rtag -b" or from
-       "cvs tag -b" is appropriate (see below).
-
-       * Roland Pesch <pesch@cygnus.com> and K. Richard Pixley
-       <rich@cygnus.com> were kind enough to contribute two new manual
-       pages for CVS: cvs(1) and cvs(5).  Most of the new CVS 1.3 features
-       are now documented, with the exception of the new branch support
-       added to commit/rtag/tag/checkout/update.
-
-       * The -j options of checkout/update have been added.  The "cvs join"
-       command has been removed.
-
-       With one -j option, CVS will merge the changes made between the
-       resulting revision and the revision that it is based on (e.g., if
-       the tag refers to a branch, CVS will merge all changes made in
-       that branch into your working file).
-
-       With two -j options, CVS will merge in the changes between the two
-       respective revisions.  This can be used to "remove" a certain delta
-       from your working file.  E.g., If the file foo.c is based on
-       revision 1.6 and I want to remove the changes made between 1.3 and
-       1.5, I might do:
-
-               % cvs update -j1.5 -j1.3 foo.c          # note the order...
-
-       In addition, each -j option can contain on optional date
-       specification which, when used with branches, can limit the chosen
-       revision to one within a specific date.  An optional date is
-       specified by adding a colon (:) to the tag, as in:
-
-               -jSymbolic_Tag:Date_Specifier
-
-       An example might be what "cvs import" tells you to do when you have
-       just imported sources that have conflicts with local changes:
-
-               % cvs checkout -jTAG:yesterday -jTAG module
-
-       which tells CVS to merge in the changes made to the branch
-       specified by TAG in the last 24 hours.  If this is not what is
-       intended, substitute "yesterday" for whatever format of date that
-       is appropriate, like:
-
-               % cvs checkout -jTAG:'1 week ago' -jTAG module
-
-       * "cvs diff" now supports the special tags "BASE" and "HEAD".  So,
-       the command:
-
-               % cvs diff -u -rBASE -rHEAD
-
-       will effectively show the changes made by others (in unidiff
-       format) that will be merged into your working sources with your
-       next "cvs update" command.  "-rBASE" resolves to the revision that
-       your working file is based on.  "-rHEAD" resolves to the current
-       head of the branch or trunk that you are working on.
-
-       * The -P option of "cvs checkout" now means to Prune empty
-       directories, as with "update".  The default is to not remove empty
-       directories.  However, if you do "checkout" with any -r options, -P
-       will be implied.  I.e., checking out with a tag will cause empty
-       directories to be pruned automatically.
-
-       * The new file INSTALL describes how to install CVS, including
-       detailed descriptions of interfaces to "configure".
-
-       * The example loginfo file in examples/loginfo has been updated to
-       use the perl script included in contrib/log.pl.  The nice thing
-       about this log program is that it records the revision numbers of
-       your change in the log message.
-
-       Example files for commitinfo and rcsinfo are now included in the
-       examples directory.
-
-       * All "#if defined(__STDC__) && __STDC__ == 1" lines have been
-       changed to be "#if __STDC__" to fix some problems with the former.
-
-       * The lib/regex.[ch] files have been updated to the 1.3 release of
-       the GNU regex package.
-
-       * The ndbm emulation routines included with CVS 1.3 Beta-2 in the
-       src/ndbm.[ch] files has been moved into the src/myndbm.[ch] files
-       to avoid any conflict with the system <ndbm.h> header file.  If
-       you had a previous CVS 1.3 Beta release, you will want to "cvs
-       remove ndbm.[ch]" form your copy of CVS as well.
-
-       * "cvs add" and "cvs remove" are a bit more verbose, telling you
-       what to do to add/remove your file permanently.
-
-       * We no longer mess with /dev/tty in "commit" and "add".
-
-       * More things are quiet with the -Q option set.
-
-       * New src/config.h option:  If CVS_BADROOT is set, CVS will not
-       allow people really logged in as "root" to commit changes.
-
-       * "cvs diff" exits with a status of 0 if there were no diffs, 1 if
-       there were diffs, and 2 if there were errors.
-
-       * "cvs -n diff" is now supported so that you can still run diffs
-       even while in the middle of committing files.
-
-       * Handling of the CVS/Entries file is now much more robust.
-
-       * The default file ignore list now includes "*.so".
-
-       * "cvs import" did not expand '@' in the log message correctly.  It
-       does now.  Also, import now uses the ignore file facility
-       correctly.
-
-       Import will now tell you whether there were conflicts that need to
-       be resolved, and how to resolve them.
-
-       * "cvs log" has been changed so that you can "log" things that are
-       not a part of the current release (in the Attic).
-
-       * If you don't change the editor message on commit, CVS now prompts
-       you with the choice:
-
-               !)reuse this message unchanged for remaining dirs
-
-       which allows you to tell CVS that you have no intention of changing
-       the log message for the remainder of the commit.
-
-       * It is no longer necessary to have CVSROOT set if you are using
-       the -H option to get Usage information on the commands.
-
-       * Command argument changes:
-       checkout:               -P handling changed as described above.
-                               New -j option (up to 2 can be specified)
-                               for doing rcsmerge kind of things on
-                               checkout.
-       commit:                 -r option now supports committing to a
-                               numeric or symbolic tags, with some
-                               restrictions.  Full consistency checks will
-                               be done.
-                               Added "-f logfile" option, which tells
-                               commit to glean the log message from the
-                               specified file, rather than invoking the
-                               editor.
-       rtag:                   Added -b option to create a branch tag,
-                               useful for creating a patch for a previous
-                               release, or for forking development.
-       tag:                    Added -b option to create a branch tag,
-                               useful for creating a patch for a previous
-                               release, or for forking development.
-       update:                 New -j option (up to 2 can be specified)
-                               for doing rcsmerge kind of things on
-                               update.
-
-Thu Jan  9 10:51:35 MST 1992 Jeff Polk (polk at BSDI.COM)
-
-       * Changes between CVS 1.3 Beta-1 and CVS 1.3 Beta-2
-
-       * Thanks to K. Richard Pixley at Cygnus we now have function
-       prototypes in all the files
-
-       * Some small changes to configure for portability.  There have
-       been other portability problems submitted that have not been fixed
-       (Brian will be working on those).  Additionally all __STDC__
-       tests have been modified to check __STDC__ against the constant 1 
-       (this is what the Second edition of K&R says must be true).
-
-       * Lots of additional error checking for forked processes (run_exec)
-       (thanks again to K. Richard Pixley)
-
-       * Lots of miscellaneous bug fixes - including but certainly not 
-       limited to:
-               various commit core dumps
-               various update core dumps
-               bogus results from status with numeric sticky tags
-               commitprog used freed memory
-               Entries file corruption caused by No_Difference
-               commit to revision broken (now works if branch exists)
-               ignore file processing broken for * and !
-               ignore processing didn't handle memory reasonably
-               miscellaneous bugs in the recursion processor
-               file descriptor leak in ParseInfo
-               CVSROOT.adm->CVSROOT rename bug
-               lots of lint fixes
-
-       * Reformatted all the code in src (with GNU indent) and then 
-       went back and fixed prototypes, etc since indent gets confused.  The
-       rationale is that it is better to do it sooner than later and now
-       everything is consistent and will hopefully stay that way.
-       The basic options to indent were: "-bad -bbb -bap -cdb -d0 -bl -bli0 
-       -nce -pcs -cs -cli4 -di1 -nbc -psl -lp -i4 -ip4 -c41"  and then
-       miscellaneous formatting fixes were applied.  Note also that the 
-       "-nfc1" or "-nfca" may be appropriate in files where comments have
-       been carefully formatted (e.g, modules.c).
-
-Sat Dec 14 20:35:22 1991  Brian Berliner  (berliner at sun.com)
-
-       * Changes between CVS 1.2 and CVS 1.3 Beta are described here.
-
-       * Lots of portability work.  CVS now uses the GNU "configure"
-       script to dynamically determine the features provided by your
-       system.  It probably is not foolproof, but it is better than
-       nothing.  Please let me know of any portability problems.  Some
-       file names were changed to fit within 14-characters.
-
-       * CVS has a new RCS parser that is much more flexible and
-       extensible.  It should read all known RCS ",v" format files.
-
-       * Most of the commands now are fully recursive, rather than just
-       operating on the current directory alone.  This includes "commit",
-       which makes it real easy to do an "atomic" commit of all the
-       changes made to a CVS hierarchy of sources.  Most of the commands
-       also correctly handle file names that are in directories other than
-       ".", including absolute path names.  Commands now accept the "-R"
-       option to force recursion on (though it is always the default now)
-       and the "-l" option to force recursion off, doing just "." and not
-       any sub-directories.
-
-       * CVS supports many of the features provided with the RCS 5.x
-       distribution - including the new "-k" keyword expansion options.  I
-       recommend using RCS 5.x (5.6 is the current official RCS version)
-       and GNU diff 1.15 (or later) distributions with CVS.
-
-       * Checking out files with symbolic tags/dates is now "sticky", in
-       that CVS remembers the tag/date used for each file (and directory)
-       and will use that tag/date automatically on the next "update" call.
-       This stickyness also holds for files checked out with the the new
-       RCS 5.x "-k" options.
-
-       * The "cvs diff" command now recognizes all of the rcsdiff 5.x
-       options.  Unidiff format is available by installing the GNU
-       diff 1.15 distribution.
-
-       * The old "CVS.adm" directories created on checkout are now called
-       "CVS" directories, to look more like "RCS" and "SCCS".  Old CVS.adm
-       directories are automagically converted to CVS directories.  The
-       old "CVSROOT.adm" directory within the source repository is
-       automagically changed into a "CVSROOT" directory as well.
-
-       * Symbolic links in the source repository are fully supported ONLY
-       if you use RCS 5.6 or later and (of course) your system supports
-       symlinks.
-
-       * A history database has been contributed which maintains the
-       history of certain CVS operations, as well as providing a wide array
-       of querying options.
-
-       * The "cvs" program has a "-n" option which can be used with the
-       "update" command to show what would be updated without actually
-       doing the update, like:  "cvs -n update".  All usage statements
-       have been cleaned up and made more verbose.
-
-       * The module database parsing has been rewritten.  The new format
-       is compatible with the old format, but with much more
-       functionality.  It allows modules to be created that grab pieces or
-       whole directories from various different parts of your source
-       repository.  Module-relative specifications are also correctly
-       recognized now, like "cvs checkout module/file.c".
-
-       * A configurable template can be specified such that on a "commit", 
-       certain directories can supply a template that the user must fill
-       before completing the commit operation.
-
-       * A configurable pre-commit checking program can be specified which
-       will run to verify that a "commit" can happen.  This feature can be
-       used to restrict certain users from changing certain pieces of the
-       source repository, or denying commits to the entire source
-       repository.
-
-       * The new "cvs export" command is much like "checkout", but
-       establishes defaults suitable for exporting code to others (expands
-       out keywords, forces the use of a symbolic tag, and does not create
-       "CVS" directories within the checked out sources.
-
-       * The new "cvs import" command replaces the deprecated "checkin"
-       shell script and is used to import sources into CVS control.  It is
-       also much faster for the first-time import.  Some algorithmic
-       improvements have also been made to reduce the number of
-       conflicting files on next-time imports.
-
-       * The new "cvs admin" command is basically an interface to the
-       "rcs" program.  (Not yet implemented very well).
-
-       * Signal handling (on systems with BSD or POSIX signals) is much
-       improved.  Interrupting CVS now works with a single interrupt!
-
-       * CVS now invokes RCS commands by direct fork/exec rather than
-       calling system(3).  This improves performance by removing a call to
-       the shell to parse the arguments.
-
-       * Support for the .cvsignore file has been contributed.  CVS will
-       now show "unknown" files as "? filename" as the result of an "update"
-       command.  The .cvsignore file can be used to add files to the
-       current list of ignored files so that they won't show up as unknown.
-
-       * Command argument changes:
-       cvs:            Added -l to turn off history logging.
-                       Added -n to show what would be done without actually
-                       doing anything.
-                       Added -q/-Q for quiet and really quiet settings.
-                       Added -t to show debugging trace.
-       add:            Added -k to allow RCS 5.x -k options to be specified.
-       admin:          New command; an interface to rcs(1).
-       checkout:       Added -A to reset sticky tags/date/options.
-                       Added -N to not shorten module paths.
-                       Added -R option to force recursion.
-                       Changed -p (prune empty directories) to -P option.
-                       Changed -f option; forcing tags match is now default.
-                       Added -p option to checkout module to standard output.
-                       Added -s option to cat the modules db with status.
-                       Added -d option to checkout in the specified directory.
-                       Added -k option to use RCS 5.x -k support.
-       commit:         Removed -a option; use -l instead.
-                       Removed -f option.
-                       Added -l option to disable recursion.
-                       Added -R option to force recursion.
-                       If no files specified, commit is recursive.
-       diff:           Now recognizes all RCS 5.x rcsdiff options.
-                       Added -l option to disable recursion.
-                       Added -R option to force recursion.
-       history:        New command; displays info about CVS usage.
-       import:         Replaces "checkin" shell script; imports sources
-                       under CVS control.  Ignores files on the ignore
-                       list (see -I option or .cvsignore description above).
-       export:         New command; like "checkout", but w/special options
-                       turned on by default to facilitate exporting sources.
-       join:           Added -B option to join from base of the branch;
-                       join now defaults to only joining with the top two
-                       revisions on the branch.
-                       Added -k option for RCS 5.x -k support.
-       log:            Supports all RCS 5.x options.
-                       Added -l option to disable recursion.
-                       Added -R option to force recursion.
-       patch:          Changed -f option; forcing tags match is now default.
-                       Added -c option to force context-style diffs.
-                       Added -u option to support unidiff-style diffs.
-                       Added -V option to support RCS specific-version
-                       keyword expansion formats.
-                       Added -R option to force recursion.
-       remove:         No option changes.  It's a bit more verbose.
-       rtag:           Equivalent to the old "cvs tag" command.
-                       No option changes.  It's a lot faster for re-tag.
-       status:         New output formats with more information.
-                       Added -l option to disable recursion.
-                       Added -R option to force recursion.
-                       Added -v option to show symbolic tags for files.
-       tag:            Functionality changed to tag checked out files
-                       rather than modules; use "rtag" command to get the
-                       old "cvs tag" behaviour.
-       update:         Added -A to reset sticky tags/date/options.
-                       Changed -p (prune empty directories) to -P option.
-                       Changed -f option; forcing tags match is now default.
-                       Added -p option to checkout module to standard output.
-                       Added -I option to add files to the ignore list.
-                       Added -R option to force recursion.
-
-       Major Contributors:
-
-       * Jeff Polk <polk@bsdi.com> rewrote most of the grody code of CVS
-       1.2.  He made just about everything dynamic (by using malloc),
-       added a generic hashed list manager, re-wrote the modules database
-       parsing in a compatible - but extended way, generalized directory
-       hierarchy recursion for virtually all the commands (including
-       commit!), generalized the loginfo file to be used for pre-commit
-       checks and commit templates, wrote a new and flexible RCS parser,
-       fixed an uncountable number of bugs, and helped in the design of
-       future CVS features.  If there's anything gross left in CVS, it's
-       probably my fault!
-
-       * David G. Grubbs <dgg@odi.com> contributed the CVS "history" and
-       "release" commands.  As well as the ever-so-useful "-n" option of
-       CVS which tells CVS to show what it would do, without actually
-       doing it.  He also contributed support for the .cvsignore file.
-
-       * Paul Sander, HaL Computer Systems, Inc. <paul@hal.com> wrote and
-       contributed the code in lib/sighandle.c.  I added support for
-       POSIX, BSD, and non-POSIX/non-BSD systems.
-
-       * Free Software Foundation contributed the "configure" script and
-       other compatibility support in the "lib" directory, which will help
-       make CVS much more portable.
-
-       * Many others have contributed bug reports and enhancement requests.
-       Some have even submitted actual code which I have not had time yet
-       to integrate into CVS.  Maybe for the next release.
-
-       * Thanks to you all!
-
-Wed Feb  6 10:10:58 1991  Brian Berliner  (berliner at sun.com)
-
-       * Changes from CVS 1.0 Patchlevel 1 to CVS 1.0 Patchlevel 2; also
-       known as "Changes from CVS 1.1 to CVS 1.2".
-
-       * Major new support with this release is the ability to use the
-       recently-posted RCS 5.5 distribution with CVS 1.2.  See below for
-       other assorted bug-fixes that have been thrown in.
-
-       * ChangeLog (new): Added Emacs-style change-log file to CVS 1.2
-       release.  Chronological description of changes between release.
-
-       * README: Small fixes to installation instructions.  My email
-       address is now "berliner@sun.com".
-
-       * src/Makefile: Removed "rcstime.h".  Removed "depend" rule.
-
-       * src/partime.c:  Updated to RCS 5.5 version with hooks for CVS.
-       * src/maketime.c: Updated to RCS 5.5 version with hooks for CVS.
-       * src/rcstime.h:  Removed from the CVS 1.2 distribution.
-       Thanks to Paul Eggert <eggert@twinsun.com> for these changes.
-
-       * src/checkin.csh: Support for RCS 5.5 parsing.
-       Thanks to Paul Eggert <eggert@twinsun.com> for this change.
-
-       * src/collect_sets.c (Collect_Sets): Be quieter if "-f" option is
-       specified.  When checking out files on-top-of other files that CVS
-       doesn't know about, run a diff in the hopes that they are really
-       the same file before aborting.
-
-       * src/commit.c (branch_number): Fix for RCS 5.5 parsing.
-       Thanks to Paul Eggert <eggert@twinsun.com> for this change.
-
-       * src/commit.c (do_editor): Bug fix - fprintf missing argument
-       which sometimes caused core dumps.
-
-       * src/modules.c (process_module): Properly NULL-terminate
-       update_dir[] in all cases.
-
-       * src/no_difference.c (No_Difference): The wrong RCS revision was
-       being registered in certain (strange) cases.
-
-       * src/patch.c (get_rcsdate): New algorithm.  No need to call
-       maketime() any longer.
-       Thanks to Paul Eggert <eggert@twinsun.com> for this change.
-
-       * src/patchlevel.h: Increased patch level to "2".
-
-       * src/subr.c (isdir, islink): Changed to compare stat mode bits
-       correctly.
-
-       * src/tag.c (tag_file): Added support for following symbolic links
-       that are in the master source repository when tagging.  Made tag
-       somewhat quieter in certain cases.
-
-       * src/update.c (update_process_lists): Unlink the user's file if it
-       was put on the Wlist, meaning that the user's file is not modified
-       and its RCS file has been removed by someone else.
-
-       * src/update.c (update): Support for "cvs update dir" to correctly
-       just update the argument directory "dir".
-
-       * src/cvs.h: Fixes for RCS 5.5 parsing.
-       * src/version_number.c (Version_Number): Fixes for parsing RCS 5.5
-       and older RCS-format files.
-       Thanks to Paul Eggert <eggert@twinsun.com> for these changes.
-
-       * src/version_number.c (Version_Number): Bug fixes for "-f" option.
-       Bug fixes for parsing with certain branch numbers.  RCS
-       revision/symbol parsing is much more solid now.
-
-Wed Feb 14 10:01:33 1990  Brian Berliner  (berliner at sun.com)
-
-       * Changes from CVS 1.0 Patchlevel 0 to CVS 1.0 Patchlevel 1; also
-       known as "Changes from CVS 1.0 to CVS 1.1".
-
-       * src/patch.c (get_rcsdate): Portability fix.  Replaced call to
-       timelocal() with call to maketime().
-
-Mon Nov 19 23:15:11 1990  Brian Berliner  (berliner at prisma.com)
-
-       * Sent CVS 1.0 release to comp.sources.unix moderator and FSF.
-
-       * Special thanks to Dick Grune <dick@cs.vu.nl> for his work on the
-       1986 version of CVS and making it available to the world.  Dick's
-       version is available on uunet.uu.net in the
-       comp.sources.unix/volume6/cvs directory.
diff --git a/contrib/cvs-1.12/PROJECTS b/contrib/cvs-1.12/PROJECTS
deleted file mode 100644 (file)
index b46eb2a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-This is a list of projects for CVS.  In general, unlike the things in
-the TODO file, these need more analysis to determine if and how
-worthwhile each task is.
-
-I haven't gone through TODO, but it's likely that it has entries that
-are actually more appropriate for this list.
-
-0. Improved Efficency
-
-* CVS uses a single doubly linked list/hash table data structure for
-  all of its lists.  Since the back links are only used for deleting
-  list nodes it might be beneficial to use singly linked lists or a
-  tree structure.  Most likely, a single list implementation will not
-  be appropriate for all uses.
-
-  One easy change would be to remove the "type" field out of the list
-  and node structures.  I have found it to be of very little use when
-  debugging, and each instance eats up a word of memory.  This can add
-  up and be a problem on memory-starved machines.
-
-  Profiles have shown that on fast machines like the Alpha, fsortcmp()
-  is one of the hot spots.
-
-* Dynamically allocated character strings are created, copied, and
-  destroyed throughout CVS.  The overhead of malloc()/strcpy()/free()
-  needs to be measured.  If significant, it could be minimized by using a
-  reference counted string "class".
-
-* File modification time is stored as a character string.  It might be
-  worthwile to use a time_t internally if the time to convert a time_t
-  (from struct stat) to a string is greater that the time to convert a
-  ctime style string (from the entries file) to a time_t.  time_t is
-  an machine-dependant type (although it's pretty standard on UN*X
-  systems), so we would have to have different conversion routines.
-  Profiles show that both operations are called about the same number
-  of times.
-
-* stat() is one of the largest performance bottlenecks on systems
-  without the 4.4BSD filesystem.  By spliting information out of
-  the filesystem (perhaps the "rename database") we should be 
-  able to improve performance.
-
-* Parsing RCS files is very expensive.  This might be unnecessary if
-  RCS files are only used as containers for revisions, and tag,
-  revision, and date information was available in easy to read 
-  (and modify) indexes.  This becomes very apparent with files
-  with several hundred revisions.
-
-1. Improved testsuite/sanity check script
-
-* Need to use a code coverage tool to determine how much the sanity
-  script tests, and fill in the holes.
-
diff --git a/contrib/cvs-1.12/TODO b/contrib/cvs-1.12/TODO
deleted file mode 100644 (file)
index 783bf60..0000000
+++ /dev/null
@@ -1,853 +0,0 @@
-The "TODO" file!                              -*-Indented-Text-*-
-
-38. Think hard about using RCS state information to allow one to checkin
-    a new vendor release without having it be accessed until it has been
-    integrated into the local changes.
-
-39. Think about a version of "cvs update -j" which remembers what from
-    that other branch is already merged.  This has pitfalls--it could
-    easily lead to invisible state which could confuse users very
-    rapidly--but having to create a tag or some such mechanism to keep
-    track of what has been merged is a pain.  Take a look at PRCS 1.2.
-    PRCS 1.0 was particularly bad the way it handled the "invisible
-    state", but 1.2 is significantly better.
-
-52. SCCS has a feature that I would *love* to see in CVS, as it is very
-    useful.  One may make a private copy of SCCS suid to a particular user,
-    so other users in the authentication list may check files in and out of
-    a project directory without mucking about with groups.  Is there any
-    plan to provide a similar functionality to CVS?  Our site (and, I'd
-    imagine, many other sites with large user bases) has decided against
-    having the user-groups feature of unix available to the users, due to
-    perceived administrative, technical and performance headaches.  A tool
-    such as CVS with features that provide group-like functionality would
-    be a huge help.
-
-62. Consider using revision controlled files and directories to handle the
-    new module format -- consider a cvs command front-end to
-    add/delete/modify module contents, maybe.
-
-63. The "import" and vendor support commands (co -j) need to be documented
-    better.
-
-66. Length of the CVS temporary files must be limited to 14 characters for
-    System-V stupid support.  As well as the length on the CVS.adm files.
-
-72. Consider re-design of the module -t options to use the file system more
-    intuitively.
-
-73. Consider an option (in .cvsrc?) to automatically add files that are new
-    and specified to commit.
-
-79. Might be nice to have some sort of interface to Sun's Translucent
-    (?) File System and tagged revisions.
-
-82. Maybe the import stuff should allow an arbitrary revision to be
-    specified.
-
-84. Improve the documentation about administration of the repository and
-    how to add/remove files and the use of symbolic links.
-
-85. Make symbolic links a valid thing to put under version control.
-    Perhaps use one of the tag fields in the RCS file?  Note that we
-    can only support symlinks that are relative and within the scope of
-    the sources being controlled.
-
-93. Need to think hard about release and development environments.  Think
-    about execsets as well.
-
-98. If diff3 bombs out (too many differences) cvs then thinks that the file
-    has been updated and is OK to be commited even though the file 
-    has not yet been merged.
-
-100. Checked out files should have revision control support.  Maybe.
-
-102. Perhaps directory modes should be propagated on all import check-ins.
-     Not necessarily uid/gid changes.
-
-103. setuid/setgid on files is suspect.
-
-104. cvs should recover nicely on unreadable files/directories.
-
-105. cvs should have administrative tools to allow for changing permissions
-     and modes and what not.  In particular, this would make cvs a
-     more attractive alternative to rdist.
-
-107. It should be possible to specify a list of symbolic revisions to
-     checkout such that the list is processed in reverse order looking for
-     matches within the RCS file for the symbolic revision.  If there is
-     not a match, the next symbolic rev on the list is checked, and so on,
-     until all symbolic revs are exhausted.  This would allow one to, say,
-     checkout "4.0" + "4.0.3" + "4.0.3Patch1" + "4.0.3Patch2" to get the
-     most recent 4.x stuff.  This is usually handled by just specifying the
-     right release_tag, but most people forget to do this.
-
-108. If someone creates a whole new directory (i.e. adds it to the cvs
-     repository) and you happen to have a directory in your source farm by
-     the same name, when you do your cvs update -d it SILENTLY does
-     *nothing* to that directory.  At least, I think it was silent;
-     certainly, it did *not* abort my cvs update, as it would have if the
-     same thing had happened with a file instead of a directory.
-
-109. I had gotten pieces of the sys directory in the past but not a
-     complete tree.  I just did something like:
-
-        cvs get *
-
-     Where sys was in * and got the message
-
-        cvs get: Executing 'sys/tools/make_links sys'
-        sh: sys/tools/make_links: not found
-
-     I suspect this is because I didn't have the file in question,
-     but I do not understand how I could fool it into getting an
-     error.  I think a later cvs get sys seemed to work so perhaps
-     something is amiss in handling multiple arguments to cvs get?
-
-119. When importing a directory tree that is under SCCS/RCS control,
-     consider an option to have import checkout the SCCS/RCS files if
-     necessary.  (This is if someone wants to import something which
-     is in RCS or SCCS without preserving the history, but makes sure
-     they do get the latest versions.  It isn't clear to me how useful
-     that is -kingdon, June 1996).
-
-122. If Name_Repository fails, it currently causes CVS to die completely.  It
-     should instead return NULL and have the caller do something reasonable
-     (???  -what is reasonable?  I'm not sure there is a real problem here.
-     -kingdon, June 1996).
-
-123. Add a flag to import to not build vendor branches for local code.
-     (See `importb' tests in src/sanity.sh for more details).
-
-124. Anyway, I thought you might want to add something like the following
-     to the cvs man pages:
-
-     BUGS
-       The sum of the sizes of a module key and its contents are
-       limited.  See ndbm(3).
-
-126. Do an analysis to see if CVS is forgetting to close file descriptors.
-     Especially when committing many files (more than the open file limit
-     for the particular UNIX).
-
-127. Look at *info files; they should all be quiet if the files are not
-     there.  Should be able to point at a RCS directory and go.
-
-130. cvs diff with no -r arguments does not need to look up the current RCS
-     version number since it only cares about what's in the Entries file.
-     This should make it much faster.
-
-     It should ParseEntries itself and access the entries list much like
-     Version_TS does (sticky tags and sticky options may need to be
-     supported here as well).  Then it should only diff the things that
-     have the wrong time stamp (the ones that look modified).
-
-134. Make a statement about using hard NFS mounts to your source
-     repository.  Look into checking NULL fgets() returns with ferror() to
-     see if an error had occurred.  (we should be checking for errors, quite
-     aside from NFS issues -kingdon, June 1996).
-
-137. Some sites might want CVS to fsync() the RCS ,v file to protect
-     against nasty hardware errors.  There is a slight performance hit with
-     doing so, though, so it should be configurable in the .cvsrc file.
-     Also, along with this, we should look at the places where CVS itself
-     could be a little more synchronous so as not to lose data.
-     [[ I've done some of this, but it could use much more ]]
-
-138. Some people have suggested that CVS use a VPATH-like environment
-     variable to limit the amount of sources that need to be duplicated for
-     sites with giant source trees and no disk space.
-
-141. Import should accept modules as its directory argument.  If we're
-     going to implement this, we should think hard about how modules
-     might be expanded and how to handle those cases.
-
-143. Update the documentation to show that the source repository is
-     something far away from the files that you work on.  (People who
-     come from an RCS background are used to their `repository' being
-     _very_ close to their working directory.)
-
-144. Have cvs checkout look for the environment variable CVSPREFIX
-     (or CVSMODPREFIX or some such).  If it's set, then when looking
-     up an alias in the modules database, first look it up with the
-     value of CVSPREFIX attached, and then look for the alias itself.
-     This would be useful when you have several projects in a single
-     repository.  You could have aliases abc_src and xyz_src and
-     tell people working on project abc to put "setenv CVSPREFIX abc_"
-     in their .cshrc file (or equivalent for other shells).
-     Then they could do "cvs co src" to get a copy of their src
-     directory, not xyz's.  (This should create a directory called
-     src, not abc_src.)
-
-145. After you create revision 1.1.1.1 in the previous scenario, if
-     you do "cvs update -r1 filename" you get revision 1.1, not
-     1.1.1.1.  It would be nice to get the later revision.  Again,
-     this restriction comes from RCS and is probably hard to
-     change in CVS.  Sigh.
-
-     |"cvs update -r1 filename" does not tell RCS to follow any branches.  CVS
-     |tries to be consistent with RCS in this fashion, so I would not change
-     |this.  Within CVS we do have the flexibility of extending things, like
-     |making a revision of the form "-r1HEAD" find the most recent revision
-     |(branch or not) with a "1." prefix in the RCS file.  This would get what
-     |you want maybe.
-      
-     This would be very useful.  Though I would prefer an option
-     such as "-v1" rather than "-r1HEAD".  This option might be
-     used quite often.
-
-146. The merging of files should be controlled via a hook so that programs
-     other than "rcsmerge" can be used, like Sun's filemerge or emacs's
-     emerge.el.  (but be careful in making this work client/server--it means
-     doing the interactive merging at the end after the server is done).
-     (probably best is to have CVS do the non-interactive part and
-     tell the user about where the files are (.#foo.c.working and
-     .#foo.c.1.5 or whatever), so they can do the interactive part at
-     that point -kingdon, June 1996).
-
-149. Maybe there should be an option to cvs admin that allows a user to
-     change the Repository/Root file with some degree of error checking?
-     Something like "cvs admin reposmv /old/path /new/pretty/path".  Before
-     it does the replace it check to see that the files
-     /new/pretty/path/<dir>/<files> exist.
-
-     The obvious cases are where one moves the repository to another
-     machine or directory.  But there are other cases, like where the
-     user might want to change from :pserver: to :ext:, use a different
-     server (if there are two server machines which share the
-     repository using a networked file system), etc.
-
-     The status quo is a bit of a mess (as of, say, CVS 1.9).  It is
-     that the -d global option has two moderately different uses.  One
-     is to use a totally different repository (in which case we'd
-     probably want to give an error if it disagreed with CVS/Root, as
-     CVS 1.8 and earlier did).  The other is the "reposmv"
-     functionality above (in which the two repositories really are the
-     same, and we want to update the CVS/Root files).  In CVS 1.9 and
-     1.10, -d rewrites the CVS/Root file (but not in subdirectories).
-     This behavior was not particularly popular and has been since
-     reverted.
-
-     This whole area is a rather bad pile of individual decisions which
-     accumulated over time, some of them probably bad decisions with
-     hindsight.  But we didn't get into this mess overnight, and we're
-     not going to get out of it overnight (that is, we need to come up
-     with a replacement behavior, document what parts of the status
-     quo are deprecated, probably circulate some unofficial patches, &c).
-
-     (this item originally added 2 Feb 1992 but revised since).
-
-150. I have a customer request for a way to specify log message per
-     file, non-interactively before the commit, such that a single, fully
-     recursive commit prompts for one commit message, and concatenates the
-     per file messages for each file.  In short, one commit, one editor
-     session, log messages allowed to vary across files within the commit.
-     Also, the per file messages should be allowed to be written when the
-     files are changed, which may predate the commit considerably.
-
-     A new command seems appropriate for this.  The state can be saved in the
-     CVS directory.  I.e.,
-
-        % cvs message foo.c
-        Enter log message for foo.c
-        >> fixed an uninitialized variable
-        >> ^D
-
-     The text is saved as CVS/foo.c,m (or some such name) and commit
-     is modified to append (prepend?) the text (if found) to the log
-     message specified at commit time.  Easy enough.  (having cvs
-     commit be non-interactive takes care of various issues like
-     whether to connect to the server before or after prompting for a
-     message (see comment in commit.c at call to start_server).  Also
-     would clean up the kludge for what to do with the message from
-     do_editor if the up-to-date check fails (see commit.c client code).
-
-     I'm not sure about the part above about having commit prompt
-     for an overall message--part of the point is having commit
-     non-interactive and somehow combining messages seems like (excess?)
-     hair.
-
-     Would be nice to do this so it allows users more flexibility in
-     specifying messages per-directory ("cvs message -l") or per-tree
-     ("cvs message") or per-file ("cvs message foo.c"), and fixes the
-     incompatibility between client/server (per-tree) and
-     non-client/server (per-directory).
-
-     A few interesting issues with this: (1) if you do a cvs update or
-     some other operation which changes the working directory, do you
-     need to run "cvs message" again (it would, of course, bring up
-     the old message which you could accept)?  Probably yes, after all
-     merging in some conflicts might change the situation.  (2) How do
-     you change the stored messages if you change your mind before the
-     commit (probably run "cvs message" again, as hinted in (1))?
-
-151. Also, is there a flag I am missing that allows replacing Ulrtx_Build
-     by Ultrix_build?  I.E. I would like a tag replacement to be a one step
-     operation rather than a two step "cvs rtag -r Ulrtx_Build Ultrix_Build"
-     followed by "cvs rtag -d Ulrtx_Build"
-
-152. The "cvs -n" option does not work as one would expect for all the
-     commands.  In particular, for "commit" and "import", where one would
-     also like to see what it would do, without actually doing anything.
-
-153. There should be some command (maybe I just haven't figured out
-     which one...) to import a source directory which is already
-     RCS-administered without losing all prior RCS gathered data.
-     Thus, it would have to examine the RCS files and choose a
-     starting version and branch higher than previous ones used.
-     (Check out rcs-to-cvs and see if it addresses this issue.)
-
-154. When committing the modules file, a pre-commit check should be done to
-     verify the validity of the new modules file before allowing it to be
-     committed.
-
-155. The options for "cvs history" are mutually exclusive, even though
-     useful queries can be done if they are not, as in specifying both
-     a module and a tag.  A workaround is to specify the module, then
-     run the output through grep to only display lines that begin with
-     T, which are tag lines.  (Better perhaps if we redesign the whole
-     "history" business -- check out doc/cvs.texinfo for the entire
-     rant.)
-
-156. Also, how hard would it be to allow continuation lines in the
-     {commit,rcs,log}info files? It would probably be useful with all of
-     the various flags that are now available, or if somebody has a lot of
-     files to put into a module.
-
-158. If I do a recursive commit and find that the same RCS file is checked
-     out (and modified!) in two different places within my checked-out
-     files (but within the realm of a single "commit"), CVS will commit the
-     first change, then overwrite that change with the second change.  We
-     should catch this (typically unusual) case and issue an appropriate
-     diagnostic and die.
-
-160. The checks that the commit command does should be extended to make
-     sure that the revision that we will lock is not already locked by
-     someone else.  Maybe it should also lock the new revision if the old
-     revision was already locked by the user as well, thus moving the lock
-     forward after the commit.
-
-163. The rtag/tag commands should have an option that removes the specified
-     tag from any file that is in the attic.  This allows one to re-use a
-     tag (like "Mon", "Tue", ...) all the time and still have it tag the
-     real main-line code.
-
-165. The "import" command will create RCS files automatically, but will
-     screw-up when trying to create long file names on short file name
-     file systems.  Perhaps import should be a bit more cautious.
-
-166. There really needs to be a "Getting Started" document which describes
-     some of the new CVS philosophies.  Folks coming straight from SCCS or
-     RCS might be confused by "cvs import".  Also need to explain:
-               - How one might setup their $CVSROOT
-               - What all the tags mean in an "import" command
-               - Tags are important; revision numbers are not
-
-170. Is there an "info" file that can be invoked when a file is checked out, or
-     updated ?  What I want to do is to advise users, particularly novices, of
-     the state of their working source whenever they check something out, as
-     a sanity check.
-     For example, I've written a perl script which tells you what branch you're
-     on, if any.  Hopefully this will help guard against mistaken checkins to
-     the trunk, or to the wrong branch.  I suppose I can do this in
-     "commitinfo", but it'd be nice to advise people before they edit their
-     files.
-  
-     It would also be nice if there was some sort of "verboseness" switch to
-     the checkout and update commands that could turn this invocation of the
-     script off, for mature users.
-
-173. Need generic date-on-branch handling.  Currently, many commands
-     allow both -r and -D, but that's problematic for commands like diff
-     that interpret that as two revisions rather than a single revision.
-     Checkout and update -j takes tag:date which is probably a better
-     solution overall.
-
-174. I would like to see "cvs release" modified so that it only removes files
-     which are known to CVS - all the files in the repository, plus those which
-     are listed in .cvsignore.  This way, if you do leave something valuable in
-     a source tree you can "cvs release -d" the tree and your non-CVS goodies
-     are still there.  If a user is going to leave non-CVS files in their source
-     trees, they really should have to clean them up by hand.
-
-175. And, in the feature request department, I'd dearly love a command-line
-     interface to adding a new module to the CVSROOT/modules file.
-
-176. If you use the -i flag in the modules file, you can control access
-     to source code; this is a Good Thing under certain circumstances. I
-     just had a nasty thought, and on experiment discovered that the
-     filter specified by -i is _not_ run before a cvs admin command; as
-     this allows a user to go behind cvs's back and delete information
-     (cvs admin -o1.4 file) this seems like a serious problem.
-
-177. We've got some external vendor source that sits under a source code
-     hierarchy, and when we do a cvs update, it gets wiped out because
-     its tag is different from the "main" distribution. I've tried to
-     use "-I" to ignore the directory, as well as .cvsignore, but this
-     doesn't work.
-
-179. "cvs admin" does not log its actions with loginfo, nor does it check
-     whether the action is allowed with commitinfo.  It should.
-
-182.  There should be a way to show log entries corresponding to
-changes from tag "foo" to tag "bar".  "cvs log -rfoo:bar" doesn't cut
-it, because it erroneously shows the changes associated with the
-change from the revision before foo to foo.  I'm not sure that is ever
-a useful or logical behavior ("cvs diff -r foo -r bar" gets this
-right), but is compatibility an issue?  See
-http://www.cyclic.com/cvs/unoff-log.txt for an unofficial patch.
-
-183.  "cvs status" should report on Entries.Static flag and CVS/Tag (how?
-maybe a "cvs status -d" to give directory status?).  There should also
-be more documentation of how these get set and how/when to re-set them.
-
-184.  Would be nice to implement the FreeBSD MD5-based password hash
-algorithm in pserver.  For more info see "6.1. DES, MD5, and Crypt" in
-the FreeBSD Handbook, and src/lib/libcrypt/crypt.c in the FreeBSD
-sources.  Certainly in the context of non-unix servers this algorithm
-makes more sense than the traditional unix crypt() algorithm, which
-suffers from export control problems.
-
-185.  A frequent complaint is that keyword expansion causes conflicts
-when merging from one branch to another.  The first step is
-documenting CVS's existing features in this area--what happens with
-various -k options in various places?  The second step is thinking
-about whether there should be some new feature and if so how it should
-be designed.  For example, here is one thought:
-
-    rcs' co command needs a new -k option.  The new option should expand
-    $Log entries without expanding $Revision entries.  This would
-    allow cvs to use rcsmerge in such a way that joining branches into
-    main lines would neither generate extra collisions on revisions nor
-    drop log lines.
-
-The details of this are out of date (CVS no longer invokes "co", and
-any changes in this area would be done by bypassing RCS rather than
-modifying it), but even as to the general idea, I don't have a clear
-idea about whether it would be good (see what I mean about the need
-for better documentation?  I work on CVS full-time, and even I don't
-understand the state of the art on this subject).
-
-186.  There is a frequent discussion of multisite features.
-
-* There may be some overlap with the client/server CVS, which is good
-especially when there is a single developer at each location.  But by
-"multisite" I mean something in which each site is more autonomous, to
-one extent or another.
-
-* Vendor branches are the closest thing that CVS currently has for
-multisite features.  They have fixable drawbacks (such as poor
-handling of added and removed files), and more fundamental drawbacks
-(when you import a vendor branch, you are importing a set of files,
-not importing any knowledge of their version history outside the
-current repository).
-
-* One approach would be to require checkins (or other modifications to
-the repository) to succeed at a write quorum of sites (51%) before
-they are allowed to complete.  To work well, the network should be
-reliable enough that one can typically get to that many sites.  When a
-server which has been out of touch reconnects, it would want to update
-its data before doing anything else.  Any of the servers can service
-all requests locally, except perhaps for a check that they are
-up-to-date.  The way this differs from a run-of-the-mill distributed
-database is that if one only allows reversible operations via this
-mechanism (exclude "cvs admin -o", "cvs tag -d", &c), then each site
-can back up the others, such that failures at one site, including
-something like deleting all the sources, can be recovered from.  Thus
-the sites need not trust each other as much as for many shared
-databases, and the system may be resilient to many types of
-organizational failures.  Sometimes I call this design the
-"CVScluster" design.
-
-* Another approach is a master/slave one.  Checkins happen at the
-master site, and slave sites need to check whether their local
-repository is up to date before relying on its information.
-
-* Another approach is to have each site own a particular branch.  This
-one is the most tolerant of flaky networks; if checkins happen at each
-site independently there is no particular problem.  The big question
-is whether merges happen only manually, as with existing CVS branches,
-or whether there is a feature whereby there are circumstances in which
-merges from one branch to the other happen automatically (for example,
-the case in which the branches have not diverged).  This might be a
-legitimate question to ask even quite aside from multisite features.
-
-187.  Might want to separate out usage error messages and help
-messages.  The problem now is that if you specify an invalid option,
-for example, the error message is lost among all the help text.  In
-the new regime, the error message would be followed by a one-line
-message directing people to the appropriate help option ("cvs -H
-<command>" or "cvs --help-commands" or whatever, according to the
-situation).  I'm not sure whether this change would be controversial
-(as defined in HACKING), so there might be a need for further
-discussion or other actions other than just coding.
-
-188.  Option parsing and .cvsrc has at least one notable limitation.
-If you want to set a global option only for some CVS commands, there
-is no way to do it (for example, if one wants to set -q only for
-"rdiff").  I am told that the "popt" package from RPM
-(http://www.rpm.org) could solve this and other problems (for example,
-if the syntax of option stuff in .cvsrc is similar to RPM, that would
-be great from a user point of view).  It would at least be worth a
-look (it also provides a cleaner API than getopt_long).
-
-Another issue which may or may not be related is the issue of
-overriding .cvsrc from the command line.  The cleanest solution might
-be to have options in mutually exclusive sets (-l/-R being a current
-example, but --foo/--no-foo is a better way to name such options).  Or
-perhaps there is some better solution.
-
-189.  Renaming files and directories is a frequently discussed topic.
-
-Some of the problems with the status quo:
-
-a.  "cvs annotate" cannot operate on both the old and new files in a
-single run.  You need to run it twice, once for the new name and once
-for the old name.
-
-b.  "cvs diff" (or "cvs diff -N") shows a rename as a removal of the
-old file and an addition of the new one.  Some people would like to
-see the differences between the file contents (but then how would we
-indicate the fact that the file has been renamed?  Certainly the
-notion that "patch(1)" has of renames is as a removal and addition).
-
-c.  "cvs log" should be able to show the changes between two
-tags/dates, even in the presence of adds/removes/renames (I'm not sure
-what the status quo is on this; see also item #182).
-
-d.  Renaming directories is way too hard.
-
-Implementations:
-
-It is perhaps premature to try to design implementation details
-without answering some of the above questions about desired behaviors
-but several general implementations get mentioned.
-
-i.  No fundamental changes (for example, a "cvs rename" command which
-operated on directories could still implement the current recommended
-practice for renaming directories, which is to rename each of the
-files contained therein via an add and a remove).  One thing to note
-that the status quo gets right is proper merges, even with adds and
-removals (Well, mostly right at least.  There are a *LOT* of different
-cases; see the testsuite for some of them).
-
-ii.  Rename database.  In this scheme the files in the repository
-would have some arbitrary name, and then a separate rename database
-would indicate the current correspondence between the filename in the
-working directory and the actual storage.  As far as I know this has
-never been designed in detail for CVS.
-
-iii.  A modest change in which the RCS files would contain some
-information such as "renamed from X" or "renamed to Y".  That is, this
-would be generally similar to the log messages which are suggested
-when one renames via an add and a removal, but would be
-computer-parseable.  I don't think anyone has tried to flesh out any
-details here either.
-
-It is interesting to note that in solution ii. version numbers in the
-"new file" start where the "old file" left off, while in solutions
-i. and iii., version numbers restart from 1.1 each time a file is
-renamed.  Except perhaps in the case where we rename a file from foo
-to bar and then back to foo.  I'll shut up now.
-
-Regardless of the method we choose, we need to address how renames
-affect existing CVS behaviors.  For example, what happens when you
-rename a file on a branch but not the trunk and then try to merge the
-two?  What happens when you rename a file on one branch and delete it
-on another and try to merge the two?
-
-Ideally, we'd come up with a way to parameterize the problem and
-simply write up a lookup table to determine the correct behavior.
-
-190.  The meaning of the -q and -Q global options is very ad hoc;
-there is no clear definition of which messages are suppressed by them
-and which are not.  Here is a classification of the current meanings
-of -q; I don't know whether anyone has done a similar investigation of
--Q:
-
-  a.  The "warm fuzzies" printed upon entering each directory (for
-  example, "cvs update: Updating sdir").  The need for these messages
-  may be decreased now that most of CVS uses ->fullname instead of
-  ->file in messages (a project which is *still* not 100% complete,
-  alas).  However, the issue of whether CVS can offer status as it
-  runs is an important one.  Of course from the command line it is
-  hard to do this well and one ends up with options like -q.  But
-  think about emacs, jCVS, or other environments which could flash you
-  the latest status line so you can see whether the system is working
-  or stuck.
-
-  b.  Other cases where the message just offers information (rather
-  than an error) and might be considered unnecessarily verbose.  These
-  have a certain point to them, although it isn't really clear whether
-  it should be the same option as the warm fuzzies or whether it is
-  worth the conceptual hair:
-
-    add.c: scheduling %s `%s' for addition (may be an issue)
-    modules.c: %s %s: Executing '%s' (I can see how that might be noise,
-      but...)
-    remove.c: scheduling `%s' for removal (analogous to the add.c one)
-    update.c: Checking out %s (hmm, that message is a bit on the noisy side...)
-      (but the similar message in annotate is not affected by -q).
-
-  c.  Suppressing various error messages.  This is almost surely
-  bogus.
-
-    commit.c: failed to remove tag `%s' from `%s' (Questionable.
-      Rationale might be that we already printed another message
-      elsewhere but why would it be necessary to avoid
-      the extra message in such an uncommon case?)
-    commit.c: failed to commit dead revision for `%s' (likewise)
-    remove.c: file `%s' still in working directory (see below about rm
-      -f analogy)
-    remove.c: nothing known about `%s' (looks dubious to me, especially in
-      the case where the user specified it explicitly).
-    remove.c: removed `%s' (seems like an obscure enough case that I fail
-      to see the appeal of being cryptically concise here).
-    remove.c: file `%s' already scheduled for removal (now it is starting
-      to look analogous to the infamous rm -f option).
-    rtag.c: cannot find tag `%s' in `%s' (more rm -f like behavior)
-    rtag.c: failed to remove tag `%s' from `%s' (ditto)
-    tag.c: failed to remove tag %s from %s (see above about whether RCS_*
-      has already printed an error message).
-    tag.c: couldn't tag added but un-commited file `%s' (more rm -f
-      like behavior)
-    tag.c: skipping removed but un-commited file `%s' (ditto)
-    tag.c: cannot find revision control file for `%s' (ditto, but at first
-      glance seems even worse, as this would seem to be a "can't happen"
-      condition)
-
-191.  Storing RCS files, especially binary files, takes rather more
-space than it could, typically.
-  - The virtue of the status quo is that it is simple to implement.
-    Of course it is also simplest in terms of dealing with compatibility.
-  - Just storing the revisions as separate gzipped files is a common 
-    technique.  It also is pretty simple (no new algorithms, CVS
-    already has zlib around).  Of course for some files (such as files
-    which are already compressed) the gzip step won't help, but
-    something which can at least sometimes avoid rewriting the entire
-    RCS file for each new revision would, I would think, be a big
-    speedup for large files.
-  - Josh MacDonald has written a tool called xdelta which produces
-    differences (that is, sufficient information to transform the old
-    to the new) which looks for common sequences of bytes, like RCS
-    currently does, but which is not based on lines.  This seems to do
-    quite well for some kinds of files (e.g. FrameMaker documents,
-    text files), and not as well for others (anything which is already
-    compressed, executables).  xdelta 1.10 also is faster than GNU diff.
-  - Karl Fogel has thought some about using a difference technique
-    analogous to fractal compression (see the comp.compression FAQ for
-    more on fractal compression, including at least one patent to
-    watch for; I don't know how analogous Karl's ideas are to the
-    techniques described there).
-  - Quite possibly want some documented interface by which a site can
-    plug in their choice of external difference programs (with the
-    ability to choose the program based on filename, magic numbers,
-    or some such).
-
-192.  "cvs update" using an absolute pathname does not work if the
-working directory is not a CVS-controlled directory with the correct
-CVSROOT.  For example, the following will fail:
-
-  cd /tmp
-  cvs -d /repos co foo
-  cd /
-  cvs update /tmp/foo
-
-It is possible to read the CVSROOT from the administrative files in
-the directory specified by the absolute pathname argument to update.
-In that case, the last command above would be equivalent to:
-
-  cd /tmp/foo
-  cvs update .
-
-This can be problematic, however, if we ask CVS to update two
-directories with different CVSROOTs.  Currently, CVS has no way of
-changing CVSROOT mid-stream.  Consider the following:
-
-  cd /tmp
-  cvs -d /repos1 co foo
-  cvs -d /repos2 co bar
-  cd /
-  cvs update /tmp/foo /tmp/bar
-
-To make that example work, we need to think hard about:
-
-  - where and when CVSROOT-related variables get set
-  - who caches said variables for later use
-  - how the remote protocol should be extended to handle sending a new
-    repository mid-stream
-  - how the client should maintain connections to a variety of servers
-    in a single invocation.
-
-Because those issues are hairy, I suspect that having a change in
-CVSROOT be an error would be a better move.
-
-193.  The client relies on timestamps to figure out whether a file is
-(maybe) modified.  If something goes awry, then it ends up sending
-entire files to the server to be checked, and this can be quite slow
-especially over a slow network.  A couple of things that can happen:
-(a) other programs, like make, use timestamps, so one ends up needing
-to do "touch foo" and otherwise messing with timestamps, (b) changing
-the timezone offset (e.g. summer vs. winter or moving a machine)
-should work on unix, but there may be problems with non-unix.
-
-Possible solutions:
-
-   a.  Store a checksum for each file in CVS/Entries or some such
-   place.  What to do about hash collisions is interesting: using a
-   checksum, like MD5, large enough to "never" have collisions
-   probably works in practice (of course, if there is a collision then
-   all hell breaks loose because that code path was not tested, but
-   given the tiny, tiny probability of that I suppose this is only an
-   aesthetic issue).
-
-   b.  I'm not thinking of others, except storing the whole file in
-   CVS/Base, and I'm sure using twice the disk space would be
-   unpopular.
-
-194.  CVS does not separate the "metadata" from the actual revision
-history; it stores them both in the RCS files.  Metadata means tags
-and header information such as the number of the head revision.
-Storing the metadata separately could speed up "cvs tag" enormously,
-which is a big problem for large repositories.  It could also probably
-make CVS's locking much less in the way (see comment in do_recursion
-about "two-pass design").
-
-195.  Many people using CVS over a slow link are interested in whether
-the remote protocol could be any more efficient with network
-bandwidth.  This item is about one aspect of that--how the server
-sends a new version of a file the client has a different version of,
-or vice versa.
-
-a.  Cases in which the status quo already sends a diff.  For most text
-files, this is probably already close to optimal.  For binary files,
-and anomalous (?) text files (e.g. those in which it would help to do
-moves, as well as adds and deletes), it might be worth looking into other
-difference algorithms (see item #191).
-
-b.  Cases in which the status quo does not send a diff (e.g. "cvs
-commit").
-
-b1.  With some frequency, people suggest rsync or a similar algorithm
-(see ftp://samba.anu.edu.au/pub/rsync/).  This could speed things up,
-and in some ways involves the most minimal changes to the default CVS
-paradigm.  There are some downsides though: (1) there is an extra
-network turnaround, (2) the algorithm needs to transmit some data to
-discover what difference type programs can discover locally (although
-this is only about 1% of the size of the files).
-
-b2.  If one is willing to require that users use "cvs edit" before
-editing a file on the client side (in some cases, a development
-environment like emacs can make this fairly easy), then the Modified
-request in the protocol could be extended to allow the client to just
-send differences instead of entire files.  In the degenerate case
-(e.g. "cvs diff" without arguments) the required network traffic is
-reduced to zero, and the client need not even contact the server.
-
-197.  Analyze the difference between CVS_UNLINK & unlink_file.  As far as I
-can tell, unlink_file aborts in noexec mode and CVS_UNLINK does not.  I'm not
-sure it would be possible to remove even the use of temp files in noexec mode,
-but most unlinks should probably be using unlink_file and not CVS_UNLINK.
-
-198.  Remove references to deprecated cvs_temp_name function.
-
-199.  Add test for login & logout functionality, including support for
-backwards compatibility with old CVSROOTs.
-
-200.  Make a 'cvs add' without write access a non-fatal error so that
-the user's Entries file is updated and future 'cvs diffs' will work
-properly.  This should ease patch submission.
-
-201.  cvs_temp_file should be creating temporary files in a privately owned
-subdirectory of of temp due to security issues on some systems.
-
-202.  Enable rdiff to accept most diff options.  Make rdiff output look
-like diff's.  Make CVS diff garbage go to stderr and only standard diff
-output go to stdout.
-
-203.  Add val-tags additions to the tagging code.  Don't remove the
-update additions since val-tags could still be used as a cache when the
-repository was imported from elsewhere (the tags weren't applied with a
-version which wrote val-tags).
-
-204.  Add test case for compression.  A buf_shutdown error using compression
-wasn't caught by the test suite.
-
-205.  There are lots of cases where trailing slashes on directory names
-and other non-canonical paths confuse CVS.  Most of the cases that do
-work are handled on an ad-hoc basis.  We need to come up with a coherent
-strategy to address path canonicalization and apply it consistently.
-
-208.  Merge enhancements to the diff package back into the original GNU source.
-
-209.  Go through this file and try to:
-
-  a.  Verify that items are still valid.
-
-  b.  Create test cases for valid items when they don't exist.
-
-  c.  Remove fixed and no longer applicable items.
-
-210.  Explain to sanity.sh how to deal with paths with spaces and other odd
-characters in them.
-
-211.  Make sanity.sh run under the Win32 bash (cygwin) and maybe other Windex
-environments (e.g. DGSS or whatever the MSVC portability environemnt is called).
-
-212.  Autotestify (see autoconf source) sanity.sh.
-
-213.  Examine desirability of updating the regex library (regex.{c,h}) to the
-more recent versions that come with glibc and emacs.  It might be worth waiting
-for the emacs folks to get their act together and merge their changes into the
-glibc version.
-
-215.  Add reditors and rwatchers commands.
-
-       - Is an r* command abstraction layer possible here for the commands
-         where this makes sense?  Would it be simpler?  It seems to me the
-         major operational differences lie in the file list construction.
-
-218.  Fix "checkout -d ." in client/server mode.
-
-221.  Handle spaces in file/directory names.  (Most, if not all, of the
-internal infrastructure already handles them correctly, but most of the
-administrative file interfaces do not.)
-
-223.  Internationalization support.  This probably means using some kind
-of universal character set (ISO 10646?) internally and converting on
-input and output, which opens the locale can of worms.
-
-225.  Add support for --allow-root to server command.
-
-227.  'cvs release' should use the CVS/Root in the directory being released
-when such is specified rather than $CVSROOT.  In my work directory with no CVS
-dir, a release of subdirectories causes the released projects to be tested
-against my $CVSROOT environment variable, which often isn't correct but which
-can complete without generating error messages if the project also exists in
-the other CVSROOT.  This happens a lot with my copies of the ccvs project.
-
-228.  Consider adding -d to commit ala ci.
-
-229.  Improve the locking code to use a random delay with exponential
-backoff ala Ethernet and separate the notification interval from the
-wait interval.
-
-230.  Support for options like compression as part of the CVSROOT might be
-nice.  This should be fairly easy to implement now using the method options.
-
-231.  The `cvs watch off' command needs an extension which enables users in the
-cvsadmin group to turn watch off for users whose logins and email address may
-not exist anymore.
-
-232. Use file descriptor operations exclusively for I/O (not STDIO).
-
-233.  The ls-D-2 test fails when run in the hour transition between daylight
-savings time and standard time.  This probably has something to do with the
-two 1AM to 2AM time slots that occur over that two hour period (one such
-failure was on the morning of October 31st, 2004).
-
-234.  Noop commands should be logged in the history file.  Information can
-still be obtained with noop commands, for instance via `cvs -n up -p', and
-paranoid admins might appreciate this.  Similarly, perhaps diff operations
-should be logged.
diff --git a/contrib/cvs-1.12/lib/regcomp.c b/contrib/cvs-1.12/lib/regcomp.c
new file mode 100644 (file)
index 0000000..279b20c
--- /dev/null
@@ -0,0 +1,3779 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
+                                         Idx length, reg_syntax_t syntax);
+static void re_compile_fastmap_iter (regex_t *bufp,
+                                    const re_dfastate_t *init_state,
+                                    char *fastmap);
+static reg_errcode_t init_dfa (re_dfa_t *dfa, Idx pat_len);
+#ifdef RE_ENABLE_I18N
+static void free_charset (re_charset_t *cset);
+#endif /* RE_ENABLE_I18N */
+static void free_workarea_compile (regex_t *preg);
+static reg_errcode_t create_initial_state (re_dfa_t *dfa);
+#ifdef RE_ENABLE_I18N
+static void optimize_utf8 (re_dfa_t *dfa);
+#endif
+static reg_errcode_t analyze (regex_t *preg);
+static reg_errcode_t preorder (bin_tree_t *root,
+                              reg_errcode_t (fn (void *, bin_tree_t *)),
+                              void *extra);
+static reg_errcode_t postorder (bin_tree_t *root,
+                               reg_errcode_t (fn (void *, bin_tree_t *)),
+                               void *extra);
+static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
+static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
+static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
+                                bin_tree_t *node);
+static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
+static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
+static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
+static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint);
+static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
+                                  unsigned int constraint);
+static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
+static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
+                                        Idx node, bool root);
+static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
+static Idx fetch_number (re_string_t *input, re_token_t *token,
+                        reg_syntax_t syntax);
+static int peek_token (re_token_t *token, re_string_t *input,
+                       reg_syntax_t syntax);
+static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
+                         reg_syntax_t syntax, reg_errcode_t *err);
+static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
+                                 re_token_t *token, reg_syntax_t syntax,
+                                 Idx nest, reg_errcode_t *err);
+static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
+                                re_token_t *token, reg_syntax_t syntax,
+                                Idx nest, reg_errcode_t *err);
+static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
+                                    re_token_t *token, reg_syntax_t syntax,
+                                    Idx nest, reg_errcode_t *err);
+static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
+                                 re_token_t *token, reg_syntax_t syntax,
+                                 Idx nest, reg_errcode_t *err);
+static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
+                                re_dfa_t *dfa, re_token_t *token,
+                                reg_syntax_t syntax, reg_errcode_t *err);
+static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
+                                     re_token_t *token, reg_syntax_t syntax,
+                                     reg_errcode_t *err);
+static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
+                                           re_string_t *regexp,
+                                           re_token_t *token, int token_len,
+                                           re_dfa_t *dfa,
+                                           reg_syntax_t syntax,
+                                           bool accept_hyphen);
+static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
+                                         re_string_t *regexp,
+                                         re_token_t *token);
+#ifdef RE_ENABLE_I18N
+static reg_errcode_t build_equiv_class (bitset sbcset,
+                                       re_charset_t *mbcset,
+                                       Idx *equiv_class_alloc,
+                                       const unsigned char *name);
+static reg_errcode_t build_charclass (unsigned REG_TRANSLATE_TYPE trans,
+                                     bitset sbcset,
+                                     re_charset_t *mbcset,
+                                     Idx *char_class_alloc,
+                                     const unsigned char *class_name,
+                                     reg_syntax_t syntax);
+#else  /* not RE_ENABLE_I18N */
+static reg_errcode_t build_equiv_class (bitset sbcset,
+                                       const unsigned char *name);
+static reg_errcode_t build_charclass (unsigned REG_TRANSLATE_TYPE trans,
+                                     bitset sbcset,
+                                     const unsigned char *class_name,
+                                     reg_syntax_t syntax);
+#endif /* not RE_ENABLE_I18N */
+static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
+                                      unsigned REG_TRANSLATE_TYPE trans,
+                                      const unsigned char *class_name,
+                                      const unsigned char *extra,
+                                      bool non_match, reg_errcode_t *err);
+static bin_tree_t *create_tree (re_dfa_t *dfa,
+                               bin_tree_t *left, bin_tree_t *right,
+                               re_token_type_t type);
+static bin_tree_t *create_token_tree (re_dfa_t *dfa,
+                                     bin_tree_t *left, bin_tree_t *right,
+                                     const re_token_t *token);
+static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
+static void free_token (re_token_t *node);
+static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
+static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
+\f
+/* This table gives an error message for each of the error codes listed
+   in regex.h.  Obviously the order here has to be same as there.
+   POSIX doesn't require that we do anything for REG_NOERROR,
+   but why not be nice?  */
+
+const char __re_error_msgid[] attribute_hidden =
+  {
+#define REG_NOERROR_IDX        0
+    gettext_noop ("Success")   /* REG_NOERROR */
+    "\0"
+#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
+    gettext_noop ("No match")  /* REG_NOMATCH */
+    "\0"
+#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match")
+    gettext_noop ("Invalid regular expression") /* REG_BADPAT */
+    "\0"
+#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
+    gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
+    "\0"
+#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character")
+    gettext_noop ("Invalid character class name") /* REG_ECTYPE */
+    "\0"
+#define REG_EESCAPE_IDX        (REG_ECTYPE_IDX + sizeof "Invalid character class name")
+    gettext_noop ("Trailing backslash") /* REG_EESCAPE */
+    "\0"
+#define REG_ESUBREG_IDX        (REG_EESCAPE_IDX + sizeof "Trailing backslash")
+    gettext_noop ("Invalid back reference") /* REG_ESUBREG */
+    "\0"
+#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference")
+    gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */
+    "\0"
+#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
+    gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
+    "\0"
+#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
+    gettext_noop ("Unmatched \\{") /* REG_EBRACE */
+    "\0"
+#define REG_BADBR_IDX  (REG_EBRACE_IDX + sizeof "Unmatched \\{")
+    gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
+    "\0"
+#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
+    gettext_noop ("Invalid range end") /* REG_ERANGE */
+    "\0"
+#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end")
+    gettext_noop ("Memory exhausted") /* REG_ESPACE */
+    "\0"
+#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted")
+    gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
+    "\0"
+#define REG_EEND_IDX   (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
+    gettext_noop ("Premature end of regular expression") /* REG_EEND */
+    "\0"
+#define REG_ESIZE_IDX  (REG_EEND_IDX + sizeof "Premature end of regular expression")
+    gettext_noop ("Regular expression too big") /* REG_ESIZE */
+    "\0"
+#define REG_ERPAREN_IDX        (REG_ESIZE_IDX + sizeof "Regular expression too big")
+    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
+  };
+
+const size_t __re_error_msgid_idx[] attribute_hidden =
+  {
+    REG_NOERROR_IDX,
+    REG_NOMATCH_IDX,
+    REG_BADPAT_IDX,
+    REG_ECOLLATE_IDX,
+    REG_ECTYPE_IDX,
+    REG_EESCAPE_IDX,
+    REG_ESUBREG_IDX,
+    REG_EBRACK_IDX,
+    REG_EPAREN_IDX,
+    REG_EBRACE_IDX,
+    REG_BADBR_IDX,
+    REG_ERANGE_IDX,
+    REG_ESPACE_IDX,
+    REG_BADRPT_IDX,
+    REG_EEND_IDX,
+    REG_ESIZE_IDX,
+    REG_ERPAREN_IDX
+  };
+\f
+/* Entry points for GNU code.  */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+   compiles PATTERN (of length LENGTH) and puts the result in BUFP.
+   Returns 0 if the pattern was valid, otherwise an error string.
+
+   Assumes the `re_allocated' (and perhaps `re_buffer') and `translate' fields
+   are set in BUFP on entry.  */
+
+const char *
+re_compile_pattern (const char *pattern, size_t length,
+                   struct re_pattern_buffer *bufp)
+{
+  reg_errcode_t ret;
+
+  /* And GNU code determines whether or not to get register information
+     by passing null for the REGS argument to re_match, etc., not by
+     setting re_no_sub, unless REG_NO_SUB is set.  */
+  bufp->re_no_sub = !!(re_syntax_options & REG_NO_SUB);
+
+  /* Match anchors at newline.  */
+  bufp->re_newline_anchor = 1;
+
+  ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
+
+  if (!ret)
+    return NULL;
+  return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
+}
+#ifdef _LIBC
+weak_alias (__re_compile_pattern, re_compile_pattern)
+#endif
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
+   also be assigned to arbitrarily: each pattern buffer stores its own
+   syntax, so it can be changed between regex compilations.  */
+/* This has no initializer because initialized variables in Emacs
+   become read-only after dumping.  */
+reg_syntax_t re_syntax_options;
+
+
+/* Specify the precise syntax of regexps for compilation.  This provides
+   for compatibility for various utilities which historically have
+   different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit mask comprised of the various bits
+   defined in regex.h.  We return the old syntax.  */
+
+reg_syntax_t
+re_set_syntax (reg_syntax_t syntax)
+{
+  reg_syntax_t ret = re_syntax_options;
+
+  re_syntax_options = syntax;
+  return ret;
+}
+#ifdef _LIBC
+weak_alias (__re_set_syntax, re_set_syntax)
+#endif
+
+int
+re_compile_fastmap (struct re_pattern_buffer *bufp)
+{
+  re_dfa_t *dfa = (re_dfa_t *) bufp->re_buffer;
+  char *fastmap = bufp->re_fastmap;
+
+  memset (fastmap, '\0', sizeof (char) * SBC_MAX);
+  re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
+  if (dfa->init_state != dfa->init_state_word)
+    re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
+  if (dfa->init_state != dfa->init_state_nl)
+    re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
+  if (dfa->init_state != dfa->init_state_begbuf)
+    re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
+  bufp->re_fastmap_accurate = 1;
+  return 0;
+}
+#ifdef _LIBC
+weak_alias (__re_compile_fastmap, re_compile_fastmap)
+#endif
+
+static inline void
+__attribute ((always_inline))
+re_set_fastmap (char *fastmap, bool icase, int ch)
+{
+  fastmap[ch] = 1;
+  if (icase)
+    fastmap[tolower (ch)] = 1;
+}
+
+/* Helper function for re_compile_fastmap.
+   Compile fastmap for the initial_state INIT_STATE.  */
+
+static void
+re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
+                        char *fastmap)
+{
+  re_dfa_t *dfa = (re_dfa_t *) bufp->re_buffer;
+  Idx node_cnt;
+  bool icase = (dfa->mb_cur_max == 1 && (bufp->re_syntax & REG_IGNORE_CASE));
+  for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
+    {
+      Idx node = init_state->nodes.elems[node_cnt];
+      re_token_type_t type = dfa->nodes[node].type;
+
+      if (type == CHARACTER)
+       {
+         re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
+#ifdef RE_ENABLE_I18N
+         if ((bufp->re_syntax & REG_IGNORE_CASE) && dfa->mb_cur_max > 1)
+           {
+             unsigned char buf[MB_LEN_MAX];
+             unsigned char *p;
+             wchar_t wc;
+             mbstate_t state;
+
+             p = buf;
+             *p++ = dfa->nodes[node].opr.c;
+             while (++node < dfa->nodes_len
+                    && dfa->nodes[node].type == CHARACTER
+                    && dfa->nodes[node].mb_partial)
+               *p++ = dfa->nodes[node].opr.c;
+             memset (&state, 0, sizeof (state));
+             if (mbrtowc (&wc, (const char *) buf, p - buf,
+                          &state) == p - buf
+                 && (__wcrtomb ((char *) buf, towlower (wc), &state)
+                     != (size_t) -1))
+               re_set_fastmap (fastmap, false, buf[0]);
+           }
+#endif
+       }
+      else if (type == SIMPLE_BRACKET)
+       {
+         int i, j, ch;
+         for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+           for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+             if (dfa->nodes[node].opr.sbcset[i] & ((bitset_word) 1 << j))
+               re_set_fastmap (fastmap, icase, ch);
+       }
+#ifdef RE_ENABLE_I18N
+      else if (type == COMPLEX_BRACKET)
+       {
+         Idx i;
+         re_charset_t *cset = dfa->nodes[node].opr.mbcset;
+         if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes
+             || cset->nranges || cset->nchar_classes)
+           {
+# ifdef _LIBC
+             if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)
+               {
+                 /* In this case we want to catch the bytes which are
+                    the first byte of any collation elements.
+                    e.g. In da_DK, we want to catch 'a' since "aa"
+                         is a valid collation element, and don't catch
+                         'b' since 'b' is the only collation element
+                         which starts from 'b'.  */
+                 const int32_t *table = (const int32_t *)
+                   _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+                 for (i = 0; i < SBC_MAX; ++i)
+                   if (table[i] < 0)
+                     re_set_fastmap (fastmap, icase, i);
+               }
+# else
+             if (dfa->mb_cur_max > 1)
+               for (i = 0; i < SBC_MAX; ++i)
+                 if (__btowc (i) == WEOF)
+                   re_set_fastmap (fastmap, icase, i);
+# endif /* not _LIBC */
+           }
+         for (i = 0; i < cset->nmbchars; ++i)
+           {
+             char buf[256];
+             mbstate_t state;
+             memset (&state, '\0', sizeof (state));
+             if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
+               re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
+             if ((bufp->re_syntax & REG_IGNORE_CASE) && dfa->mb_cur_max > 1)
+               {
+                 if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
+                     != (size_t) -1)
+                   re_set_fastmap (fastmap, false, *(unsigned char *) buf);
+               }
+           }
+       }
+#endif /* RE_ENABLE_I18N */
+      else if (type == OP_PERIOD
+#ifdef RE_ENABLE_I18N
+              || type == OP_UTF8_PERIOD
+#endif /* RE_ENABLE_I18N */
+              || type == END_OF_RE)
+       {
+         memset (fastmap, '\1', sizeof (char) * SBC_MAX);
+         if (type == END_OF_RE)
+           bufp->re_can_be_null = 1;
+         return;
+       }
+    }
+}
+\f
+/* Entry point for POSIX code.  */
+/* regcomp takes a regular expression as a string and compiles it.
+
+   PREG is a regex_t *.  We do not expect any fields to be initialized,
+   since POSIX says we shouldn't.  Thus, we set
+
+     `re_buffer' to the compiled pattern;
+     `re_used' to the length of the compiled pattern;
+     `re_syntax' to REG_SYNTAX_POSIX_EXTENDED if the
+       REG_EXTENDED bit in CFLAGS is set; otherwise, to
+       REG_SYNTAX_POSIX_BASIC;
+     `re_newline_anchor' to REG_NEWLINE being set in CFLAGS;
+     `re_fastmap' to an allocated space for the fastmap;
+     `re_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 (regex_t *__restrict preg, const char *__restrict pattern, int cflags)
+{
+  reg_errcode_t ret;
+  reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? REG_SYNTAX_POSIX_EXTENDED
+                       : REG_SYNTAX_POSIX_BASIC);
+
+  preg->re_buffer = NULL;
+  preg->re_allocated = 0;
+  preg->re_used = 0;
+
+  /* Try to allocate space for the fastmap.  */
+  preg->re_fastmap = re_malloc (char, SBC_MAX);
+  if (BE (preg->re_fastmap == NULL, 0))
+    return REG_ESPACE;
+
+  syntax |= (cflags & REG_ICASE) ? REG_IGNORE_CASE : 0;
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (cflags & REG_NEWLINE)
+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~REG_DOT_NEWLINE;
+      syntax |= REG_HAT_LISTS_NOT_NEWLINE;
+      /* It also changes the matching behavior.  */
+      preg->re_newline_anchor = 1;
+    }
+  else
+    preg->re_newline_anchor = 0;
+  preg->re_no_sub = !!(cflags & REG_NOSUB);
+  preg->re_translate = NULL;
+
+  ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
+
+  /* POSIX doesn't distinguish between an unmatched open-group and an
+     unmatched close-group: both are REG_EPAREN.  */
+  if (ret == REG_ERPAREN)
+    ret = REG_EPAREN;
+
+  /* We have already checked preg->re_fastmap != NULL.  */
+  if (BE (ret == REG_NOERROR, 1))
+    /* Compute the fastmap now, since regexec cannot modify the pattern
+       buffer.  This function never fails in this implementation.  */
+    (void) re_compile_fastmap (preg);
+  else
+    {
+      /* Some error occurred while compiling the expression.  */
+      re_free (preg->re_fastmap);
+      preg->re_fastmap = NULL;
+    }
+
+  return (int) ret;
+}
+#ifdef _LIBC
+weak_alias (__regcomp, regcomp)
+#endif
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   We don't use PREG here.  */
+
+size_t
+regerror (int errcode, const regex_t *__restrict preg,
+         char *__restrict errbuf, size_t errbuf_size)
+{
+  const char *msg;
+  size_t msg_size;
+
+  if (BE (errcode < 0
+         || errcode >= (int) (sizeof (__re_error_msgid_idx)
+                              / sizeof (__re_error_msgid_idx[0])), 0))
+    /* Only error codes returned by the rest of the code should be passed
+       to this routine.  If we are given anything else, or if other regex
+       code generates an invalid error code, then the program has a bug.
+       Dump core so we can fix it.  */
+    abort ();
+
+  msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
+
+  msg_size = strlen (msg) + 1; /* Includes the null.  */
+
+  if (BE (errbuf_size != 0, 1))
+    {
+      if (BE (msg_size > errbuf_size, 0))
+       {
+#if defined HAVE_MEMPCPY || defined _LIBC
+         *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
+#else
+         memcpy (errbuf, msg, errbuf_size - 1);
+         errbuf[errbuf_size - 1] = 0;
+#endif
+       }
+      else
+       memcpy (errbuf, msg, msg_size);
+    }
+
+  return msg_size;
+}
+#ifdef _LIBC
+weak_alias (__regerror, regerror)
+#endif
+
+
+#ifdef RE_ENABLE_I18N
+/* This static array is used for the map to single-byte characters when
+   UTF-8 is used.  Otherwise we would allocate memory just to initialize
+   it the same all the time.  UTF-8 is the preferred encoding so this is
+   a worthwhile optimization.  */
+static const bitset utf8_sb_map =
+{
+  /* Set the first 128 bits.  */
+# if 2 < BITSET_WORDS
+  BITSET_WORD_MAX,
+# endif
+# if 4 < BITSET_WORDS
+  BITSET_WORD_MAX,
+# endif
+# if 6 < BITSET_WORDS
+  BITSET_WORD_MAX,
+# endif
+# if 8 < BITSET_WORDS
+#  error "Invalid BITSET_WORDS"
+# endif
+  (BITSET_WORD_MAX
+   >> (SBC_MAX % BITSET_WORD_BITS == 0
+       ? 0
+       : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS))
+};
+#endif
+
+
+static void
+free_dfa_content (re_dfa_t *dfa)
+{
+  Idx i, j;
+
+  if (dfa->nodes)
+    for (i = 0; i < dfa->nodes_len; ++i)
+      free_token (dfa->nodes + i);
+  re_free (dfa->nexts);
+  for (i = 0; i < dfa->nodes_len; ++i)
+    {
+      if (dfa->eclosures != NULL)
+       re_node_set_free (dfa->eclosures + i);
+      if (dfa->inveclosures != NULL)
+       re_node_set_free (dfa->inveclosures + i);
+      if (dfa->edests != NULL)
+       re_node_set_free (dfa->edests + i);
+    }
+  re_free (dfa->edests);
+  re_free (dfa->eclosures);
+  re_free (dfa->inveclosures);
+  re_free (dfa->nodes);
+
+  if (dfa->state_table)
+    for (i = 0; i <= dfa->state_hash_mask; ++i)
+      {
+       struct re_state_table_entry *entry = dfa->state_table + i;
+       for (j = 0; j < entry->num; ++j)
+         {
+           re_dfastate_t *state = entry->array[j];
+           free_state (state);
+         }
+        re_free (entry->array);
+      }
+  re_free (dfa->state_table);
+#ifdef RE_ENABLE_I18N
+  if (dfa->sb_char != utf8_sb_map)
+    re_free (dfa->sb_char);
+#endif
+  re_free (dfa->subexp_map);
+#ifdef DEBUG
+  re_free (dfa->re_str);
+#endif
+
+  re_free (dfa);
+}
+
+
+/* Free dynamically allocated space used by PREG.  */
+
+void
+regfree (regex_t *preg)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  if (BE (dfa != NULL, 1))
+    free_dfa_content (dfa);
+  preg->re_buffer = NULL;
+  preg->re_allocated = 0;
+
+  re_free (preg->re_fastmap);
+  preg->re_fastmap = NULL;
+
+  re_free (preg->re_translate);
+  preg->re_translate = NULL;
+}
+#ifdef _LIBC
+weak_alias (__regfree, regfree)
+#endif
+\f
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them unless specifically requested.  */
+
+#if defined _REGEX_RE_COMP || defined _LIBC
+
+/* BSD has one and only one pattern buffer.  */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+# ifdef _LIBC
+/* Make these definitions weak in libc, so POSIX programs can redefine
+   these names if they don't use our functions, and still use
+   regcomp/regexec above without link errors.  */
+weak_function
+# endif
+re_comp (const char *s)
+{
+  reg_errcode_t ret;
+  char *fastmap;
+
+  if (!s)
+    {
+      if (!re_comp_buf.re_buffer)
+       return gettext ("No previous regular expression");
+      return 0;
+    }
+
+  if (re_comp_buf.re_buffer)
+    {
+      fastmap = re_comp_buf.re_fastmap;
+      re_comp_buf.re_fastmap = NULL;
+      __regfree (&re_comp_buf);
+      memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
+      re_comp_buf.re_fastmap = fastmap;
+    }
+
+  if (re_comp_buf.re_fastmap == NULL)
+    {
+      re_comp_buf.re_fastmap = (char *) malloc (SBC_MAX);
+      if (re_comp_buf.re_fastmap == NULL)
+       return (char *) gettext (__re_error_msgid
+                                + __re_error_msgid_idx[(int) REG_ESPACE]);
+    }
+
+  /* Since `re_exec' always passes NULL for the `regs' argument, we
+     don't need to initialize the pattern buffer fields which affect it.  */
+
+  /* Match anchors at newlines.  */
+  re_comp_buf.re_newline_anchor = 1;
+
+  ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
+
+  if (!ret)
+    return NULL;
+
+  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
+  return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
+}
+
+#ifdef _LIBC
+libc_freeres_fn (free_mem)
+{
+  __regfree (&re_comp_buf);
+}
+#endif
+
+#endif /* _REGEX_RE_COMP */
+\f
+/* Internal entry point.
+   Compile the regular expression PATTERN, whose length is LENGTH.
+   SYNTAX indicate regular expression's syntax.  */
+
+static reg_errcode_t
+re_compile_internal (regex_t *preg, const char *pattern, Idx length,
+                    reg_syntax_t syntax)
+{
+  reg_errcode_t err = REG_NOERROR;
+  re_dfa_t *dfa;
+  re_string_t regexp;
+
+  /* Initialize the pattern buffer.  */
+  preg->re_fastmap_accurate = 0;
+  preg->re_syntax = syntax;
+  preg->re_not_bol = preg->re_not_eol = 0;
+  preg->re_used = 0;
+  preg->re_nsub = 0;
+  preg->re_can_be_null = 0;
+  preg->re_regs_allocated = REG_UNALLOCATED;
+
+  /* Initialize the dfa.  */
+  dfa = (re_dfa_t *) preg->re_buffer;
+  if (BE (preg->re_allocated < sizeof (re_dfa_t), 0))
+    {
+      /* If zero allocated, but buffer is non-null, try to realloc
+        enough space.  This loses if buffer's address is bogus, but
+        that is the user's responsibility.  If buffer is null this
+        is a simple allocation.  */
+      dfa = re_realloc (preg->re_buffer, re_dfa_t, 1);
+      if (dfa == NULL)
+       return REG_ESPACE;
+      preg->re_allocated = sizeof (re_dfa_t);
+      preg->re_buffer = (unsigned char *) dfa;
+    }
+  preg->re_used = sizeof (re_dfa_t);
+
+  __libc_lock_init (dfa->lock);
+
+  err = init_dfa (dfa, length);
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_dfa_content (dfa);
+      preg->re_buffer = NULL;
+      preg->re_allocated = 0;
+      return err;
+    }
+#ifdef DEBUG
+  dfa->re_str = re_malloc (char, length + 1);
+  strncpy (dfa->re_str, pattern, length + 1);
+#endif
+
+  err = re_string_construct (&regexp, pattern, length, preg->re_translate,
+                            syntax & REG_IGNORE_CASE, dfa);
+  if (BE (err != REG_NOERROR, 0))
+    {
+    re_compile_internal_free_return:
+      free_workarea_compile (preg);
+      re_string_destruct (&regexp);
+      free_dfa_content (dfa);
+      preg->re_buffer = NULL;
+      preg->re_allocated = 0;
+      return err;
+    }
+
+  /* Parse the regular expression, and build a structure tree.  */
+  preg->re_nsub = 0;
+  dfa->str_tree = parse (&regexp, preg, syntax, &err);
+  if (BE (dfa->str_tree == NULL, 0))
+    goto re_compile_internal_free_return;
+
+  /* Analyze the tree and create the nfa.  */
+  err = analyze (preg);
+  if (BE (err != REG_NOERROR, 0))
+    goto re_compile_internal_free_return;
+
+#ifdef RE_ENABLE_I18N
+  /* If possible, do searching in single byte encoding to speed things up.  */
+  if (dfa->is_utf8 && !(syntax & REG_IGNORE_CASE) && preg->re_translate == NULL)
+    optimize_utf8 (dfa);
+#endif
+
+  /* Then create the initial state of the dfa.  */
+  err = create_initial_state (dfa);
+
+  /* Release work areas.  */
+  free_workarea_compile (preg);
+  re_string_destruct (&regexp);
+
+  if (BE (err != REG_NOERROR, 0))
+    {
+      free_dfa_content (dfa);
+      preg->re_buffer = NULL;
+      preg->re_allocated = 0;
+    }
+
+  return err;
+}
+
+/* Initialize DFA.  We use the length of the regular expression PAT_LEN
+   as the initial length of some arrays.  */
+
+static reg_errcode_t
+init_dfa (re_dfa_t *dfa, Idx pat_len)
+{
+  __re_size_t table_size;
+#ifndef _LIBC
+  char *codeset_name;
+#endif
+
+  memset (dfa, '\0', sizeof (re_dfa_t));
+
+  /* Force allocation of str_tree_storage the first time.  */
+  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
+
+  dfa->nodes_alloc = pat_len + 1;
+  dfa->nodes = re_xmalloc (re_token_t, dfa->nodes_alloc);
+
+  /*  table_size = 2 ^ ceil(log pat_len) */
+  for (table_size = 1; table_size <= pat_len; table_size <<= 1)
+    if (0 < (Idx) -1 && table_size == 0)
+      return REG_ESPACE;
+
+  dfa->state_table = re_calloc (struct re_state_table_entry, table_size);
+  dfa->state_hash_mask = table_size - 1;
+
+  dfa->mb_cur_max = MB_CUR_MAX;
+#ifdef _LIBC
+  if (dfa->mb_cur_max == 6
+      && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
+    dfa->is_utf8 = 1;
+  dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
+                      != 0);
+#else
+# ifdef HAVE_LANGINFO_CODESET
+  codeset_name = nl_langinfo (CODESET);
+# else
+  codeset_name = getenv ("LC_ALL");
+  if (codeset_name == NULL || codeset_name[0] == '\0')
+    codeset_name = getenv ("LC_CTYPE");
+  if (codeset_name == NULL || codeset_name[0] == '\0')
+    codeset_name = getenv ("LANG");
+  if (codeset_name == NULL)
+    codeset_name = "";
+  else if (strchr (codeset_name, '.') !=  NULL)
+    codeset_name = strchr (codeset_name, '.') + 1;
+# endif
+
+  if (strcasecmp (codeset_name, "UTF-8") == 0
+      || strcasecmp (codeset_name, "UTF8") == 0)
+    dfa->is_utf8 = 1;
+
+  /* We check exhaustively in the loop below if this charset is a
+     superset of ASCII.  */
+  dfa->map_notascii = 0;
+#endif
+
+#ifdef RE_ENABLE_I18N
+  if (dfa->mb_cur_max > 1)
+    {
+      if (dfa->is_utf8)
+       dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
+      else
+       {
+         int i, j, ch;
+
+         dfa->sb_char = re_calloc (bitset_word, BITSET_WORDS);
+         if (BE (dfa->sb_char == NULL, 0))
+           return REG_ESPACE;
+
+         /* Set the bits corresponding to single byte chars.  */
+         for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+           for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+             {
+               wint_t wch = __btowc (ch);
+               if (wch != WEOF)
+                 dfa->sb_char[i] |= (bitset_word) 1 << j;
+# ifndef _LIBC
+               if (isascii (ch) && wch != ch)
+                 dfa->map_notascii = 1;
+# endif
+             }
+       }
+    }
+#endif
+
+  if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0))
+    return REG_ESPACE;
+  return REG_NOERROR;
+}
+
+/* Initialize WORD_CHAR table, which indicate which character is
+   "word".  In this case "word" means that it is the word construction
+   character used by some operators like "\<", "\>", etc.  */
+
+static void
+init_word_char (re_dfa_t *dfa)
+{
+  int i, j, ch;
+  dfa->word_ops_used = 1;
+  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
+    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
+      if (isalnum (ch) || ch == '_')
+       dfa->word_char[i] |= (bitset_word) 1 << j;
+}
+
+/* Free the work area which are only used while compiling.  */
+
+static void
+free_workarea_compile (regex_t *preg)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  bin_tree_storage_t *storage, *next;
+  for (storage = dfa->str_tree_storage; storage; storage = next)
+    {
+      next = storage->next;
+      re_free (storage);
+    }
+  dfa->str_tree_storage = NULL;
+  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
+  dfa->str_tree = NULL;
+  re_free (dfa->org_indices);
+  dfa->org_indices = NULL;
+}
+
+/* Create initial states for all contexts.  */
+
+static reg_errcode_t
+create_initial_state (re_dfa_t *dfa)
+{
+  Idx first, i;
+  reg_errcode_t err;
+  re_node_set init_nodes;
+
+  /* Initial states have the epsilon closure of the node which is
+     the first node of the regular expression.  */
+  first = dfa->str_tree->first->node_idx;
+  dfa->init_node = first;
+  err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+
+  /* The back-references which are in initial states can epsilon transit,
+     since in this case all of the subexpressions can be null.
+     Then we add epsilon closures of the nodes which are the next nodes of
+     the back-references.  */
+  if (dfa->nbackref > 0)
+    for (i = 0; i < init_nodes.nelem; ++i)
+      {
+       Idx node_idx = init_nodes.elems[i];
+       re_token_type_t type = dfa->nodes[node_idx].type;
+
+       Idx clexp_idx;
+       if (type != OP_BACK_REF)
+         continue;
+       for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
+         {
+           re_token_t *clexp_node;
+           clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
+           if (clexp_node->type == OP_CLOSE_SUBEXP
+               && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)
+             break;
+         }
+       if (clexp_idx == init_nodes.nelem)
+         continue;
+
+       if (type == OP_BACK_REF)
+         {
+           Idx dest_idx = dfa->edests[node_idx].elems[0];
+           if (!re_node_set_contains (&init_nodes, dest_idx))
+             {
+               re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
+               i = 0;
+             }
+         }
+      }
+
+  /* It must be the first time to invoke acquire_state.  */
+  dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
+  /* We don't check ERR here, since the initial state must not be NULL.  */
+  if (BE (dfa->init_state == NULL, 0))
+    return err;
+  if (dfa->init_state->has_constraint)
+    {
+      dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
+                                                      CONTEXT_WORD);
+      dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
+                                                    CONTEXT_NEWLINE);
+      dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
+                                                        &init_nodes,
+                                                        CONTEXT_NEWLINE
+                                                        | CONTEXT_BEGBUF);
+      if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL
+             || dfa->init_state_begbuf == NULL, 0))
+       return err;
+    }
+  else
+    dfa->init_state_word = dfa->init_state_nl
+      = dfa->init_state_begbuf = dfa->init_state;
+
+  re_node_set_free (&init_nodes);
+  return REG_NOERROR;
+}
+\f
+#ifdef RE_ENABLE_I18N
+/* If it is possible to do searching in single byte encoding instead of UTF-8
+   to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
+   DFA nodes where needed.  */
+
+static void
+optimize_utf8 (re_dfa_t *dfa)
+{
+  Idx node;
+  int i;
+  bool mb_chars = false;
+  bool has_period = false;
+
+  for (node = 0; node < dfa->nodes_len; ++node)
+    switch (dfa->nodes[node].type)
+      {
+      case CHARACTER:
+       if (dfa->nodes[node].opr.c >= 0x80)
+         mb_chars = true;
+       break;
+      case ANCHOR:
+       switch (dfa->nodes[node].opr.idx)
+         {
+         case LINE_FIRST:
+         case LINE_LAST:
+         case BUF_FIRST:
+         case BUF_LAST:
+           break;
+         default:
+           /* Word anchors etc. cannot be handled.  */
+           return;
+         }
+       break;
+      case OP_PERIOD:
+        has_period = true;
+        break;
+      case OP_BACK_REF:
+      case OP_ALT:
+      case END_OF_RE:
+      case OP_DUP_ASTERISK:
+      case OP_OPEN_SUBEXP:
+      case OP_CLOSE_SUBEXP:
+       break;
+      case COMPLEX_BRACKET:
+       return;
+      case SIMPLE_BRACKET:
+       /* Just double check.  */
+       {
+         int rshift =
+           (SBC_MAX / 2 % BITSET_WORD_BITS == 0
+            ? 0
+            : BITSET_WORD_BITS - SBC_MAX / 2 % BITSET_WORD_BITS);
+         for (i = SBC_MAX / 2 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
+           {
+             if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0)
+               return;
+             rshift = 0;
+           }
+       }
+       break;
+      default:
+       abort ();
+      }
+
+  if (mb_chars || has_period)
+    for (node = 0; node < dfa->nodes_len; ++node)
+      {
+       if (dfa->nodes[node].type == CHARACTER
+           && dfa->nodes[node].opr.c >= 0x80)
+         dfa->nodes[node].mb_partial = 0;
+       else if (dfa->nodes[node].type == OP_PERIOD)
+         dfa->nodes[node].type = OP_UTF8_PERIOD;
+      }
+
+  /* The search can be in single byte locale.  */
+  dfa->mb_cur_max = 1;
+  dfa->is_utf8 = 0;
+  dfa->has_mb_node = dfa->nbackref > 0 || has_period;
+}
+#endif
+\f
+/* Analyze the structure tree, and calculate "first", "next", "edest",
+   "eclosure", and "inveclosure".  */
+
+static reg_errcode_t
+analyze (regex_t *preg)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  reg_errcode_t ret;
+
+  /* Allocate arrays.  */
+  dfa->nexts = re_malloc (Idx, dfa->nodes_alloc);
+  dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc);
+  dfa->edests = re_xmalloc (re_node_set, dfa->nodes_alloc);
+  dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
+  if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
+         || dfa->eclosures == NULL, 0))
+    return REG_ESPACE;
+
+  dfa->subexp_map = re_xmalloc (Idx, preg->re_nsub);
+  if (dfa->subexp_map != NULL)
+    {
+      Idx i;
+      for (i = 0; i < preg->re_nsub; i++)
+       dfa->subexp_map[i] = i;
+      preorder (dfa->str_tree, optimize_subexps, dfa);
+      for (i = 0; i < preg->re_nsub; i++)
+       if (dfa->subexp_map[i] != i)
+         break;
+      if (i == preg->re_nsub)
+       {
+         free (dfa->subexp_map);
+         dfa->subexp_map = NULL;
+       }
+    }
+
+  ret = postorder (dfa->str_tree, lower_subexps, preg);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  ret = postorder (dfa->str_tree, calc_first, dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  preorder (dfa->str_tree, calc_next, dfa);
+  ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+  ret = calc_eclosure (dfa);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+
+  /* We only need this during the prune_impossible_nodes pass in regexec.c;
+     skip it if p_i_n will not run, as calc_inveclosure can be quadratic.  */
+  if ((!preg->re_no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
+      || dfa->nbackref)
+    {
+      dfa->inveclosures = re_xmalloc (re_node_set, dfa->nodes_len);
+      if (BE (dfa->inveclosures == NULL, 0))
+        return REG_ESPACE;
+      ret = calc_inveclosure (dfa);
+    }
+
+  return ret;
+}
+
+/* Our parse trees are very unbalanced, so we cannot use a stack to
+   implement parse tree visits.  Instead, we use parent pointers and
+   some hairy code in these two functions.  */
+static reg_errcode_t
+postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
+          void *extra)
+{
+  bin_tree_t *node, *prev;
+
+  for (node = root; ; )
+    {
+      /* Descend down the tree, preferably to the left (or to the right
+        if that's the only child).  */
+      while (node->left || node->right)
+       if (node->left)
+          node = node->left;
+        else
+          node = node->right;
+
+      do
+       {
+         reg_errcode_t err = fn (extra, node);
+         if (BE (err != REG_NOERROR, 0))
+           return err;
+          if (node->parent == NULL)
+           return REG_NOERROR;
+         prev = node;
+         node = node->parent;
+       }
+      /* Go up while we have a node that is reached from the right.  */
+      while (node->right == prev || node->right == NULL);
+      node = node->right;
+    }
+}
+
+static reg_errcode_t
+preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
+         void *extra)
+{
+  bin_tree_t *node;
+
+  for (node = root; ; )
+    {
+      reg_errcode_t err = fn (extra, node);
+      if (BE (err != REG_NOERROR, 0))
+       return err;
+
+      /* Go to the left node, or up and to the right.  */
+      if (node->left)
+       node = node->left;
+      else
+       {
+         bin_tree_t *prev = NULL;
+         while (node->right == prev || node->right == NULL)
+           {
+             prev = node;
+             node = node->parent;
+             if (!node)
+               return REG_NOERROR;
+           }
+         node = node->right;
+       }
+    }
+}
+
+/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
+   re_search_internal to map the inner one's opr.idx to this one's.  Adjust
+   backreferences as well.  Requires a preorder visit.  */
+static reg_errcode_t
+optimize_subexps (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+
+  if (node->token.type == OP_BACK_REF && dfa->subexp_map)
+    {
+      int idx = node->token.opr.idx;
+      node->token.opr.idx = dfa->subexp_map[idx];
+      dfa->used_bkref_map |= 1 << node->token.opr.idx;
+    }
+
+  else if (node->token.type == SUBEXP
+           && node->left && node->left->token.type == SUBEXP)
+    {
+      Idx other_idx = node->left->token.opr.idx;
+
+      node->left = node->left->left;
+      if (node->left)
+        node->left->parent = node;
+
+      dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
+      if (other_idx < BITSET_WORD_BITS)
+       dfa->used_bkref_map &= ~ ((bitset_word) 1 << other_idx);
+    }
+
+  return REG_NOERROR;
+}
+
+/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
+   of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP.  */
+static reg_errcode_t
+lower_subexps (void *extra, bin_tree_t *node)
+{
+  regex_t *preg = (regex_t *) extra;
+  reg_errcode_t err = REG_NOERROR;
+
+  if (node->left && node->left->token.type == SUBEXP)
+    {
+      node->left = lower_subexp (&err, preg, node->left);
+      if (node->left)
+       node->left->parent = node;
+    }
+  if (node->right && node->right->token.type == SUBEXP)
+    {
+      node->right = lower_subexp (&err, preg, node->right);
+      if (node->right)
+       node->right->parent = node;
+    }
+
+  return err;
+}
+
+static bin_tree_t *
+lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  bin_tree_t *body = node->left;
+  bin_tree_t *op, *cls, *tree1, *tree;
+
+  if (preg->re_no_sub
+      /* We do not optimize empty subexpressions, because otherwise we may
+        have bad CONCAT nodes with NULL children.  This is obviously not
+        very common, so we do not lose much.  An example that triggers
+        this case is the sed "script" /\(\)/x.  */
+      && node->left != NULL
+      && ! (node->token.opr.idx < BITSET_WORD_BITS
+           && dfa->used_bkref_map & ((bitset_word) 1 << node->token.opr.idx)))
+    return node->left;
+
+  /* Convert the SUBEXP node to the concatenation of an
+     OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP.  */
+  op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
+  cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
+  tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
+  tree = create_tree (dfa, op, tree1, CONCAT);
+  if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
+  op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
+  return tree;
+}
+
+/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
+   nodes.  Requires a postorder visit.  */
+static reg_errcode_t
+calc_first (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+  if (node->token.type == CONCAT)
+    {
+      node->first = node->left->first;
+      node->node_idx = node->left->node_idx;
+    }
+  else
+    {
+      node->first = node;
+      node->node_idx = re_dfa_add_node (dfa, node->token);
+      if (BE (node->node_idx == REG_MISSING, 0))
+        return REG_ESPACE;
+    }
+  return REG_NOERROR;
+}
+
+/* Pass 2: compute NEXT on the tree.  Preorder visit.  */
+static reg_errcode_t
+calc_next (void *extra, bin_tree_t *node)
+{
+  switch (node->token.type)
+    {
+    case OP_DUP_ASTERISK:
+      node->left->next = node;
+      break;
+    case CONCAT:
+      node->left->next = node->right->first;
+      node->right->next = node->next;
+      break;
+    default:
+      if (node->left)
+       node->left->next = node->next;
+      if (node->right)
+        node->right->next = node->next;
+      break;
+    }
+  return REG_NOERROR;
+}
+
+/* Pass 3: link all DFA nodes to their NEXT node (any order will do).  */
+static reg_errcode_t
+link_nfa_nodes (void *extra, bin_tree_t *node)
+{
+  re_dfa_t *dfa = (re_dfa_t *) extra;
+  Idx idx = node->node_idx;
+  reg_errcode_t err = REG_NOERROR;
+
+  switch (node->token.type)
+    {
+    case CONCAT:
+      break;
+
+    case END_OF_RE:
+      assert (node->next == NULL);
+      break;
+
+    case OP_DUP_ASTERISK:
+    case OP_ALT:
+      {
+       Idx left, right;
+       dfa->has_plural_match = 1;
+       if (node->left != NULL)
+         left = node->left->first->node_idx;
+       else
+         left = node->next->node_idx;
+       if (node->right != NULL)
+         right = node->right->first->node_idx;
+       else
+         right = node->next->node_idx;
+       assert (REG_VALID_INDEX (left));
+       assert (REG_VALID_INDEX (right));
+       err = re_node_set_init_2 (dfa->edests + idx, left, right);
+      }
+      break;
+
+    case ANCHOR:
+    case OP_OPEN_SUBEXP:
+    case OP_CLOSE_SUBEXP:
+      err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
+      break;
+
+    case OP_BACK_REF:
+      dfa->nexts[idx] = node->next->node_idx;
+      if (node->token.type == OP_BACK_REF)
+       re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
+      break;
+
+    default:
+      assert (!IS_EPSILON_NODE (node->token.type));
+      dfa->nexts[idx] = node->next->node_idx;
+      break;
+    }
+
+  return err;
+}
+
+/* Duplicate the epsilon closure of the node ROOT_NODE.
+   Note that duplicated nodes have constraint INIT_CONSTRAINT in addition
+   to their own constraint.  */
+
+static reg_errcode_t
+duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node,
+                       Idx top_clone_node, Idx root_node,
+                       unsigned int init_constraint)
+{
+  Idx org_node, clone_node;
+  bool ok;
+  unsigned int constraint = init_constraint;
+  for (org_node = top_org_node, clone_node = top_clone_node;;)
+    {
+      Idx org_dest, clone_dest;
+      if (dfa->nodes[org_node].type == OP_BACK_REF)
+       {
+         /* If the back reference epsilon-transit, its destination must
+            also have the constraint.  Then duplicate the epsilon closure
+            of the destination of the back reference, and store it in
+            edests of the back reference.  */
+         org_dest = dfa->nexts[org_node];
+         re_node_set_empty (dfa->edests + clone_node);
+         clone_dest = duplicate_node (dfa, org_dest, constraint);
+         if (BE (clone_dest == REG_MISSING, 0))
+           return REG_ESPACE;
+         dfa->nexts[clone_node] = dfa->nexts[org_node];
+         ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+         if (BE (! ok, 0))
+           return REG_ESPACE;
+       }
+      else if (dfa->edests[org_node].nelem == 0)
+       {
+         /* In case of the node can't epsilon-transit, don't duplicate the
+            destination and store the original destination as the
+            destination of the node.  */
+         dfa->nexts[clone_node] = dfa->nexts[org_node];
+         break;
+       }
+      else if (dfa->edests[org_node].nelem == 1)
+       {
+         /* In case of the node can epsilon-transit, and it has only one
+            destination.  */
+         org_dest = dfa->edests[org_node].elems[0];
+         re_node_set_empty (dfa->edests + clone_node);
+         if (dfa->nodes[org_node].type == ANCHOR)
+           {
+             /* In case of the node has another constraint, append it.  */
+             if (org_node == root_node && clone_node != org_node)
+               {
+                 /* ...but if the node is root_node itself, it means the
+                    epsilon closure have a loop, then tie it to the
+                    destination of the root_node.  */
+                 ok = re_node_set_insert (dfa->edests + clone_node,
+                                           org_dest);
+                 if (BE (! ok, 0))
+                   return REG_ESPACE;
+                 break;
+               }
+             constraint |= dfa->nodes[org_node].opr.ctx_type;
+           }
+         clone_dest = duplicate_node (dfa, org_dest, constraint);
+         if (BE (clone_dest == REG_MISSING, 0))
+           return REG_ESPACE;
+         ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+         if (BE (! ok, 0))
+           return REG_ESPACE;
+       }
+      else /* dfa->edests[org_node].nelem == 2 */
+       {
+         /* In case of the node can epsilon-transit, and it has two
+            destinations. In the bin_tree_t and DFA, that's '|' and '*'.   */
+         org_dest = dfa->edests[org_node].elems[0];
+         re_node_set_empty (dfa->edests + clone_node);
+         /* Search for a duplicated node which satisfies the constraint.  */
+         clone_dest = search_duplicated_node (dfa, org_dest, constraint);
+         if (clone_dest == REG_MISSING)
+           {
+             /* There are no such a duplicated node, create a new one.  */
+             reg_errcode_t err;
+             clone_dest = duplicate_node (dfa, org_dest, constraint);
+             if (BE (clone_dest == REG_MISSING, 0))
+               return REG_ESPACE;
+             ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+             if (BE (! ok, 0))
+               return REG_ESPACE;
+             err = duplicate_node_closure (dfa, org_dest, clone_dest,
+                                           root_node, constraint);
+             if (BE (err != REG_NOERROR, 0))
+               return err;
+           }
+         else
+           {
+             /* There are a duplicated node which satisfy the constraint,
+                use it to avoid infinite loop.  */
+             ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+             if (BE (! ok, 0))
+               return REG_ESPACE;
+           }
+
+         org_dest = dfa->edests[org_node].elems[1];
+         clone_dest = duplicate_node (dfa, org_dest, constraint);
+         if (BE (clone_dest == REG_MISSING, 0))
+           return REG_ESPACE;
+         ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
+         if (BE (! ok, 0))
+           return REG_ESPACE;
+       }
+      org_node = org_dest;
+      clone_node = clone_dest;
+    }
+  return REG_NOERROR;
+}
+
+/* Search for a node which is duplicated from the node ORG_NODE, and
+   satisfies the constraint CONSTRAINT.  */
+
+static Idx
+search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
+                       unsigned int constraint)
+{
+  Idx idx;
+  for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
+    {
+      if (org_node == dfa->org_indices[idx]
+         && constraint == dfa->nodes[idx].constraint)
+       return idx; /* Found.  */
+    }
+  return REG_MISSING; /* Not found.  */
+}
+
+/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
+   Return the index of the new node, or REG_MISSING if insufficient storage is
+   available.  */
+
+static Idx
+duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint)
+{
+  Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
+  if (BE (dup_idx != REG_MISSING, 1))
+    {
+      dfa->nodes[dup_idx].constraint = constraint;
+      if (dfa->nodes[org_idx].type == ANCHOR)
+       dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type;
+      dfa->nodes[dup_idx].duplicated = 1;
+
+      /* Store the index of the original node.  */
+      dfa->org_indices[dup_idx] = org_idx;
+    }
+  return dup_idx;
+}
+
+static reg_errcode_t
+calc_inveclosure (re_dfa_t *dfa)
+{
+  Idx src, idx;
+  bool ok;
+  for (idx = 0; idx < dfa->nodes_len; ++idx)
+    re_node_set_init_empty (dfa->inveclosures + idx);
+
+  for (src = 0; src < dfa->nodes_len; ++src)
+    {
+      Idx *elems = dfa->eclosures[src].elems;
+      for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
+       {
+         ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
+         if (BE (! ok, 0))
+           return REG_ESPACE;
+       }
+    }
+
+  return REG_NOERROR;
+}
+
+/* Calculate "eclosure" for all the node in DFA.  */
+
+static reg_errcode_t
+calc_eclosure (re_dfa_t *dfa)
+{
+  Idx node_idx;
+  bool incomplete;
+#ifdef DEBUG
+  assert (dfa->nodes_len > 0);
+#endif
+  incomplete = false;
+  /* For each nodes, calculate epsilon closure.  */
+  for (node_idx = 0; ; ++node_idx)
+    {
+      reg_errcode_t err;
+      re_node_set eclosure_elem;
+      if (node_idx == dfa->nodes_len)
+       {
+         if (!incomplete)
+           break;
+         incomplete = false;
+         node_idx = 0;
+       }
+
+#ifdef DEBUG
+      assert (dfa->eclosures[node_idx].nelem != REG_MISSING);
+#endif
+
+      /* If we have already calculated, skip it.  */
+      if (dfa->eclosures[node_idx].nelem != 0)
+       continue;
+      /* Calculate epsilon closure of `node_idx'.  */
+      err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true);
+      if (BE (err != REG_NOERROR, 0))
+       return err;
+
+      if (dfa->eclosures[node_idx].nelem == 0)
+       {
+         incomplete = true;
+         re_node_set_free (&eclosure_elem);
+       }
+    }
+  return REG_NOERROR;
+}
+
+/* Calculate epsilon closure of NODE.  */
+
+static reg_errcode_t
+calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
+{
+  reg_errcode_t err;
+  unsigned int constraint;
+  Idx i;
+  bool incomplete;
+  bool ok;
+  re_node_set eclosure;
+  incomplete = false;
+  err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
+  if (BE (err != REG_NOERROR, 0))
+    return err;
+
+  /* This indicates that we are calculating this node now.
+     We reference this value to avoid infinite loop.  */
+  dfa->eclosures[node].nelem = REG_MISSING;
+
+  constraint = ((dfa->nodes[node].type == ANCHOR)
+               ? dfa->nodes[node].opr.ctx_type : 0);
+  /* If the current node has constraints, duplicate all nodes.
+     Since they must inherit the constraints.  */
+  if (constraint
+      && dfa->edests[node].nelem
+      && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
+    {
+      Idx org_node, cur_node;
+      org_node = cur_node = node;
+      err = duplicate_node_closure (dfa, node, node, node, constraint);
+      if (BE (err != REG_NOERROR, 0))
+       return err;
+    }
+
+  /* Expand each epsilon destination nodes.  */
+  if (IS_EPSILON_NODE(dfa->nodes[node].type))
+    for (i = 0; i < dfa->edests[node].nelem; ++i)
+      {
+       re_node_set eclosure_elem;
+       Idx edest = dfa->edests[node].elems[i];
+       /* If calculating the epsilon closure of `edest' is in progress,
+          return intermediate result.  */
+       if (dfa->eclosures[edest].nelem == REG_MISSING)
+         {
+           incomplete = true;
+           continue;
+         }
+       /* If we haven't calculated the epsilon closure of `edest' yet,
+          calculate now. Otherwise use calculated epsilon closure.  */
+       if (dfa->eclosures[edest].nelem == 0)
+         {
+           err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false);
+           if (BE (err != REG_NOERROR, 0))
+             return err;
+         }
+       else
+         eclosure_elem = dfa->eclosures[edest];
+       /* Merge the epsilon closure of `edest'.  */
+       re_node_set_merge (&eclosure, &eclosure_elem);
+       /* If the epsilon closure of `edest' is incomplete,
+          the epsilon closure of this node is also incomplete.  */
+       if (dfa->eclosures[edest].nelem == 0)
+         {
+           incomplete = true;
+           re_node_set_free (&eclosure_elem);
+         }
+      }
+
+  /* Epsilon closures include itself.  */
+  ok = re_node_set_insert (&eclosure, node);
+  if (BE (! ok, 0))
+    return REG_ESPACE;
+  if (incomplete && !root)
+    dfa->eclosures[node].nelem = 0;
+  else
+    dfa->eclosures[node] = eclosure;
+  *new_set = eclosure;
+  return REG_NOERROR;
+}
+\f
+/* Functions for token which are used in the parser.  */
+
+/* Fetch a token from INPUT.
+   We must not use this function inside bracket expressions.  */
+
+static void
+fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
+{
+  re_string_skip_bytes (input, peek_token (result, input, syntax));
+}
+
+/* Peek a token from INPUT, and return the length of the token.
+   We must not use this function inside bracket expressions.  */
+
+static int
+peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
+{
+  unsigned char c;
+
+  if (re_string_eoi (input))
+    {
+      token->type = END_OF_RE;
+      return 0;
+    }
+
+  c = re_string_peek_byte (input, 0);
+  token->opr.c = c;
+
+  token->word_char = 0;
+#ifdef RE_ENABLE_I18N
+  token->mb_partial = 0;
+  if (input->mb_cur_max > 1 &&
+      !re_string_first_byte (input, re_string_cur_idx (input)))
+    {
+      token->type = CHARACTER;
+      token->mb_partial = 1;
+      return 1;
+    }
+#endif
+  if (c == '\\')
+    {
+      unsigned char c2;
+      if (re_string_cur_idx (input) + 1 >= re_string_length (input))
+       {
+         token->type = BACK_SLASH;
+         return 1;
+       }
+
+      c2 = re_string_peek_byte_case (input, 1);
+      token->opr.c = c2;
+      token->type = CHARACTER;
+#ifdef RE_ENABLE_I18N
+      if (input->mb_cur_max > 1)
+       {
+         wint_t wc = re_string_wchar_at (input,
+                                         re_string_cur_idx (input) + 1);
+         token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+       }
+      else
+#endif
+       token->word_char = IS_WORD_CHAR (c2) != 0;
+
+      switch (c2)
+       {
+       case '|':
+         if (!(syntax & REG_LIMITED_OPS) && !(syntax & REG_NO_BK_VBAR))
+           token->type = OP_ALT;
+         break;
+       case '1': case '2': case '3': case '4': case '5':
+       case '6': case '7': case '8': case '9':
+         if (!(syntax & REG_NO_BK_REFS))
+           {
+             token->type = OP_BACK_REF;
+             token->opr.idx = c2 - '1';
+           }
+         break;
+       case '<':
+         if (!(syntax & REG_NO_GNU_OPS))
+           {
+             token->type = ANCHOR;
+             token->opr.ctx_type = WORD_FIRST;
+           }
+         break;
+       case '>':
+         if (!(syntax & REG_NO_GNU_OPS))
+           {
+             token->type = ANCHOR;
+             token->opr.ctx_type = WORD_LAST;
+           }
+         break;
+       case 'b':
+         if (!(syntax & REG_NO_GNU_OPS))
+           {
+             token->type = ANCHOR;
+             token->opr.ctx_type = WORD_DELIM;
+           }
+         break;
+       case 'B':
+         if (!(syntax & REG_NO_GNU_OPS))
+           {
+             token->type = ANCHOR;
+             token->opr.ctx_type = NOT_WORD_DELIM;
+           }
+         break;
+       case 'w':
+         if (!(syntax & REG_NO_GNU_OPS))
+           token->type = OP_WORD;
+         break;
+       case 'W':
+         if (!(syntax & REG_NO_GNU_OPS))
+           token->type = OP_NOTWORD;
+         break;
+       case 's':
+         if (!(syntax & REG_NO_GNU_OPS))
+           token->type = OP_SPACE;
+         break;
+       case 'S':
+         if (!(syntax & REG_NO_GNU_OPS))
+           token->type = OP_NOTSPACE;
+         break;
+       case '`':
+         if (!(syntax & REG_NO_GNU_OPS))
+           {
+             token->type = ANCHOR;
+             token->opr.ctx_type = BUF_FIRST;
+           }
+         break;
+       case '\'':
+         if (!(syntax & REG_NO_GNU_OPS))
+           {
+             token->type = ANCHOR;
+             token->opr.ctx_type = BUF_LAST;
+           }
+         break;
+       case '(':
+         if (!(syntax & REG_NO_BK_PARENS))
+           token->type = OP_OPEN_SUBEXP;
+         break;
+       case ')':
+         if (!(syntax & REG_NO_BK_PARENS))
+           token->type = OP_CLOSE_SUBEXP;
+         break;
+       case '+':
+         if (!(syntax & REG_LIMITED_OPS) && (syntax & REG_BK_PLUS_QM))
+           token->type = OP_DUP_PLUS;
+         break;
+       case '?':
+         if (!(syntax & REG_LIMITED_OPS) && (syntax & REG_BK_PLUS_QM))
+           token->type = OP_DUP_QUESTION;
+         break;
+       case '{':
+         if ((syntax & REG_INTERVALS) && (!(syntax & REG_NO_BK_BRACES)))
+           token->type = OP_OPEN_DUP_NUM;
+         break;
+       case '}':
+         if ((syntax & REG_INTERVALS) && (!(syntax & REG_NO_BK_BRACES)))
+           token->type = OP_CLOSE_DUP_NUM;
+         break;
+       default:
+         break;
+       }
+      return 2;
+    }
+
+  token->type = CHARACTER;
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1)
+    {
+      wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
+      token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
+    }
+  else
+#endif
+    token->word_char = IS_WORD_CHAR (token->opr.c);
+
+  switch (c)
+    {
+    case '\n':
+      if (syntax & REG_NEWLINE_ALT)
+       token->type = OP_ALT;
+      break;
+    case '|':
+      if (!(syntax & REG_LIMITED_OPS) && (syntax & REG_NO_BK_VBAR))
+       token->type = OP_ALT;
+      break;
+    case '*':
+      token->type = OP_DUP_ASTERISK;
+      break;
+    case '+':
+      if (!(syntax & REG_LIMITED_OPS) && !(syntax & REG_BK_PLUS_QM))
+       token->type = OP_DUP_PLUS;
+      break;
+    case '?':
+      if (!(syntax & REG_LIMITED_OPS) && !(syntax & REG_BK_PLUS_QM))
+       token->type = OP_DUP_QUESTION;
+      break;
+    case '{':
+      if ((syntax & REG_INTERVALS) && (syntax & REG_NO_BK_BRACES))
+       token->type = OP_OPEN_DUP_NUM;
+      break;
+    case '}':
+      if ((syntax & REG_INTERVALS) && (syntax & REG_NO_BK_BRACES))
+       token->type = OP_CLOSE_DUP_NUM;
+      break;
+    case '(':
+      if (syntax & REG_NO_BK_PARENS)
+       token->type = OP_OPEN_SUBEXP;
+      break;
+    case ')':
+      if (syntax & REG_NO_BK_PARENS)
+       token->type = OP_CLOSE_SUBEXP;
+      break;
+    case '[':
+      token->type = OP_OPEN_BRACKET;
+      break;
+    case '.':
+      token->type = OP_PERIOD;
+      break;
+    case '^':
+      if (!(syntax & (REG_CONTEXT_INDEP_ANCHORS | REG_CARET_ANCHORS_HERE)) &&
+         re_string_cur_idx (input) != 0)
+       {
+         char prev = re_string_peek_byte (input, -1);
+         if (!(syntax & REG_NEWLINE_ALT) || prev != '\n')
+           break;
+       }
+      token->type = ANCHOR;
+      token->opr.ctx_type = LINE_FIRST;
+      break;
+    case '$':
+      if (!(syntax & REG_CONTEXT_INDEP_ANCHORS) &&
+         re_string_cur_idx (input) + 1 != re_string_length (input))
+       {
+         re_token_t next;
+         re_string_skip_bytes (input, 1);
+         peek_token (&next, input, syntax);
+         re_string_skip_bytes (input, -1);
+         if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
+           break;
+       }
+      token->type = ANCHOR;
+      token->opr.ctx_type = LINE_LAST;
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+/* Peek a token from INPUT, and return the length of the token.
+   We must not use this function out of bracket expressions.  */
+
+static int
+peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
+{
+  unsigned char c;
+  if (re_string_eoi (input))
+    {
+      token->type = END_OF_RE;
+      return 0;
+    }
+  c = re_string_peek_byte (input, 0);
+  token->opr.c = c;
+
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1 &&
+      !re_string_first_byte (input, re_string_cur_idx (input)))
+    {
+      token->type = CHARACTER;
+      return 1;
+    }
+#endif /* RE_ENABLE_I18N */
+
+  if (c == '\\' && (syntax & REG_BACKSLASH_ESCAPE_IN_LISTS)
+      && re_string_cur_idx (input) + 1 < re_string_length (input))
+    {
+      /* In this case, '\' escape a character.  */
+      unsigned char c2;
+      re_string_skip_bytes (input, 1);
+      c2 = re_string_peek_byte (input, 0);
+      token->opr.c = c2;
+      token->type = CHARACTER;
+      return 1;
+    }
+  if (c == '[') /* '[' is a special char in a bracket exps.  */
+    {
+      unsigned char c2;
+      int token_len;
+      if (re_string_cur_idx (input) + 1 < re_string_length (input))
+       c2 = re_string_peek_byte (input, 1);
+      else
+       c2 = 0;
+      token->opr.c = c2;
+      token_len = 2;
+      switch (c2)
+       {
+       case '.':
+         token->type = OP_OPEN_COLL_ELEM;
+         break;
+       case '=':
+         token->type = OP_OPEN_EQUIV_CLASS;
+         break;
+       case ':':
+         if (syntax & REG_CHAR_CLASSES)
+           {
+             token->type = OP_OPEN_CHAR_CLASS;
+             break;
+           }
+         /* else fall through.  */
+       default:
+         token->type = CHARACTER;
+         token->opr.c = c;
+         token_len = 1;
+         break;
+       }
+      return token_len;
+    }
+  switch (c)
+    {
+    case '-':
+      token->type = OP_CHARSET_RANGE;
+      break;
+    case ']':
+      token->type = OP_CLOSE_BRACKET;
+      break;
+    case '^':
+      token->type = OP_NON_MATCH_LIST;
+      break;
+    default:
+      token->type = CHARACTER;
+    }
+  return 1;
+}
+\f
+/* Functions for parser.  */
+
+/* Entry point of the parser.
+   Parse the regular expression REGEXP and return the structure tree.
+   If an error is occured, ERR is set by error code, and return NULL.
+   This function build the following tree, from regular expression <reg_exp>:
+          CAT
+          / \
+         /   \
+   <reg_exp>  EOR
+
+   CAT means concatenation.
+   EOR means end of regular expression.  */
+
+static bin_tree_t *
+parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
+       reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  bin_tree_t *tree, *eor, *root;
+  re_token_t current_token;
+  dfa->syntax = syntax;
+  fetch_token (&current_token, regexp, syntax | REG_CARET_ANCHORS_HERE);
+  tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+  eor = create_tree (dfa, NULL, NULL, END_OF_RE);
+  if (tree != NULL)
+    root = create_tree (dfa, tree, eor, CONCAT);
+  else
+    root = eor;
+  if (BE (eor == NULL || root == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+  return root;
+}
+
+/* This function build the following tree, from regular expression
+   <branch1>|<branch2>:
+          ALT
+          / \
+         /   \
+   <branch1> <branch2>
+
+   ALT means alternative, which represents the operator `|'.  */
+
+static bin_tree_t *
+parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
+              reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  bin_tree_t *tree, *branch = NULL;
+  tree = parse_branch (regexp, preg, token, syntax, nest, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+
+  while (token->type == OP_ALT)
+    {
+      fetch_token (token, regexp, syntax | REG_CARET_ANCHORS_HERE);
+      if (token->type != OP_ALT && token->type != END_OF_RE
+         && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
+       {
+         branch = parse_branch (regexp, preg, token, syntax, nest, err);
+         if (BE (*err != REG_NOERROR && branch == NULL, 0))
+           return NULL;
+       }
+      else
+       branch = NULL;
+      tree = create_tree (dfa, tree, branch, OP_ALT);
+      if (BE (tree == NULL, 0))
+       {
+         *err = REG_ESPACE;
+         return NULL;
+       }
+    }
+  return tree;
+}
+
+/* This function build the following tree, from regular expression
+   <exp1><exp2>:
+       CAT
+       / \
+       /   \
+   <exp1> <exp2>
+
+   CAT means concatenation.  */
+
+static bin_tree_t *
+parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
+             reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
+{
+  bin_tree_t *tree, *exp;
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  tree = parse_expression (regexp, preg, token, syntax, nest, err);
+  if (BE (*err != REG_NOERROR && tree == NULL, 0))
+    return NULL;
+
+  while (token->type != OP_ALT && token->type != END_OF_RE
+        && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
+    {
+      exp = parse_expression (regexp, preg, token, syntax, nest, err);
+      if (BE (*err != REG_NOERROR && exp == NULL, 0))
+       {
+         return NULL;
+       }
+      if (tree != NULL && exp != NULL)
+       {
+         tree = create_tree (dfa, tree, exp, CONCAT);
+         if (tree == NULL)
+           {
+             *err = REG_ESPACE;
+             return NULL;
+           }
+       }
+      else if (tree == NULL)
+       tree = exp;
+      /* Otherwise exp == NULL, we don't need to create new tree.  */
+    }
+  return tree;
+}
+
+/* This function build the following tree, from regular expression a*:
+        *
+        |
+        a
+*/
+
+static bin_tree_t *
+parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
+                 reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  bin_tree_t *tree;
+  switch (token->type)
+    {
+    case CHARACTER:
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+       {
+         *err = REG_ESPACE;
+         return NULL;
+       }
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+       {
+         while (!re_string_eoi (regexp)
+                && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
+           {
+             bin_tree_t *mbc_remain;
+             fetch_token (token, regexp, syntax);
+             mbc_remain = create_token_tree (dfa, NULL, NULL, token);
+             tree = create_tree (dfa, tree, mbc_remain, CONCAT);
+             if (BE (mbc_remain == NULL || tree == NULL, 0))
+               {
+                 *err = REG_ESPACE;
+                 return NULL;
+               }
+           }
+       }
+#endif
+      break;
+    case OP_OPEN_SUBEXP:
+      tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+       return NULL;
+      break;
+    case OP_OPEN_BRACKET:
+      tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+       return NULL;
+      break;
+    case OP_BACK_REF:
+      if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1))
+       {
+         *err = REG_ESUBREG;
+         return NULL;
+       }
+      dfa->used_bkref_map |= 1 << token->opr.idx;
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+       {
+         *err = REG_ESPACE;
+         return NULL;
+       }
+      ++dfa->nbackref;
+      dfa->has_mb_node = 1;
+      break;
+    case OP_OPEN_DUP_NUM:
+      if (syntax & REG_CONTEXT_INVALID_DUP)
+       {
+         *err = REG_BADRPT;
+         return NULL;
+       }
+      /* FALLTHROUGH */
+    case OP_DUP_ASTERISK:
+    case OP_DUP_PLUS:
+    case OP_DUP_QUESTION:
+      if (syntax & REG_CONTEXT_INVALID_OPS)
+       {
+         *err = REG_BADRPT;
+         return NULL;
+       }
+      else if (syntax & REG_CONTEXT_INDEP_OPS)
+       {
+         fetch_token (token, regexp, syntax);
+         return parse_expression (regexp, preg, token, syntax, nest, err);
+       }
+      /* else fall through  */
+    case OP_CLOSE_SUBEXP:
+      if ((token->type == OP_CLOSE_SUBEXP) &&
+         !(syntax & REG_UNMATCHED_RIGHT_PAREN_ORD))
+       {
+         *err = REG_ERPAREN;
+         return NULL;
+       }
+      /* else fall through  */
+    case OP_CLOSE_DUP_NUM:
+      /* We treat it as a normal character.  */
+
+      /* Then we can these characters as normal characters.  */
+      token->type = CHARACTER;
+      /* mb_partial and word_char bits should be initialized already
+        by peek_token.  */
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+       {
+         *err = REG_ESPACE;
+         return NULL;
+       }
+      break;
+    case ANCHOR:
+      if ((token->opr.ctx_type
+          & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
+         && dfa->word_ops_used == 0)
+       init_word_char (dfa);
+      if (token->opr.ctx_type == WORD_DELIM
+          || token->opr.ctx_type == NOT_WORD_DELIM)
+       {
+         bin_tree_t *tree_first, *tree_last;
+         if (token->opr.ctx_type == WORD_DELIM)
+           {
+             token->opr.ctx_type = WORD_FIRST;
+             tree_first = create_token_tree (dfa, NULL, NULL, token);
+             token->opr.ctx_type = WORD_LAST;
+            }
+          else
+            {
+             token->opr.ctx_type = INSIDE_WORD;
+             tree_first = create_token_tree (dfa, NULL, NULL, token);
+             token->opr.ctx_type = INSIDE_NOTWORD;
+            }
+         tree_last = create_token_tree (dfa, NULL, NULL, token);
+         tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
+         if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0))
+           {
+             *err = REG_ESPACE;
+             return NULL;
+           }
+       }
+      else
+       {
+         tree = create_token_tree (dfa, NULL, NULL, token);
+         if (BE (tree == NULL, 0))
+           {
+             *err = REG_ESPACE;
+             return NULL;
+           }
+       }
+      /* We must return here, since ANCHORs can't be followed
+        by repetition operators.
+        eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
+            it must not be "<ANCHOR(^)><REPEAT(*)>".  */
+      fetch_token (token, regexp, syntax);
+      return tree;
+    case OP_PERIOD:
+      tree = create_token_tree (dfa, NULL, NULL, token);
+      if (BE (tree == NULL, 0))
+       {
+         *err = REG_ESPACE;
+         return NULL;
+       }
+      if (dfa->mb_cur_max > 1)
+       dfa->has_mb_node = 1;
+      break;
+    case OP_WORD:
+    case OP_NOTWORD:
+      tree = build_charclass_op (dfa, regexp->trans,
+                                (const unsigned char *) "alnum",
+                                (const unsigned char *) "_",
+                                token->type == OP_NOTWORD, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+       return NULL;
+      break;
+    case OP_SPACE:
+    case OP_NOTSPACE:
+      tree = build_charclass_op (dfa, regexp->trans,
+                                (const unsigned char *) "space",
+                                (const unsigned char *) "",
+                                token->type == OP_NOTSPACE, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+       return NULL;
+      break;
+    case OP_ALT:
+    case END_OF_RE:
+      return NULL;
+    case BACK_SLASH:
+      *err = REG_EESCAPE;
+      return NULL;
+    default:
+      /* Must not happen?  */
+#ifdef DEBUG
+      assert (0);
+#endif
+      return NULL;
+    }
+  fetch_token (token, regexp, syntax);
+
+  while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
+        || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
+    {
+      tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
+      if (BE (*err != REG_NOERROR && tree == NULL, 0))
+       return NULL;
+      /* In BRE consecutive duplications are not allowed.  */
+      if ((syntax & REG_CONTEXT_INVALID_DUP)
+         && (token->type == OP_DUP_ASTERISK
+             || token->type == OP_OPEN_DUP_NUM))
+       {
+         *err = REG_BADRPT;
+         return NULL;
+       }
+    }
+
+  return tree;
+}
+
+/* This function build the following tree, from regular expression
+   (<reg_exp>):
+        SUBEXP
+           |
+       <reg_exp>
+*/
+
+static bin_tree_t *
+parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
+              reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
+{
+  re_dfa_t *dfa = (re_dfa_t *) preg->re_buffer;
+  bin_tree_t *tree;
+  size_t cur_nsub;
+  cur_nsub = preg->re_nsub++;
+
+  fetch_token (token, regexp, syntax | REG_CARET_ANCHORS_HERE);
+
+  /* The subexpression may be a null string.  */
+  if (token->type == OP_CLOSE_SUBEXP)
+    tree = NULL;
+  else
+    {
+      tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
+      if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))
+        *err = REG_EPAREN;
+      if (BE (*err != REG_NOERROR, 0))
+       return NULL;
+    }
+
+  if (cur_nsub <= '9' - '1')
+    dfa->completed_bkref_map |= 1 << cur_nsub;
+
+  tree = create_tree (dfa, tree, NULL, SUBEXP);
+  if (BE (tree == NULL, 0))
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+  tree->token.opr.idx = cur_nsub;
+  return tree;
+}
+
+/* This function parse repetition operators like "*", "+", "{1,3}" etc.  */
+
+static bin_tree_t *
+parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
+             re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
+{
+  bin_tree_t *tree = NULL, *old_tree = NULL;
+  Idx i, start, end, start_idx = re_string_cur_idx (regexp);
+  re_token_t start_token = *token;
+
+  if (token->type == OP_OPEN_DUP_NUM)
+    {
+      end = 0;
+      start = fetch_number (regexp, token, syntax);
+      if (start == REG_MISSING)
+       {
+         if (token->type == CHARACTER && token->opr.c == ',')
+           start = 0; /* We treat "{,m}" as "{0,m}".  */
+         else
+           {
+             *err = REG_BADBR; /* <re>{} is invalid.  */
+             return NULL;
+           }
+       }
+      if (BE (start != REG_ERROR, 1))
+       {
+         /* We treat "{n}" as "{n,n}".  */
+         end = ((token->type == OP_CLOSE_DUP_NUM) ? start
+                : ((token->type == CHARACTER && token->opr.c == ',')
+                   ? fetch_number (regexp, token, syntax) : REG_ERROR));
+       }
+      if (BE (start == REG_ERROR || end == REG_ERROR, 0))
+       {
+         /* Invalid sequence.  */
+         if (BE (!(syntax & REG_INVALID_INTERVAL_ORD), 0))
+           {
+             if (token->type == END_OF_RE)
+               *err = REG_EBRACE;
+             else
+               *err = REG_BADBR;
+
+             return NULL;
+           }
+
+         /* If the syntax bit is set, rollback.  */
+         re_string_set_index (regexp, start_idx);
+         *token = start_token;
+         token->type = CHARACTER;
+         /* mb_partial and word_char bits should be already initialized by
+            peek_token.  */
+         return elem;
+       }
+
+      if (BE (end != REG_MISSING && start > end, 0))
+       {
+         /* First number greater than second.  */
+         *err = REG_BADBR;
+         return NULL;
+       }
+    }
+  else
+    {
+      start = (token->type == OP_DUP_PLUS) ? 1 : 0;
+      end = (token->type == OP_DUP_QUESTION) ? 1 : REG_MISSING;
+    }
+
+  fetch_token (token, regexp, syntax);
+
+  if (BE (elem == NULL, 0))
+    return NULL;
+  if (BE (start == 0 && end == 0, 0))
+    {
+      postorder (elem, free_tree, NULL);
+      return NULL;
+    }
+
+  /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}".  */
+  if (BE (start > 0, 0))
+    {
+      tree = elem;
+      for (i = 2; i <= start; ++i)
+       {
+         elem = duplicate_tree (elem, dfa);
+         tree = create_tree (dfa, tree, elem, CONCAT);
+         if (BE (elem == NULL || tree == NULL, 0))
+           goto parse_dup_op_espace;
+       }
+
+      if (start == end)
+       return tree;
+
+      /* Duplicate ELEM before it is marked optional.  */
+      elem = duplicate_tree (elem, dfa);
+      old_tree = tree;
+    }
+  else
+    old_tree = NULL;
+
+  if (elem->token.type == SUBEXP)
+    postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx);
+
+  tree = create_tree (dfa, elem, NULL,
+                     (end == REG_MISSING ? OP_DUP_ASTERISK : OP_ALT));
+  if (BE (tree == NULL, 0))
+    goto parse_dup_op_espace;
+
+  /* This loop is actually executed only when end != REG_MISSING,
+     to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?...  We have
+     already created the start+1-th copy.  */
+  if ((Idx) -1 < 0 || end != REG_MISSING)
+    for (i = start + 2; i <= end; ++i)
+      {
+       elem = duplicate_tree (elem, dfa);
+       tree = create_tree (dfa, tree, elem, CONCAT);
+       if (BE (elem == NULL || tree == NULL, 0))
+         goto parse_dup_op_espace;
+
+       tree = create_tree (dfa, tree, NULL, OP_ALT);
+       if (BE (tree == NULL, 0))
+         goto parse_dup_op_espace;
+      }
+
+  if (old_tree)
+    tree = create_tree (dfa, old_tree, tree, CONCAT);
+
+  return tree;
+
+ parse_dup_op_espace:
+  *err = REG_ESPACE;
+  return NULL;
+}
+
+/* Size of the names for collating symbol/equivalence_class/character_class.
+   I'm not sure, but maybe enough.  */
+#define BRACKET_NAME_BUF_SIZE 32
+
+#ifndef _LIBC
+  /* Local function for parse_bracket_exp only used in case of NOT _LIBC.
+     Build the range expression which starts from START_ELEM, and ends
+     at END_ELEM.  The result are written to MBCSET and SBCSET.
+     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
+     mbcset->range_ends, is a pointer argument sinse we may
+     update it.  */
+
+static reg_errcode_t
+build_range_exp (bitset sbcset,
+# ifdef RE_ENABLE_I18N
+                re_charset_t *mbcset, Idx *range_alloc,
+# endif
+                bracket_elem_t *start_elem, bracket_elem_t *end_elem)
+{
+  unsigned int start_ch, end_ch;
+  /* Equivalence Classes and Character Classes can't be a range start/end.  */
+  if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
+         || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
+         0))
+    return REG_ERANGE;
+
+  /* We can handle no multi character collating elements without libc
+     support.  */
+  if (BE ((start_elem->type == COLL_SYM
+          && strlen ((char *) start_elem->opr.name) > 1)
+         || (end_elem->type == COLL_SYM
+             && strlen ((char *) end_elem->opr.name) > 1), 0))
+    return REG_ECOLLATE;
+
+# ifdef RE_ENABLE_I18N
+  {
+    wchar_t wc;
+    wint_t start_wc, end_wc;
+    wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
+
+    start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
+               : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
+                  : 0));
+    end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
+             : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
+                : 0));
+    start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
+               ? __btowc (start_ch) : start_elem->opr.wch);
+    end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
+             ? __btowc (end_ch) : end_elem->opr.wch);
+    if (start_wc == WEOF || end_wc == WEOF)
+      return REG_ECOLLATE;
+    cmp_buf[0] = start_wc;
+    cmp_buf[4] = end_wc;
+    if (wcscoll (cmp_buf, cmp_buf + 4) > 0)
+      return REG_ERANGE;
+
+    /* Got valid collation sequence values, add them as a new entry.
+       However, for !_LIBC we have no collation elements: if the
+       character set is single byte, the single byte character set
+       that we build below suffices.  parse_bracket_exp passes
+       no MBCSET if dfa->mb_cur_max == 1.  */
+    if (mbcset)
+      {
+        /* Check the space of the arrays.  */
+        if (BE (*range_alloc == mbcset->nranges, 0))
+          {
+           /* There is not enough space, need realloc.  */
+           wchar_t *new_array_start, *new_array_end;
+           Idx new_nranges;
+
+           new_nranges = mbcset->nranges;
+           /* Use realloc since mbcset->range_starts and mbcset->range_ends
+              are NULL if *range_alloc == 0.  */
+           new_array_start = re_x2realloc (mbcset->range_starts, wchar_t,
+                                           &new_nranges);
+           new_array_end = re_realloc (mbcset->range_ends, wchar_t,
+                                       new_nranges);
+
+           if (BE (new_array_start == NULL || new_array_end == NULL, 0))
+             return REG_ESPACE;
+
+           mbcset->range_starts = new_array_start;
+           mbcset->range_ends = new_array_end;
+           *range_alloc = new_nranges;
+          }
+
+        mbcset->range_starts[mbcset->nranges] = start_wc;
+        mbcset->range_ends[mbcset->nranges++] = end_wc;
+      }
+
+    /* Build the table for single byte characters.  */
+    for (wc = 0; wc < SBC_MAX; ++wc)
+      {
+       cmp_buf[2] = wc;
+       if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
+           && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
+         bitset_set (sbcset, wc);
+      }
+  }
+# else /* not RE_ENABLE_I18N */
+  {
+    unsigned int ch;
+    start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
+               : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
+                  : 0));
+    end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
+             : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
+                : 0));
+    if (start_ch > end_ch)
+      return REG_ERANGE;
+    /* Build the table for single byte characters.  */
+    for (ch = 0; ch < SBC_MAX; ++ch)
+      if (start_ch <= ch  && ch <= end_ch)
+       bitset_set (sbcset, ch);
+  }
+# endif /* not RE_ENABLE_I18N */
+  return REG_NOERROR;
+}
+#endif /* not _LIBC */
+
+#ifndef _LIBC
+/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
+   Build the collating element which is represented by NAME.
+   The result are written to MBCSET and SBCSET.
+   COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
+   pointer argument since we may update it.  */
+
+static reg_errcode_t
+build_collating_symbol (bitset sbcset,
+# ifdef RE_ENABLE_I18N
+                       re_charset_t *mbcset, Idx *coll_sym_alloc,
+# endif
+                       const unsigned char *name)
+{
+  size_t name_len = strlen ((const char *) name);
+  if (BE (name_len != 1, 0))
+    return REG_ECOLLATE;
+  else
+    {
+      bitset_set (sbcset, name[0]);
+      return REG_NOERROR;
+    }
+}
+#endif /* not _LIBC */
+
+/* This function parse bracket expression like "[abc]", "[a-c]",
+   "[[.a-a.]]" etc.  */
+
+static bin_tree_t *
+parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
+                  reg_syntax_t syntax, reg_errcode_t *err)
+{
+#ifdef _LIBC
+  const unsigned char *collseqmb;
+  const char *collseqwc;
+  uint32_t nrules;
+  int32_t table_size;
+  const int32_t *symb_table;
+  const unsigned char *extra;
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     Seek the collating symbol entry correspondings to NAME.
+     Return the index of the symbol in the SYMB_TABLE.  */
+
+  auto inline int32_t
+  __attribute ((always_inline))
+  seek_collating_symbol_entry (const unsigned char *name, size_t name_len)
+    {
+      int32_t hash = elem_hash ((const char *) name, name_len);
+      int32_t elem = hash % table_size;
+      int32_t second = hash % (table_size - 2);
+      while (symb_table[2 * elem] != 0)
+       {
+         /* First compare the hashing value.  */
+         if (symb_table[2 * elem] == hash
+             /* Compare the length of the name.  */
+             && name_len == extra[symb_table[2 * elem + 1]]
+             /* Compare the name.  */
+             && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],
+                        name_len) == 0)
+           {
+             /* Yep, this is the entry.  */
+             break;
+           }
+
+         /* Next entry.  */
+         elem += second;
+       }
+      return elem;
+    }
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     Look up the collation sequence value of BR_ELEM.
+     Return the value if succeeded, UINT_MAX otherwise.  */
+
+  auto inline unsigned int
+  __attribute ((always_inline))
+  lookup_collation_sequence_value (bracket_elem_t *br_elem)
+    {
+      if (br_elem->type == SB_CHAR)
+       {
+         /*
+         if (MB_CUR_MAX == 1)
+         */
+         if (nrules == 0)
+           return collseqmb[br_elem->opr.ch];
+         else
+           {
+             wint_t wc = __btowc (br_elem->opr.ch);
+             return __collseq_table_lookup (collseqwc, wc);
+           }
+       }
+      else if (br_elem->type == MB_CHAR)
+       {
+         return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
+       }
+      else if (br_elem->type == COLL_SYM)
+       {
+         size_t sym_name_len = strlen ((char *) br_elem->opr.name);
+         if (nrules != 0)
+           {
+             int32_t elem, idx;
+             elem = seek_collating_symbol_entry (br_elem->opr.name,
+                                                 sym_name_len);
+             if (symb_table[2 * elem] != 0)
+               {
+                 /* We found the entry.  */
+                 idx = symb_table[2 * elem + 1];
+                 /* Skip the name of collating element name.  */
+                 idx += 1 + extra[idx];
+                 /* Skip the byte sequence of the collating element.  */
+                 idx += 1 + extra[idx];
+                 /* Adjust for the alignment.  */
+                 idx = (idx + 3) & ~3;
+                 /* Skip the multibyte collation sequence value.  */
+                 idx += sizeof (unsigned int);
+                 /* Skip the wide char sequence of the collating element.  */
+                 idx += sizeof (unsigned int) *
+                   (1 + *(unsigned int *) (extra + idx));
+                 /* Return the collation sequence value.  */
+                 return *(unsigned int *) (extra + idx);
+               }
+             else if (symb_table[2 * elem] == 0 && sym_name_len == 1)
+               {
+                 /* No valid character.  Match it as a single byte
+                    character.  */
+                 return collseqmb[br_elem->opr.name[0]];
+               }
+           }
+         else if (sym_name_len == 1)
+           return collseqmb[br_elem->opr.name[0]];
+       }
+      return UINT_MAX;
+    }
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     Build the range expression which starts from START_ELEM, and ends
+     at END_ELEM.  The result are written to MBCSET and SBCSET.
+     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
+     mbcset->range_ends, is a pointer argument sinse we may
+     update it.  */
+
+  auto inline reg_errcode_t
+  __attribute ((always_inline))
+  build_range_exp (bitset sbcset, re_charset_t *mbcset,
+                  Idx *range_alloc,
+                  bracket_elem_t *start_elem, bracket_elem_t *end_elem)
+    {
+      unsigned int ch;
+      uint32_t start_collseq;
+      uint32_t end_collseq;
+
+      /* Equivalence Classes and Character Classes can't be a range
+        start/end.  */
+      if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
+             || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
+             0))
+       return REG_ERANGE;
+
+      start_collseq = lookup_collation_sequence_value (start_elem);
+      end_collseq = lookup_collation_sequence_value (end_elem);
+      /* Check start/end collation sequence values.  */
+      if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))
+       return REG_ECOLLATE;
+      if (BE ((syntax & REG_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))
+       return REG_ERANGE;
+
+      /* Got valid collation sequence values, add them as a new entry.
+        However, if we have no collation elements, and the character set
+        is single byte, the single byte character set that we
+        build below suffices. */
+      if (nrules > 0 || dfa->mb_cur_max > 1)
+       {
+          /* Check the space of the arrays.  */
+          if (BE (*range_alloc == mbcset->nranges, 0))
+           {
+             /* There is not enough space, need realloc.  */
+             uint32_t *new_array_start;
+             uint32_t *new_array_end;
+             Idx new_nranges;
+
+             new_nranges = mbcset->nranges;
+             new_array_start = re_x2realloc (mbcset->range_starts, uint32_t,
+                                             &new_nranges);
+             new_array_end = re_realloc (mbcset->range_ends, uint32_t,
+                                         new_nranges);
+
+             if (BE (new_array_start == NULL || new_array_end == NULL, 0))
+               return REG_ESPACE;
+
+             mbcset->range_starts = new_array_start;
+             mbcset->range_ends = new_array_end;
+             *range_alloc = new_nranges;
+           }
+
+          mbcset->range_starts[mbcset->nranges] = start_collseq;
+          mbcset->range_ends[mbcset->nranges++] = end_collseq;
+       }
+
+      /* Build the table for single byte characters.  */
+      for (ch = 0; ch < SBC_MAX; ch++)
+       {
+         uint32_t ch_collseq;
+         /*
+         if (MB_CUR_MAX == 1)
+         */
+         if (nrules == 0)
+           ch_collseq = collseqmb[ch];
+         else
+           ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
+         if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
+           bitset_set (sbcset, ch);
+       }
+      return REG_NOERROR;
+    }
+
+  /* Local function for parse_bracket_exp used in _LIBC environement.
+     Build the collating element which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
+     pointer argument sinse we may update it.  */
+
+  auto inline reg_errcode_t
+  __attribute ((always_inline))
+  build_collating_symbol (bitset sbcset, re_charset_t *mbcset,
+                         Idx *coll_sym_alloc, const unsigned char *name)
+    {
+      int32_t elem, idx;
+      size_t name_len = strlen ((const char *) name);
+      if (nrules != 0)
+       {
+         elem = seek_collating_symbol_entry (name, name_len);
+         if (symb_table[2 * elem] != 0)
+           {
+             /* We found the entry.  */
+             idx = symb_table[2 * elem + 1];
+             /* Skip the name of collating element name.  */
+             idx += 1 + extra[idx];
+           }
+         else if (symb_table[2 * elem] == 0 && name_len == 1)
+           {
+             /* No valid character, treat it as a normal
+                character.  */
+             bitset_set (sbcset, name[0]);
+             return REG_NOERROR;
+           }
+         else
+           return REG_ECOLLATE;
+
+         /* Got valid collation sequence, add it as a new entry.  */
+         /* Check the space of the arrays.  */
+         if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0))
+           {
+             /* Not enough, realloc it.  */
+             Idx new_coll_sym_alloc = mbcset->ncoll_syms;
+             /* Use realloc since mbcset->coll_syms is NULL
+                if *alloc == 0.  */
+             int32_t *new_coll_syms = re_x2realloc (mbcset->coll_syms, int32_t,
+                                                    &new_coll_sym_alloc);
+             if (BE (new_coll_syms == NULL, 0))
+               return REG_ESPACE;
+             mbcset->coll_syms = new_coll_syms;
+             *coll_sym_alloc = new_coll_sym_alloc;
+           }
+         mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
+         return REG_NOERROR;
+       }
+      else
+       {
+         if (BE (name_len != 1, 0))
+           return REG_ECOLLATE;
+         else
+           {
+             bitset_set (sbcset, name[0]);
+             return REG_NOERROR;
+           }
+       }
+    }
+#endif
+
+  re_token_t br_token;
+  re_bitset_ptr_t sbcset;
+#ifdef RE_ENABLE_I18N
+  re_charset_t *mbcset;
+  Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
+  Idx equiv_class_alloc = 0, char_class_alloc = 0;
+#endif /* not RE_ENABLE_I18N */
+  bool non_match = false;
+  bin_tree_t *work_tree;
+  int token_len;
+  bool first_round = true;
+#ifdef _LIBC
+  collseqmb = (const unsigned char *)
+    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules)
+    {
+      /*
+      if (MB_CUR_MAX > 1)
+      */
+       collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+      table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
+      symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+                                                 _NL_COLLATE_SYMB_TABLEMB);
+      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+                                                  _NL_COLLATE_SYMB_EXTRAMB);
+    }
+#endif
+  sbcset = re_calloc (bitset_word, BITSET_WORDS);
+#ifdef RE_ENABLE_I18N
+  mbcset = re_calloc (re_charset_t, 1);
+#endif /* RE_ENABLE_I18N */
+#ifdef RE_ENABLE_I18N
+  if (BE (sbcset == NULL || mbcset == NULL, 0))
+#else
+  if (BE (sbcset == NULL, 0))
+#endif /* RE_ENABLE_I18N */
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  token_len = peek_token_bracket (token, regexp, syntax);
+  if (BE (token->type == END_OF_RE, 0))
+    {
+      *err = REG_BADPAT;
+      goto parse_bracket_exp_free_return;
+    }
+  if (token->type == OP_NON_MATCH_LIST)
+    {
+#ifdef RE_ENABLE_I18N
+      mbcset->non_match = 1;
+#endif /* not RE_ENABLE_I18N */
+      non_match = true;
+      if (syntax & REG_HAT_LISTS_NOT_NEWLINE)
+       bitset_set (sbcset, '\0');
+      re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+      token_len = peek_token_bracket (token, regexp, syntax);
+      if (BE (token->type == END_OF_RE, 0))
+       {
+         *err = REG_BADPAT;
+         goto parse_bracket_exp_free_return;
+       }
+    }
+
+  /* We treat the first ']' as a normal character.  */
+  if (token->type == OP_CLOSE_BRACKET)
+    token->type = CHARACTER;
+
+  while (1)
+    {
+      bracket_elem_t start_elem, end_elem;
+      unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
+      unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
+      reg_errcode_t ret;
+      int token_len2 = 0;
+      bool is_range_exp = false;
+      re_token_t token2;
+
+      start_elem.opr.name = start_name_buf;
+      ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
+                                  syntax, first_round);
+      if (BE (ret != REG_NOERROR, 0))
+       {
+         *err = ret;
+         goto parse_bracket_exp_free_return;
+       }
+      first_round = false;
+
+      /* Get information about the next token.  We need it in any case.  */
+      token_len = peek_token_bracket (token, regexp, syntax);
+
+      /* Do not check for ranges if we know they are not allowed.  */
+      if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)
+       {
+         if (BE (token->type == END_OF_RE, 0))
+           {
+             *err = REG_EBRACK;
+             goto parse_bracket_exp_free_return;
+           }
+         if (token->type == OP_CHARSET_RANGE)
+           {
+             re_string_skip_bytes (regexp, token_len); /* Skip '-'.  */
+             token_len2 = peek_token_bracket (&token2, regexp, syntax);
+             if (BE (token2.type == END_OF_RE, 0))
+               {
+                 *err = REG_EBRACK;
+                 goto parse_bracket_exp_free_return;
+               }
+             if (token2.type == OP_CLOSE_BRACKET)
+               {
+                 /* We treat the last '-' as a normal character.  */
+                 re_string_skip_bytes (regexp, -token_len);
+                 token->type = CHARACTER;
+               }
+             else
+               is_range_exp = true;
+           }
+       }
+
+      if (is_range_exp == true)
+       {
+         end_elem.opr.name = end_name_buf;
+         ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
+                                      dfa, syntax, true);
+         if (BE (ret != REG_NOERROR, 0))
+           {
+             *err = ret;
+             goto parse_bracket_exp_free_return;
+           }
+
+         token_len = peek_token_bracket (token, regexp, syntax);
+
+#ifdef _LIBC
+         *err = build_range_exp (sbcset, mbcset, &range_alloc,
+                                 &start_elem, &end_elem);
+#else
+# ifdef RE_ENABLE_I18N
+         *err = build_range_exp (sbcset,
+                                 dfa->mb_cur_max > 1 ? mbcset : NULL,
+                                 &range_alloc, &start_elem, &end_elem);
+# else
+         *err = build_range_exp (sbcset, &start_elem, &end_elem);
+# endif
+#endif /* RE_ENABLE_I18N */
+         if (BE (*err != REG_NOERROR, 0))
+           goto parse_bracket_exp_free_return;
+       }
+      else
+       {
+         switch (start_elem.type)
+           {
+           case SB_CHAR:
+             bitset_set (sbcset, start_elem.opr.ch);
+             break;
+#ifdef RE_ENABLE_I18N
+           case MB_CHAR:
+             /* Check whether the array has enough space.  */
+             if (BE (mbchar_alloc == mbcset->nmbchars, 0))
+               {
+                 wchar_t *new_mbchars;
+                 /* Not enough, realloc it.  */
+                 mbchar_alloc = mbcset->nmbchars;
+                 /* Use realloc since array is NULL if *alloc == 0.  */
+                 new_mbchars = re_x2realloc (mbcset->mbchars, wchar_t,
+                                             &mbchar_alloc);
+                 if (BE (new_mbchars == NULL, 0))
+                   goto parse_bracket_exp_espace;
+                 mbcset->mbchars = new_mbchars;
+               }
+             mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
+             break;
+#endif /* RE_ENABLE_I18N */
+           case EQUIV_CLASS:
+             *err = build_equiv_class (sbcset,
+#ifdef RE_ENABLE_I18N
+                                       mbcset, &equiv_class_alloc,
+#endif /* RE_ENABLE_I18N */
+                                       start_elem.opr.name);
+             if (BE (*err != REG_NOERROR, 0))
+               goto parse_bracket_exp_free_return;
+             break;
+           case COLL_SYM:
+             *err = build_collating_symbol (sbcset,
+#ifdef RE_ENABLE_I18N
+                                            mbcset, &coll_sym_alloc,
+#endif /* RE_ENABLE_I18N */
+                                            start_elem.opr.name);
+             if (BE (*err != REG_NOERROR, 0))
+               goto parse_bracket_exp_free_return;
+             break;
+           case CHAR_CLASS:
+             *err = build_charclass (regexp->trans, sbcset,
+#ifdef RE_ENABLE_I18N
+                                     mbcset, &char_class_alloc,
+#endif /* RE_ENABLE_I18N */
+                                     start_elem.opr.name, syntax);
+             if (BE (*err != REG_NOERROR, 0))
+              goto parse_bracket_exp_free_return;
+             break;
+           default:
+             assert (0);
+             break;
+           }
+       }
+      if (BE (token->type == END_OF_RE, 0))
+       {
+         *err = REG_EBRACK;
+         goto parse_bracket_exp_free_return;
+       }
+      if (token->type == OP_CLOSE_BRACKET)
+       break;
+    }
+
+  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+
+  /* If it is non-matching list.  */
+  if (non_match)
+    bitset_not (sbcset);
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure only single byte characters are set.  */
+  if (dfa->mb_cur_max > 1)
+    bitset_mask (sbcset, dfa->sb_char);
+
+  if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
+      || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
+                                                    || mbcset->non_match)))
+    {
+      bin_tree_t *mbc_tree;
+      int sbc_idx;
+      /* Build a tree for complex bracket.  */
+      dfa->has_mb_node = 1;
+      br_token.type = COMPLEX_BRACKET;
+      br_token.opr.mbcset = mbcset;
+      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (mbc_tree == NULL, 0))
+       goto parse_bracket_exp_espace;
+      for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)
+       if (sbcset[sbc_idx])
+         break;
+      /* If there are no bits set in sbcset, there is no point
+        of having both SIMPLE_BRACKET and COMPLEX_BRACKET.  */
+      if (sbc_idx < BITSET_WORDS)
+       {
+          /* Build a tree for simple bracket.  */
+          br_token.type = SIMPLE_BRACKET;
+          br_token.opr.sbcset = sbcset;
+          work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+          if (BE (work_tree == NULL, 0))
+            goto parse_bracket_exp_espace;
+
+          /* Then join them by ALT node.  */
+          work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
+          if (BE (work_tree == NULL, 0))
+            goto parse_bracket_exp_espace;
+       }
+      else
+       {
+         re_free (sbcset);
+         work_tree = mbc_tree;
+       }
+    }
+  else
+#endif /* not RE_ENABLE_I18N */
+    {
+#ifdef RE_ENABLE_I18N
+      free_charset (mbcset);
+#endif
+      /* Build a tree for simple bracket.  */
+      br_token.type = SIMPLE_BRACKET;
+      br_token.opr.sbcset = sbcset;
+      work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (work_tree == NULL, 0))
+        goto parse_bracket_exp_espace;
+    }
+  return work_tree;
+
+ parse_bracket_exp_espace:
+  *err = REG_ESPACE;
+ parse_bracket_exp_free_return:
+  re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+  free_charset (mbcset);
+#endif /* RE_ENABLE_I18N */
+  return NULL;
+}
+
+/* Parse an element in the bracket expression.  */
+
+static reg_errcode_t
+parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
+                      re_token_t *token, int token_len, re_dfa_t *dfa,
+                      reg_syntax_t syntax, bool accept_hyphen)
+{
+#ifdef RE_ENABLE_I18N
+  int cur_char_size;
+  cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
+  if (cur_char_size > 1)
+    {
+      elem->type = MB_CHAR;
+      elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
+      re_string_skip_bytes (regexp, cur_char_size);
+      return REG_NOERROR;
+    }
+#endif /* RE_ENABLE_I18N */
+  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
+  if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
+      || token->type == OP_OPEN_EQUIV_CLASS)
+    return parse_bracket_symbol (elem, regexp, token);
+  if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen)
+    {
+      /* A '-' must only appear as anything but a range indicator before
+        the closing bracket.  Everything else is an error.  */
+      re_token_t token2;
+      (void) peek_token_bracket (&token2, regexp, syntax);
+      if (token2.type != OP_CLOSE_BRACKET)
+       /* The actual error value is not standardized since this whole
+          case is undefined.  But ERANGE makes good sense.  */
+       return REG_ERANGE;
+    }
+  elem->type = SB_CHAR;
+  elem->opr.ch = token->opr.c;
+  return REG_NOERROR;
+}
+
+/* Parse a bracket symbol in the bracket expression.  Bracket symbols are
+   such as [:<character_class>:], [.<collating_element>.], and
+   [=<equivalent_class>=].  */
+
+static reg_errcode_t
+parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
+                     re_token_t *token)
+{
+  unsigned char ch, delim = token->opr.c;
+  int i = 0;
+  if (re_string_eoi(regexp))
+    return REG_EBRACK;
+  for (;; ++i)
+    {
+      if (i >= BRACKET_NAME_BUF_SIZE)
+       return REG_EBRACK;
+      if (token->type == OP_OPEN_CHAR_CLASS)
+       ch = re_string_fetch_byte_case (regexp);
+      else
+       ch = re_string_fetch_byte (regexp);
+      if (re_string_eoi(regexp))
+       return REG_EBRACK;
+      if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
+       break;
+      elem->opr.name[i] = ch;
+    }
+  re_string_skip_bytes (regexp, 1);
+  elem->opr.name[i] = '\0';
+  switch (token->type)
+    {
+    case OP_OPEN_COLL_ELEM:
+      elem->type = COLL_SYM;
+      break;
+    case OP_OPEN_EQUIV_CLASS:
+      elem->type = EQUIV_CLASS;
+      break;
+    case OP_OPEN_CHAR_CLASS:
+      elem->type = CHAR_CLASS;
+      break;
+    default:
+      break;
+    }
+  return REG_NOERROR;
+}
+
+  /* Helper function for parse_bracket_exp.
+     Build the equivalence class which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
+     is a pointer argument sinse we may update it.  */
+
+static reg_errcode_t
+build_equiv_class (bitset sbcset,
+#ifdef RE_ENABLE_I18N
+                  re_charset_t *mbcset, Idx *equiv_class_alloc,
+#endif
+                  const unsigned char *name)
+{
+#if defined _LIBC
+  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+  if (nrules != 0)
+    {
+      const int32_t *table, *indirect;
+      const unsigned char *weights, *extra, *cp;
+      unsigned char char_buf[2];
+      int32_t idx1, idx2;
+      unsigned int ch;
+      size_t len;
+      /* This #include defines a local function!  */
+# include <locale/weight.h>
+      /* Calculate the index for equivalence class.  */
+      cp = name;
+      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+      weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+                                              _NL_COLLATE_WEIGHTMB);
+      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
+                                                  _NL_COLLATE_EXTRAMB);
+      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
+                                               _NL_COLLATE_INDIRECTMB);
+      idx1 = findidx (&cp);
+      if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0))
+       /* This isn't a valid character.  */
+       return REG_ECOLLATE;
+
+      /* Build single byte matcing table for this equivalence class.  */
+      char_buf[1] = (unsigned char) '\0';
+      len = weights[idx1];
+      for (ch = 0; ch < SBC_MAX; ++ch)
+       {
+         char_buf[0] = ch;
+         cp = char_buf;
+         idx2 = findidx (&cp);
+/*
+         idx2 = table[ch];
+*/
+         if (idx2 == 0)
+           /* This isn't a valid character.  */
+           continue;
+         if (len == weights[idx2])
+           {
+             int cnt = 0;
+             while (cnt <= len &&
+                    weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt])
+               ++cnt;
+
+             if (cnt > len)
+               bitset_set (sbcset, ch);
+           }
+       }
+      /* Check whether the array has enough space.  */
+      if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))
+       {
+         /* Not enough, realloc it.  */
+         Idx new_equiv_class_alloc = mbcset->nequiv_classes;
+         /* Use realloc since the array is NULL if *alloc == 0.  */
+         int32_t *new_equiv_classes = re_x2realloc (mbcset->equiv_classes,
+                                                    int32_t,
+                                                    &new_equiv_class_alloc);
+         if (BE (new_equiv_classes == NULL, 0))
+           return REG_ESPACE;
+         mbcset->equiv_classes = new_equiv_classes;
+         *equiv_class_alloc = new_equiv_class_alloc;
+       }
+      mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
+    }
+  else
+#endif /* _LIBC */
+    {
+      if (BE (strlen ((const char *) name) != 1, 0))
+       return REG_ECOLLATE;
+      bitset_set (sbcset, *name);
+    }
+  return REG_NOERROR;
+}
+
+  /* Helper function for parse_bracket_exp.
+     Build the character class which is represented by NAME.
+     The result are written to MBCSET and SBCSET.
+     CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
+     is a pointer argument sinse we may update it.  */
+
+static reg_errcode_t
+build_charclass (unsigned REG_TRANSLATE_TYPE trans, bitset sbcset,
+#ifdef RE_ENABLE_I18N
+                re_charset_t *mbcset, Idx *char_class_alloc,
+#endif
+                const unsigned char *class_name, reg_syntax_t syntax)
+{
+  int i;
+  const char *name = (const char *) class_name;
+
+  /* In case of REG_ICASE "upper" and "lower" match the both of
+     upper and lower cases.  */
+  if ((syntax & REG_IGNORE_CASE)
+      && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
+    name = "alpha";
+
+#ifdef RE_ENABLE_I18N
+  /* Check the space of the arrays.  */
+  if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
+    {
+      /* Not enough, realloc it.  */
+      Idx new_char_class_alloc = mbcset->nchar_classes;
+      /* Use realloc since array is NULL if *alloc == 0.  */
+      wctype_t *new_char_classes = re_x2realloc (mbcset->char_classes, wctype_t,
+                                                &new_char_class_alloc);
+      if (BE (new_char_classes == NULL, 0))
+       return REG_ESPACE;
+      mbcset->char_classes = new_char_classes;
+      *char_class_alloc = new_char_class_alloc;
+    }
+  mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
+#endif /* RE_ENABLE_I18N */
+
+#define BUILD_CHARCLASS_LOOP(ctype_func)       \
+    for (i = 0; i < SBC_MAX; ++i)              \
+      {                                                \
+       if (ctype_func (i))                     \
+         {                                     \
+           int ch = trans ? trans[i] : i;      \
+           bitset_set (sbcset, ch);            \
+         }                                     \
+      }
+
+  if (strcmp (name, "alnum") == 0)
+    BUILD_CHARCLASS_LOOP (isalnum)
+  else if (strcmp (name, "cntrl") == 0)
+    BUILD_CHARCLASS_LOOP (iscntrl)
+  else if (strcmp (name, "lower") == 0)
+    BUILD_CHARCLASS_LOOP (islower)
+  else if (strcmp (name, "space") == 0)
+    BUILD_CHARCLASS_LOOP (isspace)
+  else if (strcmp (name, "alpha") == 0)
+    BUILD_CHARCLASS_LOOP (isalpha)
+  else if (strcmp (name, "digit") == 0)
+    BUILD_CHARCLASS_LOOP (isdigit)
+  else if (strcmp (name, "print") == 0)
+    BUILD_CHARCLASS_LOOP (isprint)
+  else if (strcmp (name, "upper") == 0)
+    BUILD_CHARCLASS_LOOP (isupper)
+  else if (strcmp (name, "blank") == 0)
+    BUILD_CHARCLASS_LOOP (isblank)
+  else if (strcmp (name, "graph") == 0)
+    BUILD_CHARCLASS_LOOP (isgraph)
+  else if (strcmp (name, "punct") == 0)
+    BUILD_CHARCLASS_LOOP (ispunct)
+  else if (strcmp (name, "xdigit") == 0)
+    BUILD_CHARCLASS_LOOP (isxdigit)
+  else
+    return REG_ECTYPE;
+
+  return REG_NOERROR;
+}
+
+static bin_tree_t *
+build_charclass_op (re_dfa_t *dfa, unsigned REG_TRANSLATE_TYPE trans,
+                   const unsigned char *class_name,
+                   const unsigned char *extra,
+                   bool non_match, reg_errcode_t *err)
+{
+  re_bitset_ptr_t sbcset;
+#ifdef RE_ENABLE_I18N
+  re_charset_t *mbcset;
+  Idx alloc = 0;
+#endif /* not RE_ENABLE_I18N */
+  reg_errcode_t ret;
+  re_token_t br_token;
+  bin_tree_t *tree;
+
+  sbcset = re_calloc (bitset_word, BITSET_WORDS);
+#ifdef RE_ENABLE_I18N
+  mbcset = re_calloc (re_charset_t, 1);
+#endif /* RE_ENABLE_I18N */
+
+#ifdef RE_ENABLE_I18N
+  if (BE (sbcset == NULL || mbcset == NULL, 0))
+#else /* not RE_ENABLE_I18N */
+  if (BE (sbcset == NULL, 0))
+#endif /* not RE_ENABLE_I18N */
+    {
+      *err = REG_ESPACE;
+      return NULL;
+    }
+
+  if (non_match)
+    {
+#ifdef RE_ENABLE_I18N
+      /*
+      if (syntax & REG_HAT_LISTS_NOT_NEWLINE)
+       bitset_set(cset->sbcset, '\0');
+      */
+      mbcset->non_match = 1;
+#endif /* not RE_ENABLE_I18N */
+    }
+
+  /* We don't care the syntax in this case.  */
+  ret = build_charclass (trans, sbcset,
+#ifdef RE_ENABLE_I18N
+                        mbcset, &alloc,
+#endif /* RE_ENABLE_I18N */
+                        class_name, 0);
+
+  if (BE (ret != REG_NOERROR, 0))
+    {
+      re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+      free_charset (mbcset);
+#endif /* RE_ENABLE_I18N */
+      *err = ret;
+      return NULL;
+    }
+  /* \w match '_' also.  */
+  for (; *extra; extra++)
+    bitset_set (sbcset, *extra);
+
+  /* If it is non-matching list.  */
+  if (non_match)
+    bitset_not (sbcset);
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure only single byte characters are set.  */
+  if (dfa->mb_cur_max > 1)
+    bitset_mask (sbcset, dfa->sb_char);
+#endif
+
+  /* Build a tree for simple bracket.  */
+  br_token.type = SIMPLE_BRACKET;
+  br_token.opr.sbcset = sbcset;
+  tree = create_token_tree (dfa, NULL, NULL, &br_token);
+  if (BE (tree == NULL, 0))
+    goto build_word_op_espace;
+
+#ifdef RE_ENABLE_I18N
+  if (dfa->mb_cur_max > 1)
+    {
+      bin_tree_t *mbc_tree;
+      /* Build a tree for complex bracket.  */
+      br_token.type = COMPLEX_BRACKET;
+      br_token.opr.mbcset = mbcset;
+      dfa->has_mb_node = 1;
+      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
+      if (BE (mbc_tree == NULL, 0))
+       goto build_word_op_espace;
+      /* Then join them by ALT node.  */
+      tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
+      if (BE (mbc_tree != NULL, 1))
+       return tree;
+    }
+  else
+    {
+      free_charset (mbcset);
+      return tree;
+    }
+#else /* not RE_ENABLE_I18N */
+  return tree;
+#endif /* not RE_ENABLE_I18N */
+
+ build_word_op_espace:
+  re_free (sbcset);
+#ifdef RE_ENABLE_I18N
+  free_charset (mbcset);
+#endif /* RE_ENABLE_I18N */
+  *err = REG_ESPACE;
+  return NULL;
+}
+
+/* This is intended for the expressions like "a{1,3}".
+   Fetch a number from `input', and return the number.
+   Return REG_MISSING if the number field is empty like "{,1}".
+   Return REG_ERROR if an error occurred.  */
+
+static Idx
+fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
+{
+  Idx num = REG_MISSING;
+  unsigned char c;
+  while (1)
+    {
+      fetch_token (token, input, syntax);
+      c = token->opr.c;
+      if (BE (token->type == END_OF_RE, 0))
+       return REG_ERROR;
+      if (token->type == OP_CLOSE_DUP_NUM || c == ',')
+       break;
+      num = ((token->type != CHARACTER || c < '0' || '9' < c
+             || num == REG_ERROR)
+            ? REG_ERROR
+            : ((num == REG_MISSING) ? c - '0' : num * 10 + c - '0'));
+      num = (num > REG_DUP_MAX) ? REG_ERROR : num;
+    }
+  return num;
+}
+\f
+#ifdef RE_ENABLE_I18N
+static void
+free_charset (re_charset_t *cset)
+{
+  re_free (cset->mbchars);
+# ifdef _LIBC
+  re_free (cset->coll_syms);
+  re_free (cset->equiv_classes);
+  re_free (cset->range_starts);
+  re_free (cset->range_ends);
+# endif
+  re_free (cset->char_classes);
+  re_free (cset);
+}
+#endif /* RE_ENABLE_I18N */
+\f
+/* Functions for binary tree operation.  */
+
+/* Create a tree node.  */
+
+static bin_tree_t *
+create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
+            re_token_type_t type)
+{
+  re_token_t t;
+  t.type = type;
+  return create_token_tree (dfa, left, right, &t);
+}
+
+static bin_tree_t *
+create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
+                  const re_token_t *token)
+{
+  bin_tree_t *tree;
+  if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0))
+    {
+      bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);
+
+      if (storage == NULL)
+       return NULL;
+      storage->next = dfa->str_tree_storage;
+      dfa->str_tree_storage = storage;
+      dfa->str_tree_storage_idx = 0;
+    }
+  tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];
+
+  tree->parent = NULL;
+  tree->left = left;
+  tree->right = right;
+  tree->token = *token;
+  tree->token.duplicated = 0;
+  tree->token.opt_subexp = 0;
+  tree->first = NULL;
+  tree->next = NULL;
+  tree->node_idx = REG_MISSING;
+
+  if (left != NULL)
+    left->parent = tree;
+  if (right != NULL)
+    right->parent = tree;
+  return tree;
+}
+
+/* Mark the tree SRC as an optional subexpression.
+   To be called from preorder or postorder.  */
+
+static reg_errcode_t
+mark_opt_subexp (void *extra, bin_tree_t *node)
+{
+  Idx idx = (Idx) (long) extra;
+  if (node->token.type == SUBEXP && node->token.opr.idx == idx)
+    node->token.opt_subexp = 1;
+
+  return REG_NOERROR;
+}
+
+/* Free the allocated memory inside NODE. */
+
+static void
+free_token (re_token_t *node)
+{
+#ifdef RE_ENABLE_I18N
+  if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
+    free_charset (node->opr.mbcset);
+  else
+#endif /* RE_ENABLE_I18N */
+    if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
+      re_free (node->opr.sbcset);
+}
+
+/* Worker function for tree walking.  Free the allocated memory inside NODE
+   and its children. */
+
+static reg_errcode_t
+free_tree (void *extra, bin_tree_t *node)
+{
+  free_token (&node->token);
+  return REG_NOERROR;
+}
+
+
+/* Duplicate the node SRC, and return new node.  This is a preorder
+   visit similar to the one implemented by the generic visitor, but
+   we need more infrastructure to maintain two parallel trees --- so,
+   it's easier to duplicate.  */
+
+static bin_tree_t *
+duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)
+{
+  const bin_tree_t *node;
+  bin_tree_t *dup_root;
+  bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
+
+  for (node = root; ; )
+    {
+      /* Create a new tree and link it back to the current parent.  */
+      *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
+      if (*p_new == NULL)
+       return NULL;
+      (*p_new)->parent = dup_node;
+      (*p_new)->token.duplicated = 1;
+      dup_node = *p_new;
+
+      /* Go to the left node, or up and to the right.  */
+      if (node->left)
+       {
+         node = node->left;
+         p_new = &dup_node->left;
+       }
+      else
+       {
+         const bin_tree_t *prev = NULL;
+         while (node->right == prev || node->right == NULL)
+           {
+             prev = node;
+             node = node->parent;
+             dup_node = dup_node->parent;
+             if (!node)
+               return dup_root;
+           }
+         node = node->right;
+         p_new = &dup_node->right;
+       }
+    }
+}
diff --git a/contrib/cvs-1.12/lib/regex.c b/contrib/cvs-1.12/lib/regex.c
new file mode 100644 (file)
index 0000000..82e76c0
--- /dev/null
@@ -0,0 +1,68 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+/* We have to keep the namespace clean.  */
+# define regfree(preg) __regfree (preg)
+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
+# define regerror(errcode, preg, errbuf, errbuf_size) \
+       __regerror(errcode, preg, errbuf, errbuf_size)
+# define re_set_registers(bu, re, nu, st, en) \
+       __re_set_registers (bu, re, nu, st, en)
+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
+       __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+# define re_match(bufp, string, size, pos, regs) \
+       __re_match (bufp, string, size, pos, regs)
+# define re_search(bufp, string, size, startpos, range, regs) \
+       __re_search (bufp, string, size, startpos, range, regs)
+# define re_compile_pattern(pattern, length, bufp) \
+       __re_compile_pattern (pattern, length, bufp)
+# define re_set_syntax(syntax) __re_set_syntax (syntax)
+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
+       __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
+
+# include "../locale/localeinfo.h"
+#endif
+
+/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
+   GNU regex allows.  Include it before <regex.h>, which correctly
+   #undefs RE_DUP_MAX and sets it to the right value.  */
+#include <limits.h>
+
+#include <regex.h>
+#include "regex_internal.h"
+
+#include "regex_internal.c"
+#include "regcomp.c"
+#include "regexec.c"
+
+/* Binary backward compatibility.  */
+#if _LIBC
+# include <shlib-compat.h>
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
+link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
+int re_max_failures = 2000;
+# endif
+#endif
diff --git a/contrib/cvs-1.12/lib/regex_internal.c b/contrib/cvs-1.12/lib/regex_internal.c
new file mode 100644 (file)
index 0000000..ad618cf
--- /dev/null
@@ -0,0 +1,1656 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+static void re_string_construct_common (const char *str, Idx len,
+                                       re_string_t *pstr,
+                                       REG_TRANSLATE_TYPE trans, bool icase,
+                                       const re_dfa_t *dfa) internal_function;
+static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
+                                         const re_node_set *nodes,
+                                         re_hashval_t hash) internal_function;
+static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
+                                         const re_node_set *nodes,
+                                         unsigned int context,
+                                         re_hashval_t hash) internal_function;
+\f
+/* Functions for string operation.  */
+
+/* This function allocate the buffers.  It is necessary to call
+   re_string_reconstruct before using the object.  */
+
+static reg_errcode_t
+internal_function
+re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len,
+                   REG_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa)
+{
+  reg_errcode_t ret;
+  Idx init_buf_len;
+
+  /* Ensure at least one character fits into the buffers.  */
+  if (init_len < dfa->mb_cur_max)
+    init_len = dfa->mb_cur_max;
+  init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
+  re_string_construct_common (str, len, pstr, trans, icase, dfa);
+
+  ret = re_string_realloc_buffers (pstr, init_buf_len);
+  if (BE (ret != REG_NOERROR, 0))
+    return ret;
+
+  pstr->word_char = dfa->word_char;
+  pstr->word_ops_used = dfa->word_ops_used;
+  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+  pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
+  pstr->valid_raw_len = pstr->valid_len;
+  return REG_NOERROR;
+}
+
+/* This function allocate the buffers, and initialize them.  */
+
+static reg_errcode_t
+internal_function
+re_string_construct (re_string_t *pstr, const char *str, Idx len,
+                    REG_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa)
+{
+  reg_errcode_t ret;
+  memset (pstr, '\0', sizeof (re_string_t));
+  re_string_construct_common (str, len, pstr, trans, icase, dfa);
+
+  if (len > 0)
+    {
+      ret = re_string_realloc_buffers (pstr, len + 1);
+      if (BE (ret != REG_NOERROR, 0))
+       return ret;
+    }
+  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
+
+  if (icase)
+    {
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+       {
+         while (1)
+           {
+             ret = build_wcs_upper_buffer (pstr);
+             if (BE (ret != REG_NOERROR, 0))
+               return ret;
+             if (pstr->valid_raw_len >= len)
+               break;
+             if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
+               break;
+             ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
+             if (BE (ret != REG_NOERROR, 0))
+               return ret;
+           }
+       }
+      else
+#endif /* RE_ENABLE_I18N  */
+       build_upper_buffer (pstr);
+    }
+  else
+    {
+#ifdef RE_ENABLE_I18N
+      if (dfa->mb_cur_max > 1)
+       build_wcs_buffer (pstr);
+      else
+#endif /* RE_ENABLE_I18N  */
+       {
+         if (trans != NULL)
+           re_string_translate_buffer (pstr);
+         else
+           {
+             pstr->valid_len = pstr->bufs_len;
+             pstr->valid_raw_len = pstr->bufs_len;
+           }
+       }
+    }
+
+  return REG_NOERROR;
+}
+
+/* Helper functions for re_string_allocate, and re_string_construct.  */
+
+static reg_errcode_t
+internal_function
+re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len)
+{
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1)
+    {
+      wint_t *new_wcs = re_xrealloc (pstr->wcs, wint_t, new_buf_len);
+      if (BE (new_wcs == NULL, 0))
+       return REG_ESPACE;
+      pstr->wcs = new_wcs;
+      if (pstr->offsets != NULL)
+       {
+         Idx *new_offsets = re_xrealloc (pstr->offsets, Idx, new_buf_len);
+         if (BE (new_offsets == NULL, 0))
+           return REG_ESPACE;
+         pstr->offsets = new_offsets;
+       }
+    }
+#endif /* RE_ENABLE_I18N  */
+  if (pstr->mbs_allocated)
+    {
+      unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
+                                          new_buf_len);
+      if (BE (new_mbs == NULL, 0))
+       return REG_ESPACE;
+      pstr->mbs = new_mbs;
+    }
+  pstr->bufs_len = new_buf_len;
+  return REG_NOERROR;
+}
+
+
+static void
+internal_function
+re_string_construct_common (const char *str, Idx len, re_string_t *pstr,
+                           REG_TRANSLATE_TYPE trans, bool icase,
+                           const re_dfa_t *dfa)
+{
+  pstr->raw_mbs = (const unsigned char *) str;
+  pstr->len = len;
+  pstr->raw_len = len;
+  pstr->trans = (unsigned REG_TRANSLATE_TYPE) trans;
+  pstr->icase = icase;
+  pstr->mbs_allocated = (trans != NULL || icase);
+  pstr->mb_cur_max = dfa->mb_cur_max;
+  pstr->is_utf8 = dfa->is_utf8;
+  pstr->map_notascii = dfa->map_notascii;
+  pstr->stop = pstr->len;
+  pstr->raw_stop = pstr->stop;
+}
+
+#ifdef RE_ENABLE_I18N
+
+/* Build wide character buffer PSTR->WCS.
+   If the byte sequence of the string are:
+     <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
+   Then wide character buffer will be:
+     <wc1>   , WEOF    , <wc2>   , WEOF    , <wc3>
+   We use WEOF for padding, they indicate that the position isn't
+   a first byte of a multibyte character.
+
+   Note that this function assumes PSTR->VALID_LEN elements are already
+   built and starts from PSTR->VALID_LEN.  */
+
+static void
+internal_function
+build_wcs_buffer (re_string_t *pstr)
+{
+#ifdef _LIBC
+  unsigned char buf[MB_LEN_MAX];
+  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+#else
+  unsigned char buf[64];
+#endif
+  mbstate_t prev_st;
+  Idx byte_idx, end_idx, remain_len;
+  size_t mbclen;
+
+  /* Build the buffers from pstr->valid_len to either pstr->len or
+     pstr->bufs_len.  */
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+  for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
+    {
+      wchar_t wc;
+      const char *p;
+
+      remain_len = end_idx - byte_idx;
+      prev_st = pstr->cur_state;
+      /* Apply the translation if we need.  */
+      if (BE (pstr->trans != NULL, 0))
+       {
+         int i, ch;
+
+         for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+           {
+             ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
+             buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
+           }
+         p = (const char *) buf;
+       }
+      else
+       p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
+      mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
+      if (BE (mbclen == (size_t) -2, 0))
+       {
+         /* The buffer doesn't have enough space, finish to build.  */
+         pstr->cur_state = prev_st;
+         break;
+       }
+      else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
+       {
+         /* We treat these cases as a singlebyte character.  */
+         mbclen = 1;
+         wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
+         if (BE (pstr->trans != NULL, 0))
+           wc = pstr->trans[wc];
+         pstr->cur_state = prev_st;
+       }
+
+      /* Write wide character and padding.  */
+      pstr->wcs[byte_idx++] = wc;
+      /* Write paddings.  */
+      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+       pstr->wcs[byte_idx++] = WEOF;
+    }
+  pstr->valid_len = byte_idx;
+  pstr->valid_raw_len = byte_idx;
+}
+
+/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
+   but for REG_ICASE.  */
+
+static reg_errcode_t
+internal_function
+build_wcs_upper_buffer (re_string_t *pstr)
+{
+  mbstate_t prev_st;
+  Idx src_idx, byte_idx, end_idx, remain_len;
+  size_t mbclen;
+#ifdef _LIBC
+  char buf[MB_LEN_MAX];
+  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+#else
+  char buf[64];
+#endif
+
+  byte_idx = pstr->valid_len;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  /* The following optimization assumes that ASCII characters can be
+     mapped to wide characters with a simple cast.  */
+  if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)
+    {
+      while (byte_idx < end_idx)
+       {
+         wchar_t wc;
+
+         if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
+             && mbsinit (&pstr->cur_state))
+           {
+             /* In case of a singlebyte character.  */
+             pstr->mbs[byte_idx]
+               = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
+             /* The next step uses the assumption that wchar_t is encoded
+                ASCII-safe: all ASCII values can be converted like this.  */
+             pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
+             ++byte_idx;
+             continue;
+           }
+
+         remain_len = end_idx - byte_idx;
+         prev_st = pstr->cur_state;
+         mbclen = mbrtowc (&wc,
+                           ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
+                            + byte_idx), remain_len, &pstr->cur_state);
+         if (BE ((size_t) (mbclen + 2) > 2, 1))
+           {
+             wchar_t wcu = wc;
+             if (iswlower (wc))
+               {
+                 size_t mbcdlen;
+
+                 wcu = towupper (wc);
+                 mbcdlen = wcrtomb (buf, wcu, &prev_st);
+                 if (BE (mbclen == mbcdlen, 1))
+                   memcpy (pstr->mbs + byte_idx, buf, mbclen);
+                 else
+                   {
+                     src_idx = byte_idx;
+                     goto offsets_needed;
+                   }
+               }
+             else
+               memcpy (pstr->mbs + byte_idx,
+                       pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
+             pstr->wcs[byte_idx++] = wcu;
+             /* Write paddings.  */
+             for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+               pstr->wcs[byte_idx++] = WEOF;
+           }
+         else if (mbclen == (size_t) -1 || mbclen == 0)
+           {
+             /* It is an invalid character or '\0'.  Just use the byte.  */
+             int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
+             pstr->mbs[byte_idx] = ch;
+             /* And also cast it to wide char.  */
+             pstr->wcs[byte_idx++] = (wchar_t) ch;
+             if (BE (mbclen == (size_t) -1, 0))
+               pstr->cur_state = prev_st;
+           }
+         else
+           {
+             /* The buffer doesn't have enough space, finish to build.  */
+             pstr->cur_state = prev_st;
+             break;
+           }
+       }
+      pstr->valid_len = byte_idx;
+      pstr->valid_raw_len = byte_idx;
+      return REG_NOERROR;
+    }
+  else
+    for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)
+      {
+       wchar_t wc;
+       const char *p;
+      offsets_needed:
+       remain_len = end_idx - byte_idx;
+       prev_st = pstr->cur_state;
+       if (BE (pstr->trans != NULL, 0))
+         {
+           int i, ch;
+
+           for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+             {
+               ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
+               buf[i] = pstr->trans[ch];
+             }
+           p = (const char *) buf;
+         }
+       else
+         p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
+       mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
+       if (BE ((size_t) (mbclen + 2) > 2, 1))
+         {
+           wchar_t wcu = wc;
+           if (iswlower (wc))
+             {
+               size_t mbcdlen;
+
+               wcu = towupper (wc);
+               mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st);
+               if (BE (mbclen == mbcdlen, 1))
+                 memcpy (pstr->mbs + byte_idx, buf, mbclen);
+               else if (mbcdlen != (size_t) -1)
+                 {
+                   size_t i;
+
+                   if (byte_idx + mbcdlen > pstr->bufs_len)
+                     {
+                       pstr->cur_state = prev_st;
+                       break;
+                     }
+
+                   if (pstr->offsets == NULL)
+                     {
+                       pstr->offsets = re_xmalloc (Idx, pstr->bufs_len);
+
+                       if (pstr->offsets == NULL)
+                         return REG_ESPACE;
+                     }
+                   if (!pstr->offsets_needed)
+                     {
+                       for (i = 0; i < (size_t) byte_idx; ++i)
+                         pstr->offsets[i] = i;
+                       pstr->offsets_needed = 1;
+                     }
+
+                   memcpy (pstr->mbs + byte_idx, buf, mbcdlen);
+                   pstr->wcs[byte_idx] = wcu;
+                   pstr->offsets[byte_idx] = src_idx;
+                   for (i = 1; i < mbcdlen; ++i)
+                     {
+                       pstr->offsets[byte_idx + i]
+                         = src_idx + (i < mbclen ? i : mbclen - 1);
+                       pstr->wcs[byte_idx + i] = WEOF;
+                     }
+                   pstr->len += mbcdlen - mbclen;
+                   if (pstr->raw_stop > src_idx)
+                     pstr->stop += mbcdlen - mbclen;
+                   end_idx = (pstr->bufs_len > pstr->len)
+                             ? pstr->len : pstr->bufs_len;
+                   byte_idx += mbcdlen;
+                   src_idx += mbclen;
+                   continue;
+                 }
+                else
+                  memcpy (pstr->mbs + byte_idx, p, mbclen);
+             }
+           else
+             memcpy (pstr->mbs + byte_idx, p, mbclen);
+
+           if (BE (pstr->offsets_needed != 0, 0))
+             {
+               size_t i;
+               for (i = 0; i < mbclen; ++i)
+                 pstr->offsets[byte_idx + i] = src_idx + i;
+             }
+           src_idx += mbclen;
+
+           pstr->wcs[byte_idx++] = wcu;
+           /* Write paddings.  */
+           for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
+             pstr->wcs[byte_idx++] = WEOF;
+         }
+       else if (mbclen == (size_t) -1 || mbclen == 0)
+         {
+           /* It is an invalid character or '\0'.  Just use the byte.  */
+           int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
+
+           if (BE (pstr->trans != NULL, 0))
+             ch = pstr->trans [ch];
+           pstr->mbs[byte_idx] = ch;
+
+           if (BE (pstr->offsets_needed != 0, 0))
+             pstr->offsets[byte_idx] = src_idx;
+           ++src_idx;
+
+           /* And also cast it to wide char.  */
+           pstr->wcs[byte_idx++] = (wchar_t) ch;
+           if (BE (mbclen == (size_t) -1, 0))
+             pstr->cur_state = prev_st;
+         }
+       else
+         {
+           /* The buffer doesn't have enough space, finish to build.  */
+           pstr->cur_state = prev_st;
+           break;
+         }
+      }
+  pstr->valid_len = byte_idx;
+  pstr->valid_raw_len = src_idx;
+  return REG_NOERROR;
+}
+
+/* Skip characters until the index becomes greater than NEW_RAW_IDX.
+   Return the index.  */
+
+static Idx
+internal_function
+re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc)
+{
+  mbstate_t prev_st;
+  Idx rawbuf_idx;
+  size_t mbclen;
+  wchar_t wc = 0;
+
+  /* Skip the characters which are not necessary to check.  */
+  for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
+       rawbuf_idx < new_raw_idx;)
+    {
+      Idx remain_len;
+      remain_len = pstr->len - rawbuf_idx;
+      prev_st = pstr->cur_state;
+      mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx,
+                       remain_len, &pstr->cur_state);
+      if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
+       {
+         /* We treat these cases as a singlebyte character.  */
+         mbclen = 1;
+         pstr->cur_state = prev_st;
+       }
+      /* Then proceed the next character.  */
+      rawbuf_idx += mbclen;
+    }
+  *last_wc = (wint_t) wc;
+  return rawbuf_idx;
+}
+#endif /* RE_ENABLE_I18N  */
+
+/* Build the buffer PSTR->MBS, and apply the translation if we need.
+   This function is used in case of REG_ICASE.  */
+
+static void
+internal_function
+build_upper_buffer (re_string_t *pstr)
+{
+  Idx char_idx, end_idx;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
+    {
+      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
+      if (BE (pstr->trans != NULL, 0))
+       ch = pstr->trans[ch];
+      if (islower (ch))
+       pstr->mbs[char_idx] = toupper (ch);
+      else
+       pstr->mbs[char_idx] = ch;
+    }
+  pstr->valid_len = char_idx;
+  pstr->valid_raw_len = char_idx;
+}
+
+/* Apply TRANS to the buffer in PSTR.  */
+
+static void
+internal_function
+re_string_translate_buffer (re_string_t *pstr)
+{
+  Idx buf_idx, end_idx;
+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
+
+  for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
+    {
+      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
+      pstr->mbs[buf_idx] = pstr->trans[ch];
+    }
+
+  pstr->valid_len = buf_idx;
+  pstr->valid_raw_len = buf_idx;
+}
+
+/* This function re-construct the buffers.
+   Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
+   convert to upper case in case of REG_ICASE, apply translation.  */
+
+static reg_errcode_t
+internal_function
+re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags)
+{
+  Idx offset;
+
+  if (BE (pstr->raw_mbs_idx <= idx, 0))
+    offset = idx - pstr->raw_mbs_idx;
+  else
+    {
+      /* Reset buffer.  */
+#ifdef RE_ENABLE_I18N
+      if (pstr->mb_cur_max > 1)
+       memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
+#endif /* RE_ENABLE_I18N */
+      pstr->len = pstr->raw_len;
+      pstr->stop = pstr->raw_stop;
+      pstr->valid_len = 0;
+      pstr->raw_mbs_idx = 0;
+      pstr->valid_raw_len = 0;
+      pstr->offsets_needed = 0;
+      pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
+                          : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
+      if (!pstr->mbs_allocated)
+       pstr->mbs = (unsigned char *) pstr->raw_mbs;
+      offset = idx;
+    }
+
+  if (BE (offset != 0, 1))
+    {
+      /* Are the characters which are already checked remain?  */
+      if (BE (offset < pstr->valid_raw_len, 1)
+#ifdef RE_ENABLE_I18N
+         /* Handling this would enlarge the code too much.
+            Accept a slowdown in that case.  */
+         && pstr->offsets_needed == 0
+#endif
+        )
+       {
+         /* Yes, move them to the front of the buffer.  */
+         pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags);
+#ifdef RE_ENABLE_I18N
+         if (pstr->mb_cur_max > 1)
+           memmove (pstr->wcs, pstr->wcs + offset,
+                    (pstr->valid_len - offset) * sizeof (wint_t));
+#endif /* RE_ENABLE_I18N */
+         if (BE (pstr->mbs_allocated, 0))
+           memmove (pstr->mbs, pstr->mbs + offset,
+                    pstr->valid_len - offset);
+         pstr->valid_len -= offset;
+         pstr->valid_raw_len -= offset;
+#if DEBUG
+         assert (pstr->valid_len > 0);
+#endif
+       }
+      else
+       {
+         /* No, skip all characters until IDX.  */
+#ifdef RE_ENABLE_I18N
+         if (BE (pstr->offsets_needed, 0))
+           {
+             pstr->len = pstr->raw_len - idx + offset;
+             pstr->stop = pstr->raw_stop - idx + offset;
+             pstr->offsets_needed = 0;
+           }
+#endif
+         pstr->valid_len = 0;
+         pstr->valid_raw_len = 0;
+#ifdef RE_ENABLE_I18N
+         if (pstr->mb_cur_max > 1)
+           {
+             Idx wcs_idx;
+             wint_t wc = WEOF;
+
+             if (pstr->is_utf8)
+               {
+                 const unsigned char *raw, *p, *q, *end;
+
+                 /* Special case UTF-8.  Multi-byte chars start with any
+                    byte other than 0x80 - 0xbf.  */
+                 raw = pstr->raw_mbs + pstr->raw_mbs_idx;
+                 end = raw + (offset - pstr->mb_cur_max);
+                 for (p = raw + offset - 1; p >= end; --p)
+                   if ((*p & 0xc0) != 0x80)
+                     {
+                       mbstate_t cur_state;
+                       wchar_t wc2;
+                       Idx mlen = raw + pstr->len - p;
+                       unsigned char buf[6];
+                       size_t mbclen;
+
+                       q = p;
+                       if (BE (pstr->trans != NULL, 0))
+                         {
+                           int i = mlen < 6 ? mlen : 6;
+                           while (--i >= 0)
+                             buf[i] = pstr->trans[p[i]];
+                           q = buf;
+                         }
+                       /* XXX Don't use mbrtowc, we know which conversion
+                          to use (UTF-8 -> UCS4).  */
+                       memset (&cur_state, 0, sizeof (cur_state));
+                       mbclen = mbrtowc (&wc2, (const char *) p, mlen,
+                                         &cur_state);
+                       if (raw + offset - p <= mbclen && mbclen < (size_t) -2)
+                         {
+                           memset (&pstr->cur_state, '\0',
+                                   sizeof (mbstate_t));
+                           pstr->valid_len = mbclen - (raw + offset - p);
+                           wc = wc2;
+                         }
+                       break;
+                     }
+               }
+
+             if (wc == WEOF)
+               pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
+             if (BE (pstr->valid_len, 0))
+               {
+                 for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
+                   pstr->wcs[wcs_idx] = WEOF;
+                 if (pstr->mbs_allocated)
+                   memset (pstr->mbs, -1, pstr->valid_len);
+               }
+             pstr->valid_raw_len = pstr->valid_len;
+             pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
+                                   && IS_WIDE_WORD_CHAR (wc))
+                                  ? CONTEXT_WORD
+                                  : ((IS_WIDE_NEWLINE (wc)
+                                      && pstr->newline_anchor)
+                                     ? CONTEXT_NEWLINE : 0));
+           }
+         else
+#endif /* RE_ENABLE_I18N */
+           {
+             int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
+             if (pstr->trans)
+               c = pstr->trans[c];
+             pstr->tip_context = (bitset_contain (pstr->word_char, c)
+                                  ? CONTEXT_WORD
+                                  : ((IS_NEWLINE (c) && pstr->newline_anchor)
+                                     ? CONTEXT_NEWLINE : 0));
+           }
+       }
+      if (!BE (pstr->mbs_allocated, 0))
+       pstr->mbs += offset;
+    }
+  pstr->raw_mbs_idx = idx;
+  pstr->len -= offset;
+  pstr->stop -= offset;
+
+  /* Then build the buffers.  */
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1)
+    {
+      if (pstr->icase)
+       {
+         reg_errcode_t ret = build_wcs_upper_buffer (pstr);
+         if (BE (ret != REG_NOERROR, 0))
+           return ret;
+       }
+      else
+       build_wcs_buffer (pstr);
+    }
+  else
+#endif /* RE_ENABLE_I18N */
+  if (BE (pstr->mbs_allocated, 0))
+    {
+      if (pstr->icase)
+       build_upper_buffer (pstr);
+      else if (pstr->trans != NULL)
+       re_string_translate_buffer (pstr);
+    }
+  else
+    pstr->valid_len = pstr->len;
+
+  pstr->cur_idx = 0;
+  return REG_NOERROR;
+}
+
+static unsigned char
+internal_function __attribute ((pure))
+re_string_peek_byte_case (const re_string_t *pstr, Idx idx)
+{
+  int ch;
+  Idx off;
+
+  /* Handle the common (easiest) cases first.  */
+  if (BE (!pstr->mbs_allocated, 1))
+    return re_string_peek_byte (pstr, idx);
+
+#ifdef RE_ENABLE_I18N
+  if (pstr->mb_cur_max > 1
+      && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
+    return re_string_peek_byte (pstr, idx);
+#endif
+
+  off = pstr->cur_idx + idx;
+#ifdef RE_ENABLE_I18N
+  if (pstr->offsets_needed)
+    off = pstr->offsets[off];
+#endif
+
+  ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
+
+#ifdef RE_ENABLE_I18N
+  /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
+     this function returns CAPITAL LETTER I instead of first byte of
+     DOTLESS SMALL LETTER I.  The latter would confuse the parser,
+     since peek_byte_case doesn't advance cur_idx in any way.  */
+  if (pstr->offsets_needed && !isascii (ch))
+    return re_string_peek_byte (pstr, idx);
+#endif
+
+  return ch;
+}
+
+static unsigned char
+internal_function __attribute ((pure))
+re_string_fetch_byte_case (re_string_t *pstr)
+{
+  if (BE (!pstr->mbs_allocated, 1))
+    return re_string_fetch_byte (pstr);
+
+#ifdef RE_ENABLE_I18N
+  if (pstr->offsets_needed)
+    {
+      Idx off;
+      int ch;
+
+      /* For tr_TR.UTF-8 [[:islower:]] there is
+        [[: CAPITAL LETTER I WITH DOT lower:]] in mbs.  Skip
+        in that case the whole multi-byte character and return
+        the original letter.  On the other side, with
+        [[: DOTLESS SMALL LETTER I return [[:I, as doing
+        anything else would complicate things too much.  */
+
+      if (!re_string_first_byte (pstr, pstr->cur_idx))
+       return re_string_fetch_byte (pstr);
+
+      off = pstr->offsets[pstr->cur_idx];
+      ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
+
+      if (! isascii (ch))
+       return re_string_fetch_byte (pstr);
+
+      re_string_skip_bytes (pstr,
+                           re_string_char_size_at (pstr, pstr->cur_idx));
+      return ch;
+    }
+#endif
+
+  return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
+}
+
+static void
+internal_function
+re_string_destruct (re_string_t *pstr)
+{
+#ifdef RE_ENABLE_I18N
+  re_free (pstr->wcs);
+  re_free (pstr->offsets);
+#endif /* RE_ENABLE_I18N  */
+  if (pstr->mbs_allocated)
+    re_free (pstr->mbs);
+}
+
+/* Return the context at IDX in INPUT.  */
+
+static unsigned int
+internal_function
+re_string_context_at (const re_string_t *input, Idx idx, int eflags)
+{
+  int c;
+  if (BE (! REG_VALID_INDEX (idx), 0))
+    /* In this case, we use the value stored in input->tip_context,
+       since we can't know the character in input->mbs[-1] here.  */
+    return input->tip_context;
+  if (BE (idx == input->len, 0))
+    return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
+           : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
+#ifdef RE_ENABLE_I18N
+  if (input->mb_cur_max > 1)
+    {
+      wint_t wc;
+      Idx wc_idx = idx;
+      while(input->wcs[wc_idx] == WEOF)
+       {
+#ifdef DEBUG
+         /* It must not happen.  */
+         assert (REG_VALID_INDEX (wc_idx));
+#endif
+         --wc_idx;
+         if (! REG_VALID_INDEX (wc_idx))
+           return input->tip_context;
+       }
+      wc = input->wcs[wc_idx];
+      if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc))
+       return CONTEXT_WORD;
+      return (IS_WIDE_NEWLINE (wc) && input->newline_anchor
+             ? CONTEXT_NEWLINE : 0);
+    }
+  else
+#endif
+    {
+      c = re_string_byte_at (input, idx);
+      if (bitset_contain (input->word_char, c))
+       return CONTEXT_WORD;
+      return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;
+    }
+}
+\f
+/* Functions for set operation.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_alloc (re_node_set *set, Idx size)
+{
+  set->alloc = size;
+  set->nelem = 0;
+  set->elems = re_xmalloc (Idx, size);
+  if (BE (set->elems == NULL, 0))
+    return REG_ESPACE;
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_1 (re_node_set *set, Idx elem)
+{
+  set->alloc = 1;
+  set->nelem = 1;
+  set->elems = re_malloc (Idx, 1);
+  if (BE (set->elems == NULL, 0))
+    {
+      set->alloc = set->nelem = 0;
+      return REG_ESPACE;
+    }
+  set->elems[0] = elem;
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2)
+{
+  set->alloc = 2;
+  set->elems = re_malloc (Idx, 2);
+  if (BE (set->elems == NULL, 0))
+    return REG_ESPACE;
+  if (elem1 == elem2)
+    {
+      set->nelem = 1;
+      set->elems[0] = elem1;
+    }
+  else
+    {
+      set->nelem = 2;
+      if (elem1 < elem2)
+       {
+         set->elems[0] = elem1;
+         set->elems[1] = elem2;
+       }
+      else
+       {
+         set->elems[0] = elem2;
+         set->elems[1] = elem1;
+       }
+    }
+  return REG_NOERROR;
+}
+
+static reg_errcode_t
+internal_function
+re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
+{
+  dest->nelem = src->nelem;
+  if (src->nelem > 0)
+    {
+      dest->alloc = dest->nelem;
+      dest->elems = re_malloc (Idx, dest->alloc);
+      if (BE (dest->elems == NULL, 0))
+       {
+         dest->alloc = dest->nelem = 0;
+         return REG_ESPACE;
+       }
+      memcpy (dest->elems, src->elems, src->nelem * sizeof dest->elems[0]);
+    }
+  else
+    re_node_set_init_empty (dest);
+  return REG_NOERROR;
+}
+
+/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.
+   Note: We assume dest->elems is NULL, when dest->alloc is 0.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
+                          const re_node_set *src2)
+{
+  Idx i1, i2, is, id, delta, sbase;
+  if (src1->nelem == 0 || src2->nelem == 0)
+    return REG_NOERROR;
+
+  /* We need dest->nelem + 2 * elems_in_intersection; this is a
+     conservative estimate.  */
+  if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
+    {
+      Idx new_alloc = src1->nelem + src2->nelem + dest->alloc;
+      Idx *new_elems;
+      if (sizeof (Idx) < 3
+         && (new_alloc < dest->alloc
+             || ((Idx) (src1->nelem + src2->nelem) < src1->nelem)))
+       return REG_ESPACE;
+      new_elems = re_xrealloc (dest->elems, Idx, new_alloc);
+      if (BE (new_elems == NULL, 0))
+        return REG_ESPACE;
+      dest->elems = new_elems;
+      dest->alloc = new_alloc;
+    }
+
+  /* Find the items in the intersection of SRC1 and SRC2, and copy
+     into the top of DEST those that are not already in DEST itself.  */
+  sbase = dest->nelem + src1->nelem + src2->nelem;
+  i1 = src1->nelem - 1;
+  i2 = src2->nelem - 1;
+  id = dest->nelem - 1;
+  for (;;)
+    {
+      if (src1->elems[i1] == src2->elems[i2])
+       {
+         /* Try to find the item in DEST.  Maybe we could binary search?  */
+         while (REG_VALID_INDEX (id) && dest->elems[id] > src1->elems[i1])
+           --id;
+
+          if (! REG_VALID_INDEX (id) || dest->elems[id] != src1->elems[i1])
+            dest->elems[--sbase] = src1->elems[i1];
+
+         if (! REG_VALID_INDEX (--i1) || ! REG_VALID_INDEX (--i2))
+           break;
+       }
+
+      /* Lower the highest of the two items.  */
+      else if (src1->elems[i1] < src2->elems[i2])
+       {
+         if (! REG_VALID_INDEX (--i2))
+           break;
+       }
+      else
+       {
+         if (! REG_VALID_INDEX (--i1))
+           break;
+       }
+    }
+
+  id = dest->nelem - 1;
+  is = dest->nelem + src1->nelem + src2->nelem - 1;
+  delta = is - sbase + 1;
+
+  /* Now copy.  When DELTA becomes zero, the remaining
+     DEST elements are already in place; this is more or
+     less the same loop that is in re_node_set_merge.  */
+  dest->nelem += delta;
+  if (delta > 0 && REG_VALID_INDEX (id))
+    for (;;)
+      {
+        if (dest->elems[is] > dest->elems[id])
+          {
+            /* Copy from the top.  */
+            dest->elems[id + delta--] = dest->elems[is--];
+            if (delta == 0)
+              break;
+          }
+        else
+          {
+            /* Slide from the bottom.  */
+            dest->elems[id + delta] = dest->elems[id];
+            if (! REG_VALID_INDEX (--id))
+              break;
+          }
+      }
+
+  /* Copy remaining SRC elements.  */
+  memcpy (dest->elems, dest->elems + sbase, delta * sizeof dest->elems[0]);
+
+  return REG_NOERROR;
+}
+
+/* Calculate the union set of the sets SRC1 and SRC2. And store it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
+                       const re_node_set *src2)
+{
+  Idx i1, i2, id;
+  if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
+    {
+      dest->alloc = src1->nelem + src2->nelem;
+      if (sizeof (Idx) < 2 && dest->alloc < src1->nelem)
+       return REG_ESPACE;
+      dest->elems = re_xmalloc (Idx, dest->alloc);
+      if (BE (dest->elems == NULL, 0))
+       return REG_ESPACE;
+    }
+  else
+    {
+      if (src1 != NULL && src1->nelem > 0)
+       return re_node_set_init_copy (dest, src1);
+      else if (src2 != NULL && src2->nelem > 0)
+       return re_node_set_init_copy (dest, src2);
+      else
+       re_node_set_init_empty (dest);
+      return REG_NOERROR;
+    }
+  for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
+    {
+      if (src1->elems[i1] > src2->elems[i2])
+       {
+         dest->elems[id++] = src2->elems[i2++];
+         continue;
+       }
+      if (src1->elems[i1] == src2->elems[i2])
+       ++i2;
+      dest->elems[id++] = src1->elems[i1++];
+    }
+  if (i1 < src1->nelem)
+    {
+      memcpy (dest->elems + id, src1->elems + i1,
+            (src1->nelem - i1) * sizeof dest->elems[0]);
+      id += src1->nelem - i1;
+    }
+  else if (i2 < src2->nelem)
+    {
+      memcpy (dest->elems + id, src2->elems + i2,
+            (src2->nelem - i2) * sizeof dest->elems[0]);
+      id += src2->nelem - i2;
+    }
+  dest->nelem = id;
+  return REG_NOERROR;
+}
+
+/* Calculate the union set of the sets DEST and SRC. And store it to
+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
+
+static reg_errcode_t
+internal_function
+re_node_set_merge (re_node_set *dest, const re_node_set *src)
+{
+  Idx is, id, sbase, delta;
+  if (src == NULL || src->nelem == 0)
+    return REG_NOERROR;
+  if (sizeof (Idx) < 3
+      && ((Idx) (2 * src->nelem) < src->nelem
+         || (Idx) (2 * src->nelem + dest->nelem) < dest->nelem))
+    return REG_ESPACE;
+  if (dest->alloc < 2 * src->nelem + dest->nelem)
+    {
+      Idx new_alloc = src->nelem + dest->alloc;
+      Idx *new_buffer;
+      if (sizeof (Idx) < 4 && new_alloc < dest->alloc)
+       return REG_ESPACE;
+      new_buffer = re_x2realloc (dest->elems, Idx, &new_alloc);
+      if (BE (new_buffer == NULL, 0))
+       return REG_ESPACE;
+      dest->elems = new_buffer;
+      dest->alloc = new_alloc;
+    }
+
+  if (BE (dest->nelem == 0, 0))
+    {
+      dest->nelem = src->nelem;
+      memcpy (dest->elems, src->elems, src->nelem * sizeof dest->elems[0]);
+      return REG_NOERROR;
+    }
+
+  /* Copy into the top of DEST the items of SRC that are not
+     found in DEST.  Maybe we could binary search in DEST?  */
+  for (sbase = dest->nelem + 2 * src->nelem,
+       is = src->nelem - 1, id = dest->nelem - 1;