]> mj.ucw.cz Git - libucw.git/commitdiff
Merge branch 'master' into dev-admin
authorPavel Charvat <pchar@ucw.cz>
Mon, 7 Jul 2008 20:32:10 +0000 (22:32 +0200)
committerPavel Charvat <pchar@ucw.cz>
Mon, 7 Jul 2008 20:32:10 +0000 (22:32 +0200)
31 files changed:
build/Makebottom
free/libs/README
free/libs/examples/internal/default.cfg
lib/Makefile
lib/autoconf.cfg
lib/default.cfg
lib/fb-socket.c [new file with mode: 0644]
lib/fb-socket.h [new file with mode: 0644]
lib/fb-socket.t [new file with mode: 0644]
lib/ff-utf8.h [deleted file]
lib/lib.h
lib/log-file.c
lib/log.c
lib/perl/Configure.pm
lib/regex.c
lib/regex/Makefile [deleted file]
lib/regex/README [deleted file]
lib/regex/regcomp.c [deleted file]
lib/regex/regex-sh.h [deleted file]
lib/regex/regex.c [deleted file]
lib/regex/regex.h [deleted file]
lib/regex/regex_internal.c [deleted file]
lib/regex/regex_internal.h [deleted file]
lib/regex/regexec.c [deleted file]
sherlock/xml/dtd.c
sherlock/xml/dtd.h
sherlock/xml/parse.c
sherlock/xml/source.c
sherlock/xml/xml-test.c
sherlock/xml/xml-test.t
sherlock/xml/xml.h

index b6f716eab6d5ad98ad380c2d4735a2c6ac3b4924..bf9a49e966489e0c5479274212b0ec0c56fcc064 100644 (file)
@@ -39,13 +39,14 @@ force:
 
 # Rules for configuration files
 
-run/cf/%: custom/cf/% $(o)/config.mk $(s)/build/genconf
+run/cf/%: $(s)/cf/% $(o)/config.mk $(s)/build/genconf
        $(M)CF $<
        $(Q)$(s)/build/genconf $< $@ $(o)/config.mk
 
-run/cf/%: $(s)/cf/% $(o)/config.mk $(s)/build/genconf
+$(o)/%.cf: $(s)/%.cf $(o)/config.mk $(s)/build/genconf
        $(M)CF $<
        $(Q)$(s)/build/genconf $< $@ $(o)/config.mk
+       $(Q)cp $@ run/cf/$(basename $(@F))
 
 # Rules for libraries
 
index 44168dcb19d9aa361da8026946c449d27fd86fd2..6dcddcc2cb4ab30730913d7faa8c1de2bd0b918a 100644 (file)
@@ -1,7 +1,7 @@
-Sherlock Holmes Libraries 3.12.3
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(c) 1997--2007 Martin Mares <mj@ucw.cz>
-(c) 2000--2007 Robert Spalek <robert@ucw.cz>
+Sherlock Holmes Libraries 3.13
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+(c) 1997--2008 Martin Mares <mj@ucw.cz>
+(c) 2000--2008 Robert Spalek <robert@ucw.cz>
 
 This package contains all libraries from the freely distributable version
 of the Sherlock Holmes search engine (see http://www.ucw.cz/holmes/).
index c0335b5e4167b9944e05c15f825300d5feb5a0c9..12b3c7b7f57de2357a715949fc877787703d8be3 100644 (file)
@@ -5,7 +5,8 @@ Set("CONFIG_SHARED");
 
 # Liblang settings
 Set("CONFIG_LANG");
-Set("MAX_WORD_LEN" => 64);
+Set("MAX_WORD_CHARS" => 64);
+Set("MAX_WORD_BYTES" => 192);
 
 # Libimages settings
 Set("CONFIG_IMAGES");
index 24e5a87603055e462a0a75a35ff4725722700449..0c5d0ac730b192a92675f47dc200d8dcc5dcd3d5 100644 (file)
@@ -18,7 +18,7 @@ LIBUCW_MODS= \
        ipaccess \
        profile \
        fastbuf ff-binary ff-string ff-printf ff-unicode \
-       fb-file carefulio fb-mem fb-temp fb-mmap fb-limfd fb-buffer fb-grow fb-pool fb-atomic fb-param \
+       fb-file carefulio fb-mem fb-temp fb-mmap fb-limfd fb-buffer fb-grow fb-pool fb-atomic fb-param fb-socket \
        str_ctype str_upper str_lower unicode stkstring \
        wildmatch wordsplit ctmatch patimatch patmatch regex \
        prime primetable random timer randomkey \
@@ -49,7 +49,7 @@ LIBUCW_INCLUDES= \
        bitops.h \
        conf.h getopt.h ipaccess.h \
        profile.h \
-       fastbuf.h lfs.h ff-unicode.h ff-utf8.h ff-binary.h \
+       fastbuf.h lfs.h ff-unicode.h ff-binary.h \
        chartype.h unicode.h stkstring.h \
        wildmatch.h patmatch.h \
        db.h \
@@ -68,10 +68,6 @@ LIBUCW_MODS+=threads-conf workqueue asio fb-direct
 LIBUCW_INCLUDES+=workqueue.h semaphore.h asio.h
 endif
 
-ifdef CONFIG_OWN_REGEX
-include $(s)/lib/regex/Makefile
-endif
-
 ifdef CONFIG_OWN_GETOPT
 include $(s)/lib/getopt/Makefile
 endif
@@ -101,7 +97,8 @@ $(o)/lib/ipaccess-test: $(o)/lib/ipaccess-test.o $(LIBUCW)
 $(o)/lib/trie-test: $(o)/lib/trie-test.o $(LIBUCW)
 
 TESTS+=$(addprefix $(o)/lib/,regex.test unicode.test hash-test.test mempool.test stkstring.test \
-    slists.test kmp-test.test bbuf.test getopt.test fastbuf.test ff-unicode.test eltpool.test trie-test.test)
+    slists.test kmp-test.test bbuf.test getopt.test fastbuf.test ff-unicode.test eltpool.test \
+    fb-socket.test trie-test.test)
 
 $(o)/lib/regex.test: $(o)/lib/regex-t
 $(o)/lib/unicode.test: $(o)/lib/unicode-t
@@ -116,6 +113,7 @@ $(o)/lib/getopt.test: $(o)/lib/getopt-t
 $(o)/lib/fastbuf.test: $(o)/lib/fb-file-t $(o)/lib/fb-grow-t $(o)/lib/fb-pool-t
 $(o)/lib/ff-unicode.test: $(o)/lib/ff-unicode-t
 $(o)/lib/eltpool.test: $(o)/lib/eltpool-t
+$(o)/lib/fb-socket.test: $(o)/lib/fb-socket-t
 $(o)/lib/trie-test.test: $(o)/lib/trie-test
 
 ifdef CONFIG_UCW_THREADS
index b0e3c536eba25d2bcd05e30a24f69f12a8d62815..28f1184322bde1eb97805cee54f73df6ff33ac0c 100644 (file)
@@ -201,14 +201,13 @@ if ($gccver == 3000) {
 } elsif ($gccver == 3004) {
        Append("CWARNS" => "-Wundef -Wredundant-decls");
        Append("COPT" => "-finline-limit=2000 --param large-function-insns=5000 --param inline-unit-growth=200 --param large-function-growth=400");
-} elsif ($gccver == 4000 || $gccver == 4001) {
+} elsif ($gccver >= 4000) {
        Append("CWARNS" => "-Wundef -Wredundant-decls -Wno-pointer-sign -Wdisabled-optimization -Wno-missing-field-initializers");
        Append("CWARNS_OFF" => "-Wno-pointer-sign");
        Append("COPT" => "-finline-limit=5000 --param large-function-insns=5000 --param inline-unit-growth=200 --param large-function-growth=400");
-} elsif ($gccver == 4002) {
-       Append("CWARNS" => "-Wundef -Wredundant-decls -Wno-pointer-sign -Wdisabled-optimization -Wno-missing-field-initializers");
-       Append("CWARNS_OFF" => "-Wno-pointer-sign");
-       Append("COPT" => "-finline-limit=5000 --param large-function-insns=5000 --param inline-unit-growth=200 --param large-function-growth=400 -fgnu89-inline");
+       if ($gccver >= 4002) {
+               Append("COPT" => "-fgnu89-inline");
+       }
 } else {
        Warn "Don't know anything about this GCC version, using default switches.\n";
 }
index ceb6d58680fad665067ef07cbe31a2cf36032674..8c2b21ba853371e36c8eceef526a579db552a378 100644 (file)
@@ -1,8 +1,8 @@
 # Configuration variables of the UCW library and their default values
-# (c) 2005--2007 Martin Mares <mj@ucw.cz>
+# (c) 2005--2008 Martin Mares <mj@ucw.cz>
 
 # Version of the whole package
-Set("SHERLOCK_VERSION" => "3.12.3");
+Set("SHERLOCK_VERSION" => "3.13-dev");
 
 # Compile everything with debug information and ASSERT's
 UnSet("CONFIG_DEBUG");
@@ -16,11 +16,6 @@ Set("CONFIG_LARGE_FILES");
 # Use shared libraries
 UnSet("CONFIG_SHARED");
 
-# If your system doesn't contain GNU libc 2.3 or newer, it's recommended to let Sherlock
-# use its own regex library (a copy of the glibc one), because the default regex library
-# is likely to be crappy.
-Set("CONFIG_OWN_REGEX");
-
 # If your system can't reset getopt with 'optind = 0', you need to compile our internal copy
 # of GNU libc's getopt. This should not be necessary on GNU libc.
 UnSet("CONFIG_OWN_GETOPT");
diff --git a/lib/fb-socket.c b/lib/fb-socket.c
new file mode 100644 (file)
index 0000000..841e0cf
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ *     UCW Library -- Fast Buffered I/O on Sockets with Timeouts
+ *
+ *     (c) 2008 Martin Mares <mj@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#include "lib/lib.h"
+#include "lib/fastbuf.h"
+#include "lib/fb-socket.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <poll.h>
+#include <errno.h>
+
+struct fb_sock {
+  struct fastbuf fb;
+  struct fbsock_params par;
+  byte buf[0];
+};
+
+#define FB_SOCK(f) ((struct fb_sock *)(f)->is_fastbuf)
+
+static int
+fbs_refill(struct fastbuf *f)
+{
+  struct fbsock_params *p = &FB_SOCK(f)->par;
+  struct pollfd pf = {
+      .fd = p->fd,
+      .events = POLLIN
+  };
+
+  for (;;)
+    {
+      int e = poll(&pf, 1, p->timeout_ms);
+      if (e < 0)
+       {
+         p->err(p->data, FBSOCK_READ, "read error");
+         return 0;
+       }
+      if (!e)
+       {
+         p->err(p->data, FBSOCK_READ | FBSOCK_TIMEOUT, "read timeout");
+         return 0;
+       }
+
+      f->bptr = f->buffer;
+      int l = read(p->fd, f->buffer, f->bufend-f->buffer);
+      if (l < 0)
+       {
+         if (errno == EINTR || errno == EAGAIN)
+           continue;
+         p->err(p->data, FBSOCK_READ, "read error");
+         return 0;
+       }
+      f->bstop = f->buffer + l;
+      f->pos += l;
+      return l;
+    }
+}
+
+static void
+fbs_spout(struct fastbuf *f)
+{
+  struct fbsock_params *p = &FB_SOCK(f)->par;
+  struct pollfd pf = {
+      .fd = p->fd,
+      .events = POLLOUT,
+  };
+
+  int l = f->bptr - f->buffer;
+  f->bptr = f->buffer;
+  char *buf = f->buffer;
+
+  while (l)
+    {
+      int e = poll(&pf, 1, p->timeout_ms);
+      if (e < 0)
+       {
+         p->err(p->data, FBSOCK_WRITE, "write error");
+         return;
+       }
+      if (!e)
+       {
+         p->err(p->data, FBSOCK_WRITE | FBSOCK_TIMEOUT, "write timeout");
+         return;
+       }
+
+      e = write(p->fd, buf, l);
+      if (e < 0)
+       {
+         if (errno == EINTR || errno == EAGAIN)
+           continue;
+         p->err(p->data, FBSOCK_WRITE, "write error");
+         return;
+       }
+      buf += e;
+      l -= e;
+    }
+}
+
+static void
+fbs_close(struct fastbuf *f)
+{
+  close(FB_SOCK(f)->par.fd);
+  xfree(f);
+}
+
+struct fastbuf *
+fbsock_create(struct fbsock_params *p)
+{
+  struct fb_sock *F = xmalloc(sizeof(*F) + p->bufsize);
+  struct fastbuf *f = &F->fb;
+
+  bzero(F, sizeof(*F));
+  F->par = *p;
+  f->buffer = F->buf;
+  f->bptr = f->bstop = f->buffer;
+  f->bufend = f->buffer + p->bufsize;
+  f->name = "<socket>";
+  f->refill = fbs_refill;
+  f->spout = fbs_spout;
+  f->close = fbs_close;
+  f->can_overwrite_buffer = 1;
+  return f;
+}
+
+#ifdef TEST
+
+#include <stdlib.h>
+
+static void test_err(void *x UNUSED, uns flags, char *msg UNUSED)
+{
+  if (flags & FBSOCK_READ)
+    printf("READ");
+  else if (flags & FBSOCK_WRITE)
+    printf("WRITE");
+  if (flags & FBSOCK_TIMEOUT)
+    printf(" TIMEOUT\n");
+  else
+    printf(" ERROR\n");
+  exit(0);
+}
+
+int main(void)
+{
+  int fd[2];
+  if (pipe(fd) < 0)
+    ASSERT(0);
+
+  struct fbsock_params p = {
+      .fd = fd[0],
+      .bufsize = 16,
+      .timeout_ms = 100,
+      .err = test_err
+  };
+  struct fastbuf *f = fbsock_create(&p);
+
+  bputsn(f, "Oook!");          // This fits in PIPE_BUF
+  bflush(f);
+
+  char buf[256];
+  if (!bgets(f, buf, sizeof(buf)))
+    die("bgets failed");
+  if (strcmp(buf, "Oook!"))
+    die("Misread input");
+
+  bgets(f, buf, sizeof(buf));
+  puts("WRONG");
+  exit(0);
+}
+
+#endif
diff --git a/lib/fb-socket.h b/lib/fb-socket.h
new file mode 100644 (file)
index 0000000..ff5ae7d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *     UCW Library -- Fast Buffered I/O on Sockets with Timeouts
+ *
+ *     (c) 2008 Martin Mares <mj@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#ifndef _UCW_FB_SOCKET_H
+#define _UCW_FB_SOCKET_H
+
+#include "lib/fastbuf.h"
+
+struct fbsock_params {
+  int fd;
+  uns bufsize;
+  uns timeout_ms;
+  void (*err)(void *data, uns flags, char *msg);
+  void *data;                  // Passed to the err callback
+};
+
+enum fbsock_err_flags {
+  FBSOCK_READ = 1,             // Happened during read
+  FBSOCK_WRITE = 2,            // Happened during write
+  FBSOCK_TIMEOUT = 4,          // The error is a timeout
+};
+
+struct fastbuf *fbsock_create(struct fbsock_params *par);
+
+#endif
diff --git a/lib/fb-socket.t b/lib/fb-socket.t
new file mode 100644 (file)
index 0000000..32f49ac
--- /dev/null
@@ -0,0 +1,5 @@
+# Tests for the fb-socket module
+
+Name:  fb-socket
+Run:   ../obj/lib/fb-socket-t
+Out:   WRITE TIMEOUT
diff --git a/lib/ff-utf8.h b/lib/ff-utf8.h
deleted file mode 100644 (file)
index af7543f..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- *     UCW Library: An alias for lib/ff-unicode.h (for backwards compatibility)
- *
- *     (c) 2008 Pavel Charvat <pchar@ucw.cz>
- *
- *     This software may be freely distributed and used according to the terms
- *     of the GNU Lesser General Public License.
- */
-
-#ifndef _UCW_FF_UTF8_H
-#define _UCW_FF_UTF8_H
-
-#include "lib/ff-unicode.h"
-
-#endif
index f8659ed192a3b276fd604b1ba884d367d11476b7..e93bdf6a750157a8ba29e642c09bd7cb0845772d 100644 (file)
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -1,7 +1,7 @@
 /*
  *     The UCW Library -- Miscellaneous Functions
  *
- *     (c) 1997--2007 Martin Mares <mj@ucw.cz>
+ *     (c) 1997--2008 Martin Mares <mj@ucw.cz>
  *     (c) 2005 Tomas Valla <tom@ucw.cz>
  *     (c) 2006 Robert Spalek <robert@ucw.cz>
  *     (c) 2007 Pavel Charvat <pchar@ucw.cz>
 #define L_ERROR_R      'e'
 #define L_FATAL                '!'             /* die() */
 
-extern char *log_title;                        /* NULL - print no title, default is log_progname */
+#define L_SIGHANDLER   0x10000         /* Avoid operations that are unsafe in signal handlers */
+
+extern char *log_title;                        /* NULL - print no title, default is program name given to log_init() */
 extern char *log_filename;             /* Expanded name of the current log file */
-extern volatile int log_switch_nest;   /* log_switch() nesting counter, increment to disable automatic switches */
 extern int log_pid;                    /* 0 if shouldn't be logged */
 extern int log_precise_timings;                /* Include microsecond timestamps in log messages */
 extern void (*log_die_hook)(void);
@@ -104,8 +105,13 @@ void vmsg(uns cat, const char *fmt, va_list args);
 void die(const char *, ...) NONRET FORMAT_CHECK(printf,1,2);
 void log_init(const char *argv0);
 void log_file(const char *name);
-void log_fork(void);
+void log_fork(void);                   /* Call after fork() to update log_pid */
+
+/* If the log name contains metacharacters for date and time, we switch the logs
+ * automatically whenever the name changes. You can disable it and switch explicitly. */
 int log_switch(void);
+void log_switch_disable(void);
+void log_switch_enable(void);
 
 void assert_failed(const char *assertion, const char *file, int line) NONRET;
 void assert_failed_noinfo(void) NONRET;
@@ -124,9 +130,6 @@ void assert_failed_noinfo(void) NONRET;
 #define DBG(x,y...) do { } while(0)
 #endif
 
-static inline void log_switch_disable(void) { log_switch_nest++; }
-static inline void log_switch_enable(void) { ASSERT(log_switch_nest); log_switch_nest--; }
-
 /* Memory allocation */
 
 #define xmalloc sh_xmalloc
index 401e797c3edeca4d4e5a529bc4b0e12debb13c30..0b22ff243e8811618dadf45c201b17b9051f74ec 100644 (file)
@@ -20,7 +20,7 @@
 static char *log_name_patt;
 static int log_params;
 static int log_filename_size;
-volatile int log_switch_nest;
+static int log_switch_nest;
 
 static int
 do_log_switch(struct tm *tm)
@@ -94,6 +94,19 @@ log_fork(void)
   log_pid = getpid();
 }
 
+void
+log_switch_disable(void)
+{
+  log_switch_nest++;
+}
+
+void
+log_switch_enable(void)
+{
+  ASSERT(log_switch_nest);
+  log_switch_nest--;
+}
+
 #ifdef TEST
 
 int main(int argc, char **argv)
index 0063f3ea7eed13d2239f28f85cda35d8a475d927..f3ab51dbfa0dd5d651e1bc637c3b0cb54b075891 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -1,7 +1,7 @@
 /*
  *     UCW Library -- Logging
  *
- *     (c) 1997--2006 Martin Mares <mj@ucw.cz>
+ *     (c) 1997--2008 Martin Mares <mj@ucw.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
@@ -29,27 +29,39 @@ void
 vmsg(unsigned int cat, const char *fmt, va_list args)
 {
   struct timeval tv;
+  int have_tm = 0;
   struct tm tm;
   byte *buf, *p;
   int buflen = 256;
   int l, l0, r;
   va_list args2;
 
-  gettimeofday(&tv, NULL);
-  if (!localtime_r(&tv.tv_sec, &tm))
-    bzero(&tm, sizeof(tm));
+  if (!(cat & L_SIGHANDLER))
+    {
+      /* CAVEAT: These calls are not safe in signal handlers. */
+      gettimeofday(&tv, NULL);
+      if (localtime_r(&tv.tv_sec, &tm))
+       have_tm = 1;
+      if (log_switch_hook)
+       log_switch_hook(&tm);
+    }
 
-  if (log_switch_hook)
-    log_switch_hook(&tm);
   while (1)
     {
       p = buf = alloca(buflen);
-      *p++ = cat;
-      /* We cannot use strftime() here, because it's not re-entrant */
-      p += sprintf(p, " %4d-%02d-%02d %02d:%02d:%02d", tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
-                  tm.tm_hour, tm.tm_min, tm.tm_sec);
-      if (log_precise_timings)
-        p += sprintf(p, ".%06d", (int)tv.tv_usec);
+      *p++ = cat & 0xff;
+      if (have_tm)
+       {
+         p += strftime(p, buflen, " %Y-%m-%d %H:%M:%S", &tm);
+         if (log_precise_timings)
+           p += sprintf(p, ".%06d", (int)tv.tv_usec);
+       }
+      else
+       {
+         p += sprintf(p, " \?\?\?\?-\?\?-\?\? \?\?:\?\?:\?\?");
+         if (log_precise_timings)
+           p += sprintf(p, ".\?\?\?\?\?\?");
+       }
       *p++ = ' ';
       if (log_title)
        {
index bd1a7cc53f94ad5297beb1b9cd39c07441866d29..4ab9e7276c0a85de4871d8a65ae57ab680d821c1 100644 (file)
@@ -16,7 +16,7 @@ BEGIN {
        our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
        $VERSION = 1.0;
        @ISA = qw(Exporter);
-       @EXPORT = qw(&Init &Log &Notice &Warn &Fail &IsSet &Set &UnSet &Append &Override &Get &Test &Include &Finish &FindFile &TryFindFile);
+       @EXPORT = qw(&Init &Log &Notice &Warn &Fail &IsSet &IsGiven &Set &UnSet &Append &Override &Get &Test &Include &Finish &FindFile &TryFindFile &TryCmd &PkgConfig &TrivConfig);
        @EXPORT_OK = qw();
        %EXPORT_TAGS = ();
 }
@@ -46,6 +46,11 @@ sub IsSet($) {
        return exists $vars{$x};
 }
 
+sub IsGiven($) {
+       my ($x) = @_;
+       return exists $overriden{$x};
+}
+
 sub Get($) {
        my ($x) = @_;
        return $vars{$x};
@@ -103,15 +108,19 @@ sub FindFile($) {
 
 sub Init($$) {
        my ($srcdir,$defconfig) = @_;
-       if ((!defined $defconfig && !@ARGV) || @ARGV && $ARGV[0] eq "--help") {
-               print STDERR "Usage: [<srcdir>/]configure " . (defined $defconfig ? "[" : "") . "<config-name>" . (defined $defconfig ? "]" : "") .
+       sub usage($) {
+               my ($dc) = @_;
+               print STDERR "Usage: [<srcdir>/]configure " . (defined $dc ? "[" : "") . "<config-name>" . (defined $dc ? "]" : "") .
                        " [<option>[=<value>] | -<option>] ...\n";
                exit 1;
        }
-       if (@ARGV && $ARGV[0] !~ /=/) {
-               Set('CONFIG' => shift @ARGV);
-       } else {
-               Set('CONFIG' => $defconfig);
+       Set('CONFIG' => $defconfig) if defined $defconfig;
+       if (@ARGV) {
+               usage($defconfig) if $ARGV[0] eq "--help";
+               if (!defined($defconfig) || $ARGV[0] !~ /^-?[A-Z][A-Z0-9_]*(=|$)/) {
+                       # This does not look like an option, so read it as a file name
+                       Set('CONFIG' => shift @ARGV);
+               }
        }
        Set("SRCDIR", $srcdir);
 
@@ -129,6 +138,7 @@ sub Init($$) {
                }
        }
 
+       defined Get("CONFIG") or usage($defconfig);
        if (!TryFindFile(Get("CONFIG"))) {
                TryFindFile(Get("CONFIG")."/config") or Fail "Cannot find configuration " . Get("CONFIG");
                Override("CONFIG" => Get("CONFIG")."/config");
@@ -187,4 +197,84 @@ sub Finish() {
        Log "done\n";
 }
 
+sub TryCmd($) {
+       my ($cmd) = @_;
+       my $res = `$cmd`;
+       chomp $res;
+       return $res unless $?;
+       return;
+}
+
+sub maybe_manually($) {
+       my ($n) = @_;
+       if (IsGiven($n)) {
+               if (Get("$n")) { Log "YES (set manually)\n"; }
+               else { Log "NO (set manually)\n"; }
+               return 1;
+       }
+       return 0;
+}
+
+sub PkgConfig($@) {
+       my $pkg = shift @_;
+       my %opts = @_;
+       my $upper = $pkg; $upper =~ tr/a-z/A-Z/; $upper =~ s/[^0-9A-Z]+/_/g;
+       Log "Checking for package $pkg ... ";
+       maybe_manually("CONFIG_HAVE_$upper") and return Get("CONFIG_HAVE_$upper");
+       my $ver = TryCmd("pkg-config --modversion $pkg 2>/dev/null");
+       if (!defined $ver) {
+               Log("NONE\n");
+               return 0;
+       }
+       if (defined($opts{minversion})) {
+               my $min = $opts{minversion};
+               if (!defined TryCmd("pkg-config --atleast-version=$min $pkg")) {
+                       Log("NO: version $ver is too old (need >= $min)\n");
+                       return 0;
+               }
+       }
+       Log("YES: version $ver\n");
+       Set("CONFIG_HAVE_$upper" => 1);
+       Set("CONFIG_VER_$upper" => $ver);
+       my $cf = TryCmd("pkg-config --cflags $pkg");
+       Set("CFLAGS_$upper" => $cf) if defined $cf;
+       my $lf = TryCmd("pkg-config --libs $pkg");
+       Set("LIBS_$upper" => $lf) if defined $lf;
+       return 1;
+}
+
+sub ver_norm($) {
+       my ($v) = @_;
+       return join(".", map { sprintf("%05s", $_) } split(/\./, $v));
+}
+
+sub TrivConfig($@) {
+       my $pkg = shift @_;
+       my %opts = @_;
+       my $upper = $pkg; $upper =~ tr/a-z/A-Z/; $upper =~ s/[^0-9A-Z]+/_/g;
+       Log "Checking for package $pkg ... ";
+       maybe_manually("CONFIG_HAVE_$upper") and return Get("CONFIG_HAVE_$upper");
+       my $pc = $opts{script};
+       my $ver = TryCmd("$pc --version 2>/dev/null");
+       if (!defined $ver) {
+               Log("NONE\n");
+               return 0;
+       }
+       if (defined($opts{minversion})) {
+               my $min = $opts{minversion};
+               if (ver_norm($ver) lt ver_norm($min)) {
+                       Log("NO: version $ver is too old (need >= $min)\n");
+                       return 0;
+               }
+       }
+       Log("YES: version $ver\n");
+       Set("CONFIG_HAVE_$upper" => 1);
+       Set("CONFIG_VER_$upper" => $ver);
+       my $cf = TryCmd("$pc --cflags");
+       Set("CFLAGS_$upper" => $cf) if defined $cf;
+       my $lf = TryCmd("$pc --libs");
+       Set("LIBS_$upper" => $lf) if defined $lf;
+       return 1;
+}
+
 1;  # OK
index 270fb590b5e7fc8873afefc2d5c898c97a1d1287..cfabd4d0b6043cc7a63884fc4294a8cefe922871 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
-#if defined(CONFIG_OWN_REGEX) || defined(CONFIG_POSIX_REGEX)
+#ifdef CONFIG_POSIX_REGEX
 
 /* POSIX regular expression library */
 
-#ifdef CONFIG_OWN_REGEX
-#include "lib/regex/regex-sh.h"
-#else
 #include <regex.h>
-#endif
 
 struct regex {
   regex_t rx;
diff --git a/lib/regex/Makefile b/lib/regex/Makefile
deleted file mode 100644 (file)
index 730b249..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# Makefile for the UCW Regex Library (c) 2004 Martin Mares <mj@ucw.cz>
-
-DIRS+=lib/regex
-
-LIBUCW_MODS+=regex/regex
-
-$(o)/lib/regex/regex.o $(o)/lib/regex/regex.oo: CWARNS=
diff --git a/lib/regex/README b/lib/regex/README
deleted file mode 100644 (file)
index f8c2605..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-This directory contains regular expression routines from the GNU libc 2.3.2
-which are significantly faster than the default regex libraries on most systems.
-
-They are distributed under the GNU LGPL.
-
-All files are exact copies of the original distribution, I only provided my
-own regex.c, regex-sh.h and Makefile.
-
-                                       Martin Mares, March 2004
diff --git a/lib/regex/regcomp.c b/lib/regex/regcomp.c
deleted file mode 100644 (file)
index f25ecae..0000000
+++ /dev/null
@@ -1,3544 +0,0 @@
-/* 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>.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
-                                         int 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, int pat_len);
-static reg_errcode_t init_word_char (re_dfa_t *dfa);
-#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);
-static reg_errcode_t analyze (re_dfa_t *dfa);
-static reg_errcode_t analyze_tree (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_first (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_next (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_epsdest (re_dfa_t *dfa, bin_tree_t *node);
-static reg_errcode_t duplicate_node_closure (re_dfa_t *dfa, int top_org_node,
-                                            int top_clone_node, int root_node,
-                                            unsigned int constraint);
-static reg_errcode_t duplicate_node (int *new_idx, re_dfa_t *dfa, int org_idx,
-                                    unsigned int constraint);
-static int search_duplicated_node (re_dfa_t *dfa, int org_node,
-                                  unsigned int constraint);
-static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
-static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
-                                        int node, int root);
-static void calc_inveclosure (re_dfa_t *dfa);
-static int fetch_number (re_string_t *input, re_token_t *token,
-                        reg_syntax_t syntax);
-static re_token_t fetch_token (re_string_t *input, reg_syntax_t syntax);
-static int peek_token (re_token_t *token, re_string_t *input,
-                       reg_syntax_t syntax);
-static int peek_token_bracket (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,
-                                 int nest, reg_errcode_t *err);
-static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
-                                re_token_t *token, reg_syntax_t syntax,
-                                int nest, reg_errcode_t *err);
-static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
-                                    re_token_t *token, reg_syntax_t syntax,
-                                    int nest, reg_errcode_t *err);
-static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
-                                 re_token_t *token, reg_syntax_t syntax,
-                                 int nest, reg_errcode_t *err);
-static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
-                                re_dfa_t *dfa, re_token_t *token,
-                                reg_syntax_t syntax, reg_errcode_t *err);
-static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
-                                     re_token_t *token, reg_syntax_t syntax,
-                                     reg_errcode_t *err);
-static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
-                                           re_string_t *regexp,
-                                           re_token_t *token, int token_len,
-                                           re_dfa_t *dfa,
-                                           reg_syntax_t syntax);
-static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
-                                         re_string_t *regexp,
-                                         re_token_t *token);
-#ifndef _LIBC
-# ifdef RE_ENABLE_I18N
-static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset,
-                                     re_charset_t *mbcset, int *range_alloc,
-                                     bracket_elem_t *start_elem,
-                                     bracket_elem_t *end_elem);
-static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset,
-                                            re_charset_t *mbcset,
-                                            int *coll_sym_alloc,
-                                            const unsigned char *name);
-# else /* not RE_ENABLE_I18N */
-static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset,
-                                     bracket_elem_t *start_elem,
-                                     bracket_elem_t *end_elem);
-static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset,
-                                            const unsigned char *name);
-# endif /* not RE_ENABLE_I18N */
-#endif /* not _LIBC */
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset,
-                                       re_charset_t *mbcset,
-                                       int *equiv_class_alloc,
-                                       const unsigned char *name);
-static reg_errcode_t build_charclass (re_bitset_ptr_t sbcset,
-                                     re_charset_t *mbcset,
-                                     int *char_class_alloc,
-                                     const unsigned char *class_name,
-                                     reg_syntax_t syntax);
-#else  /* not RE_ENABLE_I18N */
-static reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset,
-                                       const unsigned char *name);
-static reg_errcode_t build_charclass (re_bitset_ptr_t sbcset,
-                                     const unsigned char *class_name,
-                                     reg_syntax_t syntax);
-#endif /* not RE_ENABLE_I18N */
-static bin_tree_t *build_word_op (re_dfa_t *dfa, int not, reg_errcode_t *err);
-static void free_bin_tree (bin_tree_t *tree);
-static bin_tree_t *create_tree (bin_tree_t *left, bin_tree_t *right,
-                               re_token_type_t type, int index);
-static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
-\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 `allocated' (and perhaps `buffer') and `translate' fields
-   are set in BUFP on entry.  */
-
-const char *
-re_compile_pattern (pattern, length, bufp)
-    const char *pattern;
-    size_t length;
-    struct re_pattern_buffer *bufp;
-{
-  reg_errcode_t ret;
-
-  /* And GNU code determines whether or not to get register information
-     by passing null for the REGS argument to re_match, etc., not by
-     setting no_sub.  */
-  bufp->no_sub = 0;
-
-  /* Match anchors at newline.  */
-  bufp->newline_anchor = 1;
-
-  ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
-
-  if (!ret)
-    return NULL;
-  return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
-}
-#ifdef _LIBC
-weak_alias (__re_compile_pattern, re_compile_pattern)
-#endif
-
-/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
-   also be assigned to arbitrarily: each pattern buffer stores its own
-   syntax, so it can be changed between regex compilations.  */
-/* This has no initializer because initialized variables in Emacs
-   become read-only after dumping.  */
-reg_syntax_t re_syntax_options;
-
-
-/* Specify the precise syntax of regexps for compilation.  This provides
-   for compatibility for various utilities which historically have
-   different, incompatible syntaxes.
-
-   The argument SYNTAX is a bit mask comprised of the various bits
-   defined in regex.h.  We return the old syntax.  */
-
-reg_syntax_t
-re_set_syntax (syntax)
-    reg_syntax_t syntax;
-{
-  reg_syntax_t ret = re_syntax_options;
-
-  re_syntax_options = syntax;
-  return ret;
-}
-#ifdef _LIBC
-weak_alias (__re_set_syntax, re_set_syntax)
-#endif
-
-int
-re_compile_fastmap (bufp)
-    struct re_pattern_buffer *bufp;
-{
-  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
-  char *fastmap = bufp->fastmap;
-
-  memset (fastmap, '\0', sizeof (char) * SBC_MAX);
-  re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
-  if (dfa->init_state != dfa->init_state_word)
-    re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
-  if (dfa->init_state != dfa->init_state_nl)
-    re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
-  if (dfa->init_state != dfa->init_state_begbuf)
-    re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
-  bufp->fastmap_accurate = 1;
-  return 0;
-}
-#ifdef _LIBC
-weak_alias (__re_compile_fastmap, re_compile_fastmap)
-#endif
-
-static inline void
-re_set_fastmap (char *fastmap, int icase, int ch)
-{
-  fastmap[ch] = 1;
-  if (icase)
-    fastmap[tolower (ch)] = 1;
-}
-
-/* Helper function for re_compile_fastmap.
-   Compile fastmap for the initial_state INIT_STATE.  */
-
-static void
-re_compile_fastmap_iter (bufp, init_state, fastmap)
-     regex_t *bufp;
-     const re_dfastate_t *init_state;
-     char *fastmap;
-{
-  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
-  int node_cnt;
-  int icase = (MB_CUR_MAX == 1 && (bufp->syntax & RE_ICASE));
-  for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
-    {
-      int node = init_state->nodes.elems[node_cnt];
-      re_token_type_t type = dfa->nodes[node].type;
-
-      if (type == CHARACTER)
-       re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
-      else if (type == SIMPLE_BRACKET)
-       {
-         int i, j, ch;
-         for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
-           for (j = 0; j < UINT_BITS; ++j, ++ch)
-             if (dfa->nodes[node].opr.sbcset[i] & (1 << j))
-               re_set_fastmap (fastmap, icase, ch);
-       }
-#ifdef RE_ENABLE_I18N
-      else if (type == COMPLEX_BRACKET)
-       {
-         int i;
-         re_charset_t *cset = dfa->nodes[node].opr.mbcset;
-         if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes
-             || cset->nranges || cset->nchar_classes)
-           {
-# ifdef _LIBC
-             if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)
-               {
-                 /* In this case we want to catch the bytes which are
-                    the first byte of any collation elements.
-                    e.g. In da_DK, we want to catch 'a' since "aa"
-                         is a valid collation element, and don't catch
-                         'b' since 'b' is the only collation element
-                         which starts from 'b'.  */
-                 int j, ch;
-                 const int32_t *table = (const int32_t *)
-                   _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
-                 for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
-                   for (j = 0; j < UINT_BITS; ++j, ++ch)
-                     if (table[ch] < 0)
-                       re_set_fastmap (fastmap, icase, ch);
-               }
-# else
-             if (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));
-             __wcrtomb (buf, cset->mbchars[i], &state);
-             re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
-           }
-       }
-#endif /* RE_ENABLE_I18N */
-      else if (type == END_OF_RE || type == OP_PERIOD)
-       {
-         memset (fastmap, '\1', sizeof (char) * SBC_MAX);
-         if (type == END_OF_RE)
-           bufp->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
-
-     `buffer' to the compiled pattern;
-     `used' to the length of the compiled pattern;
-     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
-       REG_EXTENDED bit in CFLAGS is set; otherwise, to
-       RE_SYNTAX_POSIX_BASIC;
-     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
-     `fastmap' to an allocated space for the fastmap;
-     `fastmap_accurate' to zero;
-     `re_nsub' to the number of subexpressions in PATTERN.
-
-   PATTERN is the address of the pattern string.
-
-   CFLAGS is a series of bits which affect compilation.
-
-     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
-     use POSIX basic syntax.
-
-     If REG_NEWLINE is set, then . and [^...] don't match newline.
-     Also, regexec will try a match beginning after every newline.
-
-     If REG_ICASE is set, then we considers upper- and lowercase
-     versions of letters to be equivalent when matching.
-
-     If REG_NOSUB is set, then when PREG is passed to regexec, that
-     routine will report only success or failure, and nothing about the
-     registers.
-
-   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
-   the return codes and their meanings.)  */
-
-int
-regcomp (preg, pattern, cflags)
-    regex_t *__restrict preg;
-    const char *__restrict pattern;
-    int cflags;
-{
-  reg_errcode_t ret;
-  reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
-                        : RE_SYNTAX_POSIX_BASIC);
-
-  preg->buffer = NULL;
-  preg->allocated = 0;
-  preg->used = 0;
-
-  /* Try to allocate space for the fastmap.  */
-  preg->fastmap = re_malloc (char, SBC_MAX);
-  if (BE (preg->fastmap == NULL, 0))
-    return REG_ESPACE;
-
-  syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
-
-  /* If REG_NEWLINE is set, newlines are treated differently.  */
-  if (cflags & REG_NEWLINE)
-    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
-      syntax &= ~RE_DOT_NEWLINE;
-      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
-      /* It also changes the matching behavior.  */
-      preg->newline_anchor = 1;
-    }
-  else
-    preg->newline_anchor = 0;
-  preg->no_sub = !!(cflags & REG_NOSUB);
-  preg->translate = NULL;
-
-  ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
-
-  /* POSIX doesn't distinguish between an unmatched open-group and an
-     unmatched close-group: both are REG_EPAREN.  */
-  if (ret == REG_ERPAREN)
-    ret = REG_EPAREN;
-
-  /* We have already checked preg->fastmap != NULL.  */
-  if (BE (ret == REG_NOERROR, 1))
-    /* Compute the fastmap now, since regexec cannot modify the pattern
-       buffer.  This function nevers fails in this implementation.  */
-    (void) re_compile_fastmap (preg);
-  else
-    {
-      /* Some error occurred while compiling the expression.  */
-      re_free (preg->fastmap);
-      preg->fastmap = NULL;
-    }
-
-  return (int) ret;
-}
-#ifdef _LIBC
-weak_alias (__regcomp, regcomp)
-#endif
-
-/* Returns a message corresponding to an error code, ERRCODE, returned
-   from either regcomp or regexec.   We don't use PREG here.  */
-
-size_t
-regerror (errcode, preg, errbuf, errbuf_size)
-    int errcode;
-    const regex_t *preg;
-    char *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
-
-
-static void
-free_dfa_content (re_dfa_t *dfa)
-{
-  int i, j;
-
-  re_free (dfa->subexps);
-
-  for (i = 0; i < dfa->nodes_len; ++i)
-    {
-      re_token_t *node = dfa->nodes + i;
-#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);
-    }
-  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);
-
-  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);
-
-  if (dfa->word_char != NULL)
-    re_free (dfa->word_char);
-#ifdef DEBUG
-  re_free (dfa->re_str);
-#endif
-
-  re_free (dfa);
-}
-
-
-/* Free dynamically allocated space used by PREG.  */
-
-void
-regfree (preg)
-    regex_t *preg;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  if (BE (dfa != NULL, 1))
-    free_dfa_content (dfa);
-
-  re_free (preg->fastmap);
-}
-#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 (s)
-     const char *s;
-{
-  reg_errcode_t ret;
-  char *fastmap;
-
-  if (!s)
-    {
-      if (!re_comp_buf.buffer)
-       return gettext ("No previous regular expression");
-      return 0;
-    }
-
-  if (re_comp_buf.buffer)
-    {
-      fastmap = re_comp_buf.fastmap;
-      re_comp_buf.fastmap = NULL;
-      __regfree (&re_comp_buf);
-      memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
-      re_comp_buf.fastmap = fastmap;
-    }
-
-  if (re_comp_buf.fastmap == NULL)
-    {
-      re_comp_buf.fastmap = (char *) malloc (SBC_MAX);
-      if (re_comp_buf.fastmap == NULL)
-       return (char *) gettext (__re_error_msgid
-                                + __re_error_msgid_idx[(int) REG_ESPACE]);
-    }
-
-  /* Since `re_exec' always passes NULL for the `regs' argument, we
-     don't need to initialize the pattern buffer fields which affect it.  */
-
-  /* Match anchors at newlines.  */
-  re_comp_buf.newline_anchor = 1;
-
-  ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
-
-  if (!ret)
-    return NULL;
-
-  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
-  return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
-}
-
-#ifdef _LIBC
-libc_freeres_fn (free_mem)
-{
-  __regfree (&re_comp_buf);
-}
-#endif
-
-#endif /* _REGEX_RE_COMP */
-\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 (preg, pattern, length, syntax)
-     regex_t *preg;
-     const char * pattern;
-     int length;
-     reg_syntax_t syntax;
-{
-  reg_errcode_t err = REG_NOERROR;
-  re_dfa_t *dfa;
-  re_string_t regexp;
-
-  /* Initialize the pattern buffer.  */
-  preg->fastmap_accurate = 0;
-  preg->syntax = syntax;
-  preg->not_bol = preg->not_eol = 0;
-  preg->used = 0;
-  preg->re_nsub = 0;
-  preg->can_be_null = 0;
-  preg->regs_allocated = REGS_UNALLOCATED;
-
-  /* Initialize the dfa.  */
-  dfa = (re_dfa_t *) preg->buffer;
-  if (preg->allocated < sizeof (re_dfa_t))
-    {
-      /* If zero allocated, but buffer is non-null, try to realloc
-        enough space.  This loses if buffer's address is bogus, but
-        that is the user's responsibility.  If ->buffer is NULL this
-        is a simple allocation.  */
-      dfa = re_realloc (preg->buffer, re_dfa_t, 1);
-      if (dfa == NULL)
-       return REG_ESPACE;
-      preg->allocated = sizeof (re_dfa_t);
-    }
-  preg->buffer = (unsigned char *) dfa;
-  preg->used = sizeof (re_dfa_t);
-
-  err = init_dfa (dfa, length);
-  if (BE (err != REG_NOERROR, 0))
-    {
-      re_free (dfa);
-      preg->buffer = NULL;
-      preg->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->translate,
-                            syntax & RE_ICASE);
-  if (BE (err != REG_NOERROR, 0))
-    {
-      re_free (dfa);
-      preg->buffer = NULL;
-      preg->allocated = 0;
-      return err;
-    }
-
-  /* Parse the regular expression, and build a structure tree.  */
-  preg->re_nsub = 0;
-  dfa->str_tree = parse (&regexp, preg, syntax, &err);
-  if (BE (dfa->str_tree == NULL, 0))
-    goto re_compile_internal_free_return;
-
-  /* Analyze the tree and collect information which is necessary to
-     create the dfa.  */
-  err = analyze (dfa);
-  if (BE (err != REG_NOERROR, 0))
-    goto re_compile_internal_free_return;
-
-  /* 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))
-    {
-    re_compile_internal_free_return:
-      free_dfa_content (dfa);
-      preg->buffer = NULL;
-      preg->allocated = 0;
-    }
-
-  return err;
-}
-
-/* Initialize DFA.  We use the length of the regular expression PAT_LEN
-   as the initial length of some arrays.  */
-
-static reg_errcode_t
-init_dfa (dfa, pat_len)
-     re_dfa_t *dfa;
-     int pat_len;
-{
-  int table_size;
-
-  memset (dfa, '\0', sizeof (re_dfa_t));
-
-  dfa->nodes_alloc = pat_len + 1;
-  dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
-
-  dfa->states_alloc = pat_len + 1;
-
-  /*  table_size = 2 ^ ceil(log pat_len) */
-  for (table_size = 1; table_size > 0; table_size <<= 1)
-    if (table_size > pat_len)
-      break;
-
-  dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
-  dfa->state_hash_mask = table_size - 1;
-
-  dfa->subexps_alloc = 1;
-  dfa->subexps = re_malloc (re_subexp_t, dfa->subexps_alloc);
-  dfa->word_char = NULL;
-
-  if (BE (dfa->nodes == NULL || dfa->state_table == NULL
-         || dfa->subexps == NULL, 0))
-    {
-      /* We don't bother to free anything which was allocated.  Very
-        soon the process will go down anyway.  */
-      dfa->subexps = NULL;
-      dfa->state_table = NULL;
-      dfa->nodes = NULL;
-      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 reg_errcode_t
-init_word_char (dfa)
-     re_dfa_t *dfa;
-{
-  int i, j, ch;
-  dfa->word_char = (re_bitset_ptr_t) calloc (sizeof (bitset), 1);
-  if (BE (dfa->word_char == NULL, 0))
-    return REG_ESPACE;
-  for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
-    for (j = 0; j < UINT_BITS; ++j, ++ch)
-      if (isalnum (ch) || ch == '_')
-       dfa->word_char[i] |= 1 << j;
-  return REG_NOERROR;
-}
-
-/* Free the work area which are only used while compiling.  */
-
-static void
-free_workarea_compile (preg)
-     regex_t *preg;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  free_bin_tree (dfa->str_tree);
-  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 (dfa)
-     re_dfa_t *dfa;
-{
-  int first, i;
-  reg_errcode_t err;
-  re_node_set init_nodes;
-
-  /* Initial states have the epsilon closure of the node which is
-     the first node of the regular expression.  */
-  first = dfa->str_tree->first;
-  dfa->init_node = first;
-  err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
-  if (BE (err != REG_NOERROR, 0))
-    return err;
-
-  /* The back-references which are in initial states can epsilon transit,
-     since in this case all of the subexpressions can be null.
-     Then we add epsilon closures of the nodes which are the next nodes of
-     the back-references.  */
-  if (dfa->nbackref > 0)
-    for (i = 0; i < init_nodes.nelem; ++i)
-      {
-       int node_idx = init_nodes.elems[i];
-       re_token_type_t type = dfa->nodes[node_idx].type;
-
-       int clexp_idx;
-       if (type != OP_BACK_REF)
-         continue;
-       for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
-         {
-           re_token_t *clexp_node;
-           clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
-           if (clexp_node->type == OP_CLOSE_SUBEXP
-               && clexp_node->opr.idx + 1 == dfa->nodes[node_idx].opr.idx)
-             break;
-         }
-       if (clexp_idx == init_nodes.nelem)
-         continue;
-
-       if (type == OP_BACK_REF)
-         {
-           int dest_idx = dfa->edests[node_idx].elems[0];
-           if (!re_node_set_contains (&init_nodes, dest_idx))
-             {
-               re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
-               i = 0;
-             }
-         }
-      }
-
-  /* It must be the first time to invoke acquire_state.  */
-  dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
-  /* We don't check ERR here, since the initial state must not be NULL.  */
-  if (BE (dfa->init_state == NULL, 0))
-    return err;
-  if (dfa->init_state->has_constraint)
-    {
-      dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
-                                                      CONTEXT_WORD);
-      dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
-                                                    CONTEXT_NEWLINE);
-      dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
-                                                        &init_nodes,
-                                                        CONTEXT_NEWLINE
-                                                        | CONTEXT_BEGBUF);
-      if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL
-             || dfa->init_state_begbuf == NULL, 0))
-       return err;
-    }
-  else
-    dfa->init_state_word = dfa->init_state_nl
-      = dfa->init_state_begbuf = dfa->init_state;
-
-  re_node_set_free (&init_nodes);
-  return REG_NOERROR;
-}
-\f
-/* Analyze the structure tree, and calculate "first", "next", "edest",
-   "eclosure", and "inveclosure".  */
-
-static reg_errcode_t
-analyze (dfa)
-     re_dfa_t *dfa;
-{
-  int i;
-  reg_errcode_t ret;
-
-  /* Allocate arrays.  */
-  dfa->nexts = re_malloc (int, dfa->nodes_alloc);
-  dfa->org_indices = re_malloc (int, dfa->nodes_alloc);
-  dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
-  dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
-  dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_alloc);
-  if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
-         || dfa->eclosures == NULL || dfa->inveclosures == NULL, 0))
-    return REG_ESPACE;
-  /* Initialize them.  */
-  for (i = 0; i < dfa->nodes_len; ++i)
-    {
-      dfa->nexts[i] = -1;
-      re_node_set_init_empty (dfa->edests + i);
-      re_node_set_init_empty (dfa->eclosures + i);
-      re_node_set_init_empty (dfa->inveclosures + i);
-    }
-
-  ret = analyze_tree (dfa, dfa->str_tree);
-  if (BE (ret == REG_NOERROR, 1))
-    {
-      ret = calc_eclosure (dfa);
-      if (ret == REG_NOERROR)
-       calc_inveclosure (dfa);
-    }
-  return ret;
-}
-
-/* Helper functions for analyze.
-   This function calculate "first", "next", and "edest" for the subtree
-   whose root is NODE.  */
-
-static reg_errcode_t
-analyze_tree (dfa, node)
-     re_dfa_t *dfa;
-     bin_tree_t *node;
-{
-  reg_errcode_t ret;
-  if (node->first == -1)
-    calc_first (dfa, node);
-  if (node->next == -1)
-    calc_next (dfa, node);
-  if (node->eclosure.nelem == 0)
-    calc_epsdest (dfa, node);
-  /* Calculate "first" etc. for the left child.  */
-  if (node->left != NULL)
-    {
-      ret = analyze_tree (dfa, node->left);
-      if (BE (ret != REG_NOERROR, 0))
-       return ret;
-    }
-  /* Calculate "first" etc. for the right child.  */
-  if (node->right != NULL)
-    {
-      ret = analyze_tree (dfa, node->right);
-      if (BE (ret != REG_NOERROR, 0))
-       return ret;
-    }
-  return REG_NOERROR;
-}
-
-/* Calculate "first" for the node NODE.  */
-static void
-calc_first (dfa, node)
-     re_dfa_t *dfa;
-     bin_tree_t *node;
-{
-  int idx, type;
-  idx = node->node_idx;
-  type = (node->type == 0) ? dfa->nodes[idx].type : node->type;
-
-  switch (type)
-    {
-#ifdef DEBUG
-    case OP_OPEN_BRACKET:
-    case OP_CLOSE_BRACKET:
-    case OP_OPEN_DUP_NUM:
-    case OP_CLOSE_DUP_NUM:
-    case OP_NON_MATCH_LIST:
-    case OP_OPEN_COLL_ELEM:
-    case OP_CLOSE_COLL_ELEM:
-    case OP_OPEN_EQUIV_CLASS:
-    case OP_CLOSE_EQUIV_CLASS:
-    case OP_OPEN_CHAR_CLASS:
-    case OP_CLOSE_CHAR_CLASS:
-      /* These must not be appeared here.  */
-      assert (0);
-#endif
-    case END_OF_RE:
-    case CHARACTER:
-    case OP_PERIOD:
-    case OP_DUP_ASTERISK:
-    case OP_DUP_QUESTION:
-#ifdef RE_ENABLE_I18N
-    case COMPLEX_BRACKET:
-#endif /* RE_ENABLE_I18N */
-    case SIMPLE_BRACKET:
-    case OP_BACK_REF:
-    case ANCHOR:
-    case OP_OPEN_SUBEXP:
-    case OP_CLOSE_SUBEXP:
-      node->first = idx;
-      break;
-    case OP_DUP_PLUS:
-#ifdef DEBUG
-      assert (node->left != NULL);
-#endif
-      if (node->left->first == -1)
-       calc_first (dfa, node->left);
-      node->first = node->left->first;
-      break;
-    case OP_ALT:
-      node->first = idx;
-      break;
-      /* else fall through */
-    default:
-#ifdef DEBUG
-      assert (node->left != NULL);
-#endif
-      if (node->left->first == -1)
-       calc_first (dfa, node->left);
-      node->first = node->left->first;
-      break;
-    }
-}
-
-/* Calculate "next" for the node NODE.  */
-
-static void
-calc_next (dfa, node)
-     re_dfa_t *dfa;
-     bin_tree_t *node;
-{
-  int idx, type;
-  bin_tree_t *parent = node->parent;
-  if (parent == NULL)
-    {
-      node->next = -1;
-      idx = node->node_idx;
-      if (node->type == 0)
-       dfa->nexts[idx] = node->next;
-      return;
-    }
-
-  idx = parent->node_idx;
-  type = (parent->type == 0) ? dfa->nodes[idx].type : parent->type;
-
-  switch (type)
-    {
-    case OP_DUP_ASTERISK:
-    case OP_DUP_PLUS:
-      node->next = idx;
-      break;
-    case CONCAT:
-      if (parent->left == node)
-       {
-         if (parent->right->first == -1)
-           calc_first (dfa, parent->right);
-         node->next = parent->right->first;
-         break;
-       }
-      /* else fall through */
-    default:
-      if (parent->next == -1)
-       calc_next (dfa, parent);
-      node->next = parent->next;
-      break;
-    }
-  idx = node->node_idx;
-  if (node->type == 0)
-    dfa->nexts[idx] = node->next;
-}
-
-/* Calculate "edest" for the node NODE.  */
-
-static void
-calc_epsdest (dfa, node)
-     re_dfa_t *dfa;
-     bin_tree_t *node;
-{
-  int idx;
-  idx = node->node_idx;
-  if (node->type == 0)
-    {
-      if (dfa->nodes[idx].type == OP_DUP_ASTERISK
-         || dfa->nodes[idx].type == OP_DUP_PLUS
-         || dfa->nodes[idx].type == OP_DUP_QUESTION)
-       {
-         if (node->left->first == -1)
-           calc_first (dfa, node->left);
-         if (node->next == -1)
-           calc_next (dfa, node);
-         re_node_set_init_2 (dfa->edests + idx, node->left->first,
-                             node->next);
-       }
-      else if (dfa->nodes[idx].type == OP_ALT)
-       {
-         int left, right;
-         if (node->left != NULL)
-           {
-             if (node->left->first == -1)
-               calc_first (dfa, node->left);
-             left = node->left->first;
-           }
-         else
-           {
-             if (node->next == -1)
-               calc_next (dfa, node);
-             left = node->next;
-           }
-         if (node->right != NULL)
-           {
-             if (node->right->first == -1)
-               calc_first (dfa, node->right);
-             right = node->right->first;
-           }
-         else
-           {
-             if (node->next == -1)
-               calc_next (dfa, node);
-             right = node->next;
-           }
-         re_node_set_init_2 (dfa->edests + idx, left, right);
-       }
-      else if (dfa->nodes[idx].type == ANCHOR
-              || dfa->nodes[idx].type == OP_OPEN_SUBEXP
-              || dfa->nodes[idx].type == OP_CLOSE_SUBEXP
-              || dfa->nodes[idx].type == OP_BACK_REF)
-       re_node_set_init_1 (dfa->edests + idx, node->next);
-    }
-}
-
-/* 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 (dfa, top_org_node, top_clone_node, root_node,
-                       init_constraint)
-     re_dfa_t *dfa;
-     int top_org_node, top_clone_node, root_node;
-     unsigned int init_constraint;
-{
-  reg_errcode_t err;
-  int org_node, clone_node, ret;
-  unsigned int constraint = init_constraint;
-  for (org_node = top_org_node, clone_node = top_clone_node;;)
-    {
-      int org_dest, clone_dest;
-      if (dfa->nodes[org_node].type == OP_BACK_REF)
-       {
-         /* If the back reference epsilon-transit, its destination must
-            also have the constraint.  Then duplicate the epsilon closure
-            of the destination of the back reference, and store it in
-            edests of the back reference.  */
-         org_dest = dfa->nexts[org_node];
-         re_node_set_empty (dfa->edests + clone_node);
-         err = duplicate_node (&clone_dest, dfa, org_dest, constraint);
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-         dfa->nexts[clone_node] = dfa->nexts[org_node];
-         ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
-         if (BE (ret < 0, 0))
-           return REG_ESPACE;
-       }
-      else if (dfa->edests[org_node].nelem == 0)
-       {
-         /* In case of the node can't epsilon-transit, don't duplicate the
-            destination and store the original destination as the
-            destination of the node.  */
-         dfa->nexts[clone_node] = dfa->nexts[org_node];
-         break;
-       }
-      else if (dfa->edests[org_node].nelem == 1)
-       {
-         /* In case of the node can epsilon-transit, and it has only one
-            destination.  */
-         org_dest = dfa->edests[org_node].elems[0];
-         re_node_set_empty (dfa->edests + clone_node);
-         if (dfa->nodes[org_node].type == ANCHOR)
-           {
-             /* In case of the node has another constraint, append it.  */
-             if (org_node == root_node && clone_node != org_node)
-               {
-                 /* ...but if the node is root_node itself, it means the
-                    epsilon closure have a loop, then tie it to the
-                    destination of the root_node.  */
-                 ret = re_node_set_insert (dfa->edests + clone_node,
-                                           org_dest);
-                 if (BE (ret < 0, 0))
-                   return REG_ESPACE;
-                 break;
-               }
-             constraint |= dfa->nodes[org_node].opr.ctx_type;
-           }
-         err = duplicate_node (&clone_dest, dfa, org_dest, constraint);
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-         ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
-         if (BE (ret < 0, 0))
-           return REG_ESPACE;
-       }
-      else /* dfa->edests[org_node].nelem == 2 */
-       {
-         /* In case of the node can epsilon-transit, and it has two
-            destinations. E.g. '|', '*', '+', '?'.   */
-         org_dest = dfa->edests[org_node].elems[0];
-         re_node_set_empty (dfa->edests + clone_node);
-         /* Search for a duplicated node which satisfies the constraint.  */
-         clone_dest = search_duplicated_node (dfa, org_dest, constraint);
-         if (clone_dest == -1)
-           {
-             /* There are no such a duplicated node, create a new one.  */
-             err = duplicate_node (&clone_dest, dfa, org_dest, constraint);
-             if (BE (err != REG_NOERROR, 0))
-               return err;
-             ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
-             if (BE (ret < 0, 0))
-               return REG_ESPACE;
-             err = duplicate_node_closure (dfa, org_dest, clone_dest,
-                                           root_node, constraint);
-             if (BE (err != REG_NOERROR, 0))
-               return err;
-           }
-         else
-           {
-             /* There are a duplicated node which satisfy the constraint,
-                use it to avoid infinite loop.  */
-             ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
-             if (BE (ret < 0, 0))
-               return REG_ESPACE;
-           }
-
-         org_dest = dfa->edests[org_node].elems[1];
-         err = duplicate_node (&clone_dest, dfa, org_dest, constraint);
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-         ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
-         if (BE (ret < 0, 0))
-           return REG_ESPACE;
-       }
-      org_node = org_dest;
-      clone_node = clone_dest;
-    }
-  return REG_NOERROR;
-}
-
-/* Search for a node which is duplicated from the node ORG_NODE, and
-   satisfies the constraint CONSTRAINT.  */
-
-static int
-search_duplicated_node (dfa, org_node, constraint)
-     re_dfa_t *dfa;
-     int org_node;
-     unsigned int constraint;
-{
-  int idx;
-  for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
-    {
-      if (org_node == dfa->org_indices[idx]
-         && constraint == dfa->nodes[idx].constraint)
-       return idx; /* Found.  */
-    }
-  return -1; /* Not found.  */
-}
-
-/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
-   The new index will be stored in NEW_IDX and return REG_NOERROR if succeeded,
-   otherwise return the error code.  */
-
-static reg_errcode_t
-duplicate_node (new_idx, dfa, org_idx, constraint)
-     re_dfa_t *dfa;
-     int *new_idx, org_idx;
-     unsigned int constraint;
-{
-  re_token_t dup;
-  int dup_idx;
-
-  dup = dfa->nodes[org_idx];
-  dup_idx = re_dfa_add_node (dfa, dup, 1);
-  if (BE (dup_idx == -1, 0))
-    return REG_ESPACE;
-  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;
-  re_node_set_init_empty (dfa->edests + dup_idx);
-  re_node_set_init_empty (dfa->eclosures + dup_idx);
-  re_node_set_init_empty (dfa->inveclosures + dup_idx);
-
-  /* Store the index of the original node.  */
-  dfa->org_indices[dup_idx] = org_idx;
-  *new_idx = dup_idx;
-  return REG_NOERROR;
-}
-
-static void
-calc_inveclosure (dfa)
-     re_dfa_t *dfa;
-{
-  int src, idx, dest;
-  for (src = 0; src < dfa->nodes_len; ++src)
-    {
-      for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
-       {
-         dest = dfa->eclosures[src].elems[idx];
-         re_node_set_insert (dfa->inveclosures + dest, src);
-       }
-    }
-}
-
-/* Calculate "eclosure" for all the node in DFA.  */
-
-static reg_errcode_t
-calc_eclosure (dfa)
-     re_dfa_t *dfa;
-{
-  int node_idx, incomplete;
-#ifdef DEBUG
-  assert (dfa->nodes_len > 0);
-#endif
-  incomplete = 0;
-  /* For each nodes, calculate epsilon closure.  */
-  for (node_idx = 0; ; ++node_idx)
-    {
-      reg_errcode_t err;
-      re_node_set eclosure_elem;
-      if (node_idx == dfa->nodes_len)
-       {
-         if (!incomplete)
-           break;
-         incomplete = 0;
-         node_idx = 0;
-       }
-
-#ifdef DEBUG
-      assert (dfa->eclosures[node_idx].nelem != -1);
-#endif
-      /* If we have already calculated, skip it.  */
-      if (dfa->eclosures[node_idx].nelem != 0)
-       continue;
-      /* Calculate epsilon closure of `node_idx'.  */
-      err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-
-      if (dfa->eclosures[node_idx].nelem == 0)
-       {
-         incomplete = 1;
-         re_node_set_free (&eclosure_elem);
-       }
-    }
-  return REG_NOERROR;
-}
-
-/* Calculate epsilon closure of NODE.  */
-
-static reg_errcode_t
-calc_eclosure_iter (new_set, dfa, node, root)
-     re_node_set *new_set;
-     re_dfa_t *dfa;
-     int node, root;
-{
-  reg_errcode_t err;
-  unsigned int constraint;
-  int i, incomplete;
-  re_node_set eclosure;
-  incomplete = 0;
-  err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
-  if (BE (err != REG_NOERROR, 0))
-    return err;
-
-  /* This indicates that we are calculating this node now.
-     We reference this value to avoid infinite loop.  */
-  dfa->eclosures[node].nelem = -1;
-
-  constraint = ((dfa->nodes[node].type == ANCHOR)
-               ? dfa->nodes[node].opr.ctx_type : 0);
-  /* If the current node has constraints, duplicate all nodes.
-     Since they must inherit the constraints.  */
-  if (constraint && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
-    {
-      int 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;
-       int edest = dfa->edests[node].elems[i];
-       /* If calculating the epsilon closure of `edest' is in progress,
-          return intermediate result.  */
-       if (dfa->eclosures[edest].nelem == -1)
-         {
-           incomplete = 1;
-           continue;
-         }
-       /* If we haven't calculated the epsilon closure of `edest' yet,
-          calculate now. Otherwise use calculated epsilon closure.  */
-       if (dfa->eclosures[edest].nelem == 0)
-         {
-           err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0);
-           if (BE (err != REG_NOERROR, 0))
-             return err;
-         }
-       else
-         eclosure_elem = dfa->eclosures[edest];
-       /* Merge the epsilon closure of `edest'.  */
-       re_node_set_merge (&eclosure, &eclosure_elem);
-       /* If the epsilon closure of `edest' is incomplete,
-          the epsilon closure of this node is also incomplete.  */
-       if (dfa->eclosures[edest].nelem == 0)
-         {
-           incomplete = 1;
-           re_node_set_free (&eclosure_elem);
-         }
-      }
-
-  /* Epsilon closures include itself.  */
-  re_node_set_insert (&eclosure, node);
-  if (incomplete && !root)
-    dfa->eclosures[node].nelem = 0;
-  else
-    dfa->eclosures[node] = eclosure;
-  *new_set = eclosure;
-  return REG_NOERROR;
-}
-\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 re_token_t
-fetch_token (input, syntax)
-     re_string_t *input;
-     reg_syntax_t syntax;
-{
-  re_token_t token;
-  int consumed_byte;
-  consumed_byte = peek_token (&token, input, syntax);
-  re_string_skip_bytes (input, consumed_byte);
-  return token;
-}
-
-/* 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 (token, input, syntax)
-     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
-  token->mb_partial = 0;
-  if (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;
-      switch (c2)
-       {
-       case '|':
-         if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
-           token->type = OP_ALT;
-         break;
-       case '1': case '2': case '3': case '4': case '5':
-       case '6': case '7': case '8': case '9':
-         if (!(syntax & RE_NO_BK_REFS))
-           {
-             token->type = OP_BACK_REF;
-             token->opr.idx = c2 - '0';
-           }
-         break;
-       case '<':
-         if (!(syntax & RE_NO_GNU_OPS))
-           {
-             token->type = ANCHOR;
-             token->opr.idx = WORD_FIRST;
-           }
-         break;
-       case '>':
-         if (!(syntax & RE_NO_GNU_OPS))
-           {
-             token->type = ANCHOR;
-             token->opr.idx = WORD_LAST;
-           }
-         break;
-       case 'b':
-         if (!(syntax & RE_NO_GNU_OPS))
-           {
-             token->type = ANCHOR;
-             token->opr.idx = WORD_DELIM;
-           }
-         break;
-       case 'B':
-         if (!(syntax & RE_NO_GNU_OPS))
-           {
-             token->type = ANCHOR;
-             token->opr.idx = INSIDE_WORD;
-           }
-         break;
-       case 'w':
-         if (!(syntax & RE_NO_GNU_OPS))
-           token->type = OP_WORD;
-         break;
-       case 'W':
-         if (!(syntax & RE_NO_GNU_OPS))
-           token->type = OP_NOTWORD;
-         break;
-       case '`':
-         if (!(syntax & RE_NO_GNU_OPS))
-           {
-             token->type = ANCHOR;
-             token->opr.idx = BUF_FIRST;
-           }
-         break;
-       case '\'':
-         if (!(syntax & RE_NO_GNU_OPS))
-           {
-             token->type = ANCHOR;
-             token->opr.idx = BUF_LAST;
-           }
-         break;
-       case '(':
-         if (!(syntax & RE_NO_BK_PARENS))
-           token->type = OP_OPEN_SUBEXP;
-         break;
-       case ')':
-         if (!(syntax & RE_NO_BK_PARENS))
-           token->type = OP_CLOSE_SUBEXP;
-         break;
-       case '+':
-         if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
-           token->type = OP_DUP_PLUS;
-         break;
-       case '?':
-         if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
-           token->type = OP_DUP_QUESTION;
-         break;
-       case '{':
-         if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
-           token->type = OP_OPEN_DUP_NUM;
-         break;
-       case '}':
-         if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
-           token->type = OP_CLOSE_DUP_NUM;
-         break;
-       default:
-         break;
-       }
-      return 2;
-    }
-
-  token->type = CHARACTER;
-  switch (c)
-    {
-    case '\n':
-      if (syntax & RE_NEWLINE_ALT)
-       token->type = OP_ALT;
-      break;
-    case '|':
-      if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
-       token->type = OP_ALT;
-      break;
-    case '*':
-      token->type = OP_DUP_ASTERISK;
-      break;
-    case '+':
-      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
-       token->type = OP_DUP_PLUS;
-      break;
-    case '?':
-      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
-       token->type = OP_DUP_QUESTION;
-      break;
-    case '{':
-      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
-       token->type = OP_OPEN_DUP_NUM;
-      break;
-    case '}':
-      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
-       token->type = OP_CLOSE_DUP_NUM;
-      break;
-    case '(':
-      if (syntax & RE_NO_BK_PARENS)
-       token->type = OP_OPEN_SUBEXP;
-      break;
-    case ')':
-      if (syntax & RE_NO_BK_PARENS)
-       token->type = OP_CLOSE_SUBEXP;
-      break;
-    case '[':
-      token->type = OP_OPEN_BRACKET;
-      break;
-    case '.':
-      token->type = OP_PERIOD;
-      break;
-    case '^':
-      if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
-         re_string_cur_idx (input) != 0)
-       {
-         char prev = re_string_peek_byte (input, -1);
-         if (prev != '|' && prev != '(' &&
-             (!(syntax & RE_NEWLINE_ALT) || prev != '\n'))
-           break;
-       }
-      token->type = ANCHOR;
-      token->opr.idx = LINE_FIRST;
-      break;
-    case '$':
-      if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
-         re_string_cur_idx (input) + 1 != re_string_length (input))
-       {
-         re_token_t next;
-         re_string_skip_bytes (input, 1);
-         peek_token (&next, input, syntax);
-         re_string_skip_bytes (input, -1);
-         if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
-           break;
-       }
-      token->type = ANCHOR;
-      token->opr.idx = 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 (token, input, syntax)
-     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 (MB_CUR_MAX > 1 &&
-      !re_string_first_byte (input, re_string_cur_idx (input)))
-    {
-      token->type = CHARACTER;
-      return 1;
-    }
-#endif /* RE_ENABLE_I18N */
-
-  if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS))
-    {
-      /* 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;
-      c2 = re_string_peek_byte (input, 1);
-      token->opr.c = c2;
-      token_len = 2;
-      switch (c2)
-       {
-       case '.':
-         token->type = OP_OPEN_COLL_ELEM;
-         break;
-       case '=':
-         token->type = OP_OPEN_EQUIV_CLASS;
-         break;
-       case ':':
-         if (syntax & RE_CHAR_CLASSES)
-           {
-             token->type = OP_OPEN_CHAR_CLASS;
-             break;
-           }
-         /* else fall through.  */
-       default:
-         token->type = CHARACTER;
-         token->opr.c = c;
-         token_len = 1;
-         break;
-       }
-      return token_len;
-    }
-  switch (c)
-    {
-    case '-':
-      token->type = OP_CHARSET_RANGE;
-      break;
-    case ']':
-      token->type = OP_CLOSE_BRACKET;
-      break;
-    case '^':
-      token->type = OP_NON_MATCH_LIST;
-      break;
-    default:
-      token->type = CHARACTER;
-    }
-  return 1;
-}
-\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 (regexp, preg, syntax, err)
-     re_string_t *regexp;
-     regex_t *preg;
-     reg_syntax_t syntax;
-     reg_errcode_t *err;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  bin_tree_t *tree, *eor, *root;
-  re_token_t current_token;
-  int new_idx;
-  current_token = fetch_token (regexp, syntax);
-  tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
-  if (BE (*err != REG_NOERROR && tree == NULL, 0))
-    return NULL;
-  new_idx = re_dfa_add_node (dfa, current_token, 0);
-  eor = create_tree (NULL, NULL, 0, new_idx);
-  if (tree != NULL)
-    root = create_tree (tree, eor, CONCAT, 0);
-  else
-    root = eor;
-  if (BE (new_idx == -1 || 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 (regexp, preg, token, syntax, nest, err)
-     re_string_t *regexp;
-     regex_t *preg;
-     re_token_t *token;
-     reg_syntax_t syntax;
-     int nest;
-     reg_errcode_t *err;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  bin_tree_t *tree, *branch = NULL;
-  int new_idx;
-  tree = parse_branch (regexp, preg, token, syntax, nest, err);
-  if (BE (*err != REG_NOERROR && tree == NULL, 0))
-    return NULL;
-
-  while (token->type == OP_ALT)
-    {
-      re_token_t alt_token = *token;
-      new_idx = re_dfa_add_node (dfa, alt_token, 0);
-      *token = fetch_token (regexp, syntax);
-      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))
-           {
-             free_bin_tree (tree);
-             return NULL;
-           }
-       }
-      else
-       branch = NULL;
-      tree = create_tree (tree, branch, 0, new_idx);
-      if (BE (new_idx == -1 || tree == NULL, 0))
-       {
-         *err = REG_ESPACE;
-         return NULL;
-       }
-      dfa->has_plural_match = 1;
-    }
-  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 (regexp, preg, token, syntax, nest, err)
-     re_string_t *regexp;
-     regex_t *preg;
-     re_token_t *token;
-     reg_syntax_t syntax;
-     int nest;
-     reg_errcode_t *err;
-{
-  bin_tree_t *tree, *exp;
-  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))
-       {
-         free_bin_tree (tree);
-         return NULL;
-       }
-      if (tree != NULL && exp != NULL)
-       {
-         tree = create_tree (tree, exp, CONCAT, 0);
-         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 (regexp, preg, token, syntax, nest, err)
-     re_string_t *regexp;
-     regex_t *preg;
-     re_token_t *token;
-     reg_syntax_t syntax;
-     int nest;
-     reg_errcode_t *err;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  bin_tree_t *tree;
-  int new_idx;
-  switch (token->type)
-    {
-    case CHARACTER:
-      new_idx = re_dfa_add_node (dfa, *token, 0);
-      tree = create_tree (NULL, NULL, 0, new_idx);
-      if (BE (new_idx == -1 || tree == NULL, 0))
-       {
-         *err = REG_ESPACE;
-         return NULL;
-       }
-#ifdef RE_ENABLE_I18N
-      if (MB_CUR_MAX > 1)
-       {
-         while (!re_string_eoi (regexp)
-                && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
-           {
-             bin_tree_t *mbc_remain;
-             *token = fetch_token (regexp, syntax);
-             new_idx = re_dfa_add_node (dfa, *token, 0);
-             mbc_remain = create_tree (NULL, NULL, 0, new_idx);
-             tree = create_tree (tree, mbc_remain, CONCAT, 0);
-             if (BE (new_idx == -1 || 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 (preg->re_nsub < token->opr.idx
-             || dfa->subexps[token->opr.idx - 1].end == -1, 0))
-       {
-         *err = REG_ESUBREG;
-         return NULL;
-       }
-      dfa->used_bkref_map |= 1 << (token->opr.idx - 1);
-      new_idx = re_dfa_add_node (dfa, *token, 0);
-      tree = create_tree (NULL, NULL, 0, new_idx);
-      if (BE (new_idx == -1 || tree == NULL, 0))
-       {
-         *err = REG_ESPACE;
-         return NULL;
-       }
-      ++dfa->nbackref;
-      dfa->has_mb_node = 1;
-      break;
-    case OP_DUP_ASTERISK:
-    case OP_DUP_PLUS:
-    case OP_DUP_QUESTION:
-    case OP_OPEN_DUP_NUM:
-      if (syntax & RE_CONTEXT_INVALID_OPS)
-       {
-         *err = REG_BADRPT;
-         return NULL;
-       }
-      else if (syntax & RE_CONTEXT_INDEP_OPS)
-       {
-         *token = fetch_token (regexp, syntax);
-         return parse_expression (regexp, preg, token, syntax, nest, err);
-       }
-      /* else fall through  */
-    case OP_CLOSE_SUBEXP:
-      if ((token->type == OP_CLOSE_SUBEXP) &&
-         !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
-       {
-         *err = REG_ERPAREN;
-         return NULL;
-       }
-      /* else fall through  */
-    case OP_CLOSE_DUP_NUM:
-      /* We treat it as a normal character.  */
-
-      /* Then we can these characters as normal characters.  */
-      token->type = CHARACTER;
-      new_idx = re_dfa_add_node (dfa, *token, 0);
-      tree = create_tree (NULL, NULL, 0, new_idx);
-      if (BE (new_idx == -1 || tree == NULL, 0))
-       {
-         *err = REG_ESPACE;
-         return NULL;
-       }
-      break;
-    case ANCHOR:
-      if (dfa->word_char == NULL)
-       {
-         *err = init_word_char (dfa);
-         if (BE (*err != REG_NOERROR, 0))
-           return NULL;
-       }
-      if (token->opr.ctx_type == WORD_DELIM)
-       {
-         bin_tree_t *tree_first, *tree_last;
-         int idx_first, idx_last;
-         token->opr.ctx_type = WORD_FIRST;
-         idx_first = re_dfa_add_node (dfa, *token, 0);
-         tree_first = create_tree (NULL, NULL, 0, idx_first);
-         token->opr.ctx_type = WORD_LAST;
-         idx_last = re_dfa_add_node (dfa, *token, 0);
-         tree_last = create_tree (NULL, NULL, 0, idx_last);
-         token->type = OP_ALT;
-         new_idx = re_dfa_add_node (dfa, *token, 0);
-         tree = create_tree (tree_first, tree_last, 0, new_idx);
-         if (BE (idx_first == -1 || idx_last == -1 || new_idx == -1
-                 || tree_first == NULL || tree_last == NULL
-                 || tree == NULL, 0))
-           {
-             *err = REG_ESPACE;
-             return NULL;
-           }
-       }
-      else
-       {
-         new_idx = re_dfa_add_node (dfa, *token, 0);
-         tree = create_tree (NULL, NULL, 0, new_idx);
-         if (BE (new_idx == -1 || 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(*)>".  */
-      *token = fetch_token (regexp, syntax);
-      return tree;
-    case OP_PERIOD:
-      new_idx = re_dfa_add_node (dfa, *token, 0);
-      tree = create_tree (NULL, NULL, 0, new_idx);
-      if (BE (new_idx == -1 || tree == NULL, 0))
-       {
-         *err = REG_ESPACE;
-         return NULL;
-       }
-      if (MB_CUR_MAX > 1)
-       dfa->has_mb_node = 1;
-      break;
-    case OP_WORD:
-      tree = build_word_op (dfa, 0, err);
-      if (BE (*err != REG_NOERROR && tree == NULL, 0))
-       return NULL;
-      break;
-    case OP_NOTWORD:
-      tree = build_word_op (dfa, 1, 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;
-    }
-  *token = fetch_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;
-      dfa->has_plural_match = 1;
-    }
-
-  return tree;
-}
-
-/* This function build the following tree, from regular expression
-   (<reg_exp>):
-        SUBEXP
-           |
-       <reg_exp>
-*/
-
-static bin_tree_t *
-parse_sub_exp (regexp, preg, token, syntax, nest, err)
-     re_string_t *regexp;
-     regex_t *preg;
-     re_token_t *token;
-     reg_syntax_t syntax;
-     int nest;
-     reg_errcode_t *err;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  bin_tree_t *tree, *left_par, *right_par;
-  size_t cur_nsub;
-  int new_idx;
-  cur_nsub = preg->re_nsub++;
-  if (dfa->subexps_alloc < preg->re_nsub)
-    {
-      re_subexp_t *new_array;
-      dfa->subexps_alloc *= 2;
-      new_array = re_realloc (dfa->subexps, re_subexp_t, dfa->subexps_alloc);
-      if (BE (new_array == NULL, 0))
-       {
-         dfa->subexps_alloc /= 2;
-         *err = REG_ESPACE;
-         return NULL;
-       }
-      dfa->subexps = new_array;
-    }
-  dfa->subexps[cur_nsub].start = dfa->nodes_len;
-  dfa->subexps[cur_nsub].end = -1;
-
-  new_idx = re_dfa_add_node (dfa, *token, 0);
-  left_par = create_tree (NULL, NULL, 0, new_idx);
-  if (BE (new_idx == -1 || left_par == NULL, 0))
-    {
-      *err = REG_ESPACE;
-      return NULL;
-    }
-  dfa->nodes[new_idx].opr.idx = cur_nsub;
-  *token = fetch_token (regexp, syntax);
-
-  /* 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 && tree == NULL, 0))
-       return NULL;
-    }
-  if (BE (token->type != OP_CLOSE_SUBEXP, 0))
-    {
-      free_bin_tree (tree);
-      *err = REG_BADPAT;
-      return NULL;
-    }
-  new_idx = re_dfa_add_node (dfa, *token, 0);
-  dfa->subexps[cur_nsub].end = dfa->nodes_len;
-  right_par = create_tree (NULL, NULL, 0, new_idx);
-  tree = ((tree == NULL) ? right_par
-         : create_tree (tree, right_par, CONCAT, 0));
-  tree = create_tree (left_par, tree, CONCAT, 0);
-  if (BE (new_idx == -1 || right_par == NULL || tree == NULL, 0))
-    {
-      *err = REG_ESPACE;
-      return NULL;
-    }
-  dfa->nodes[new_idx].opr.idx = cur_nsub;
-
-  return tree;
-}
-
-/* This function parse repetition operators like "*", "+", "{1,3}" etc.  */
-
-static bin_tree_t *
-parse_dup_op (dup_elem, regexp, dfa, token, syntax, err)
-     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;
-{
-  re_token_t dup_token;
-  bin_tree_t *tree = dup_elem, *work_tree;
-  int new_idx, start_idx = re_string_cur_idx (regexp);
-  re_token_t start_token = *token;
-  if (token->type == OP_OPEN_DUP_NUM)
-    {
-      int i;
-      int end = 0;
-      int start = fetch_number (regexp, token, syntax);
-      bin_tree_t *elem;
-      if (start == -1)
-       {
-         if (token->type == CHARACTER && token->opr.c == ',')
-           start = 0; /* We treat "{,m}" as "{0,m}".  */
-         else
-           {
-             *err = REG_BADBR; /* <re>{} is invalid.  */
-             return NULL;
-           }
-       }
-      if (BE (start != -2, 1))
-       {
-         /* We treat "{n}" as "{n,n}".  */
-         end = ((token->type == OP_CLOSE_DUP_NUM) ? start
-                : ((token->type == CHARACTER && token->opr.c == ',')
-                   ? fetch_number (regexp, token, syntax) : -2));
-       }
-      if (BE (start == -2 || end == -2, 0))
-       {
-         /* Invalid sequence.  */
-         if (token->type == OP_CLOSE_DUP_NUM)
-           goto parse_dup_op_invalid_interval;
-         else
-           goto parse_dup_op_ebrace;
-       }
-      if (BE (start == 0 && end == 0, 0))
-       {
-         /* We treat "<re>{0}" and "<re>{0,0}" as null string.  */
-         *token = fetch_token (regexp, syntax);
-         free_bin_tree (dup_elem);
-         return NULL;
-       }
-
-      /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}".  */
-      elem = tree;
-      for (i = 0; i < start; ++i)
-       if (i != 0)
-         {
-           work_tree = duplicate_tree (elem, dfa);
-           tree = create_tree (tree, work_tree, CONCAT, 0);
-           if (BE (work_tree == NULL || tree == NULL, 0))
-             goto parse_dup_op_espace;
-         }
-
-      if (end == -1)
-       {
-         /* We treat "<re>{0,}" as "<re>*".  */
-         dup_token.type = OP_DUP_ASTERISK;
-         if (start > 0)
-           {
-             elem = duplicate_tree (elem, dfa);
-             new_idx = re_dfa_add_node (dfa, dup_token, 0);
-             work_tree = create_tree (elem, NULL, 0, new_idx);
-             tree = create_tree (tree, work_tree, CONCAT, 0);
-             if (BE (elem == NULL || new_idx == -1 || work_tree == NULL
-                     || tree == NULL, 0))
-               goto parse_dup_op_espace;
-           }
-         else
-           {
-             new_idx = re_dfa_add_node (dfa, dup_token, 0);
-             tree = create_tree (elem, NULL, 0, new_idx);
-             if (BE (new_idx == -1 || tree == NULL, 0))
-               goto parse_dup_op_espace;
-           }
-       }
-      else if (end - start > 0)
-       {
-         /* Then extract "<re>{0,m}" to "<re>?<re>?...<re>?".  */
-         dup_token.type = OP_DUP_QUESTION;
-         if (start > 0)
-           {
-             elem = duplicate_tree (elem, dfa);
-             new_idx = re_dfa_add_node (dfa, dup_token, 0);
-             elem = create_tree (elem, NULL, 0, new_idx);
-             tree = create_tree (tree, elem, CONCAT, 0);
-             if (BE (elem == NULL || new_idx == -1 || tree == NULL, 0))
-               goto parse_dup_op_espace;
-           }
-         else
-           {
-             new_idx = re_dfa_add_node (dfa, dup_token, 0);
-             tree = elem = create_tree (elem, NULL, 0, new_idx);
-             if (BE (new_idx == -1 || tree == NULL, 0))
-               goto parse_dup_op_espace;
-           }
-         for (i = 1; i < end - start; ++i)
-           {
-             work_tree = duplicate_tree (elem, dfa);
-             tree = create_tree (tree, work_tree, CONCAT, 0);
-             if (BE (work_tree == NULL || tree == NULL, 0))
-               {
-                 *err = REG_ESPACE;
-                 return NULL;
-               }
-           }
-       }
-    }
-  else
-    {
-      new_idx = re_dfa_add_node (dfa, *token, 0);
-      tree = create_tree (tree, NULL, 0, new_idx);
-      if (BE (new_idx == -1 || tree == NULL, 0))
-       {
-         *err = REG_ESPACE;
-         return NULL;
-       }
-    }
-  *token = fetch_token (regexp, syntax);
-  return tree;
-
- parse_dup_op_espace:
-  free_bin_tree (tree);
-  *err = REG_ESPACE;
-  return NULL;
-
- parse_dup_op_ebrace:
-  if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
-    {
-      *err = REG_EBRACE;
-      return NULL;
-    }
-  goto parse_dup_op_rollback;
- parse_dup_op_invalid_interval:
-  if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
-    {
-      *err = REG_BADBR;
-      return NULL;
-    }
- parse_dup_op_rollback:
-  re_string_set_index (regexp, start_idx);
-  *token = start_token;
-  token->type = CHARACTER;
-  return dup_elem;
-}
-
-/* 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
-# ifdef RE_ENABLE_I18N
-build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
-     re_charset_t *mbcset;
-     int *range_alloc;
-# else /* not RE_ENABLE_I18N */
-build_range_exp (sbcset, start_elem, end_elem)
-# endif /* not RE_ENABLE_I18N */
-     re_bitset_ptr_t sbcset;
-     bracket_elem_t *start_elem, *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, 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);
-    cmp_buf[0] = start_wc;
-    cmp_buf[4] = end_wc;
-    if (wcscoll (cmp_buf, cmp_buf + 4) > 0)
-      return REG_ERANGE;
-
-    /* Check the space of the arrays.  */
-    if (*range_alloc == mbcset->nranges)
-      {
-       /* There are not enough space, need realloc.  */
-       wchar_t *new_array_start, *new_array_end;
-       int new_nranges;
-
-       /* +1 in case of mbcset->nranges is 0.  */
-       new_nranges = 2 * mbcset->nranges + 1;
-       /* Use realloc since mbcset->range_starts and mbcset->range_ends
-          are NULL if *range_alloc == 0.  */
-       new_array_start = re_realloc (mbcset->range_starts, wchar_t,
-                                     new_nranges);
-       new_array_end = re_realloc (mbcset->range_ends, wchar_t,
-                                   new_nranges);
-
-       if (BE (new_array_start == NULL || new_array_end == NULL, 0))
-         return REG_ESPACE;
-
-       mbcset->range_starts = new_array_start;
-       mbcset->range_ends = new_array_end;
-       *range_alloc = new_nranges;
-      }
-
-    mbcset->range_starts[mbcset->nranges] = start_wc;
-    mbcset->range_ends[mbcset->nranges++] = end_wc;
-
-    /* Build the table for single byte characters.  */
-    for (wc = 0; wc <= SBC_MAX; ++wc)
-      {
-       cmp_buf[2] = wc;
-       if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
-           && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
-         bitset_set (sbcset, wc);
-      }
-  }
-# else /* not RE_ENABLE_I18N */
-  {
-    unsigned int ch;
-    start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
-               : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
-                  : 0));
-    end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
-             : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
-                : 0));
-    if (start_ch > end_ch)
-      return REG_ERANGE;
-    /* Build the table for single byte characters.  */
-    for (ch = 0; ch <= SBC_MAX; ++ch)
-      if (start_ch <= ch  && ch <= end_ch)
-       bitset_set (sbcset, ch);
-  }
-# endif /* not RE_ENABLE_I18N */
-  return REG_NOERROR;
-}
-#endif /* not _LIBC */
-
-#ifndef _LIBC
-/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
-   Build the collating element which is represented by NAME.
-   The result are written to MBCSET and SBCSET.
-   COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
-   pointer argument since we may update it.  */
-
-static reg_errcode_t
-# ifdef RE_ENABLE_I18N
-build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)
-     re_charset_t *mbcset;
-     int *coll_sym_alloc;
-# else /* not RE_ENABLE_I18N */
-build_collating_symbol (sbcset, name)
-# endif /* not RE_ENABLE_I18N */
-     re_bitset_ptr_t sbcset;
-     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 (regexp, dfa, token, syntax, err)
-     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.  */
-
-  static inline int32_t
-  seek_collating_symbol_entry (name, name_len)
-        const unsigned char *name;
-        size_t name_len;
-    {
-      int32_t hash = elem_hash ((const char *) name, name_len);
-      int32_t elem = hash % table_size;
-      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.  */
-
-  static inline unsigned int
-  lookup_collation_sequence_value (br_elem)
-        bracket_elem_t *br_elem;
-    {
-      if (br_elem->type == SB_CHAR)
-       {
-         /*
-         if (MB_CUR_MAX == 1)
-         */
-         if (nrules == 0)
-           return collseqmb[br_elem->opr.ch];
-         else
-           {
-             wint_t wc = __btowc (br_elem->opr.ch);
-             return collseq_table_lookup (collseqwc, wc);
-           }
-       }
-      else if (br_elem->type == MB_CHAR)
-       {
-         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.  */
-
-  static inline reg_errcode_t
-# ifdef RE_ENABLE_I18N
-  build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
-        re_charset_t *mbcset;
-        int *range_alloc;
-# else /* not RE_ENABLE_I18N */
-  build_range_exp (sbcset, start_elem, end_elem)
-# endif /* not RE_ENABLE_I18N */
-        re_bitset_ptr_t sbcset;
-        bracket_elem_t *start_elem, *end_elem;
-    {
-      unsigned int ch;
-      uint32_t start_collseq;
-      uint32_t end_collseq;
-
-# ifdef RE_ENABLE_I18N
-      /* Check the space of the arrays.  */
-      if (*range_alloc == mbcset->nranges)
-       {
-         /* There are not enough space, need realloc.  */
-         uint32_t *new_array_start;
-         uint32_t *new_array_end;
-         int new_nranges;
-
-         /* +1 in case of mbcset->nranges is 0.  */
-         new_nranges = 2 * mbcset->nranges + 1;
-         /* Use realloc since mbcset->range_starts and mbcset->range_ends
-            are NULL if *range_alloc == 0.  */
-         new_array_start = re_realloc (mbcset->range_starts, uint32_t,
-                                       new_nranges);
-         new_array_end = re_realloc (mbcset->range_ends, uint32_t,
-                                     new_nranges);
-
-         if (BE (new_array_start == NULL || new_array_end == NULL, 0))
-           return REG_ESPACE;
-
-         mbcset->range_starts = new_array_start;
-         mbcset->range_ends = new_array_end;
-         *range_alloc = new_nranges;
-       }
-# endif /* RE_ENABLE_I18N */
-
-      /* Equivalence Classes and Character Classes can't be a range
-        start/end.  */
-      if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
-             || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
-             0))
-       return REG_ERANGE;
-
-      start_collseq = lookup_collation_sequence_value (start_elem);
-      end_collseq = lookup_collation_sequence_value (end_elem);
-      /* Check start/end collation sequence values.  */
-      if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))
-       return REG_ECOLLATE;
-      if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))
-       return REG_ERANGE;
-
-# ifdef RE_ENABLE_I18N
-      /* Got valid collation sequence values, add them as a new entry.  */
-      mbcset->range_starts[mbcset->nranges] = start_collseq;
-      mbcset->range_ends[mbcset->nranges++] = end_collseq;
-# endif /* RE_ENABLE_I18N */
-
-      /* 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.  */
-
-  static inline reg_errcode_t
-# ifdef RE_ENABLE_I18N
-  build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)
-        re_charset_t *mbcset;
-        int *coll_sym_alloc;
-# else /* not RE_ENABLE_I18N */
-  build_collating_symbol (sbcset, name)
-# endif /* not RE_ENABLE_I18N */
-        re_bitset_ptr_t sbcset;
-        const unsigned char *name;
-    {
-      int32_t elem, idx;
-      size_t name_len = strlen ((const char *) name);
-      if (nrules != 0)
-       {
-         elem = seek_collating_symbol_entry (name, name_len);
-         if (symb_table[2 * elem] != 0)
-           {
-             /* We found the entry.  */
-             idx = symb_table[2 * elem + 1];
-             /* Skip the name of collating element name.  */
-             idx += 1 + extra[idx];
-           }
-         else if (symb_table[2 * elem] == 0 && name_len == 1)
-           {
-             /* No valid character, treat it as a normal
-                character.  */
-             bitset_set (sbcset, name[0]);
-             return REG_NOERROR;
-           }
-         else
-           return REG_ECOLLATE;
-
-# ifdef RE_ENABLE_I18N
-         /* Got valid collation sequence, add it as a new entry.  */
-         /* Check the space of the arrays.  */
-         if (*coll_sym_alloc == mbcset->ncoll_syms)
-           {
-             /* Not enough, realloc it.  */
-             /* +1 in case of mbcset->ncoll_syms is 0.  */
-             *coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
-             /* Use realloc since mbcset->coll_syms is NULL
-                if *alloc == 0.  */
-             mbcset->coll_syms = re_realloc (mbcset->coll_syms, int32_t,
-                                             *coll_sym_alloc);
-             if (BE (mbcset->coll_syms == NULL, 0))
-               return REG_ESPACE;
-           }
-         mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
-# endif /* RE_ENABLE_I18N */
-         return REG_NOERROR;
-       }
-      else
-       {
-         if (BE (name_len != 1, 0))
-           return REG_ECOLLATE;
-         else
-           {
-             bitset_set (sbcset, name[0]);
-             return REG_NOERROR;
-           }
-       }
-    }
-#endif
-
-  re_token_t br_token;
-  re_bitset_ptr_t sbcset;
-#ifdef RE_ENABLE_I18N
-  re_charset_t *mbcset;
-  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
-  int equiv_class_alloc = 0, char_class_alloc = 0;
-#else /* not RE_ENABLE_I18N */
-  int non_match = 0;
-#endif /* not RE_ENABLE_I18N */
-  bin_tree_t *work_tree;
-  int token_len, new_idx;
-#ifdef _LIBC
-  collseqmb = (const unsigned char *)
-    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
-  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-  if (nrules)
-    {
-      /*
-      if (MB_CUR_MAX > 1)
-      */
-       collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
-      table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
-      symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
-                                                 _NL_COLLATE_SYMB_TABLEMB);
-      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
-                                                  _NL_COLLATE_SYMB_EXTRAMB);
-    }
-#endif
-  sbcset = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS);
-#ifdef RE_ENABLE_I18N
-  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
-#endif /* RE_ENABLE_I18N */
-#ifdef RE_ENABLE_I18N
-  if (BE (sbcset == NULL || mbcset == NULL, 0))
-#else
-  if (BE (sbcset == NULL, 0))
-#endif /* RE_ENABLE_I18N */
-    {
-      *err = REG_ESPACE;
-      return NULL;
-    }
-
-  token_len = peek_token_bracket (token, regexp, syntax);
-  if (BE (token->type == END_OF_RE, 0))
-    {
-      *err = REG_BADPAT;
-      goto parse_bracket_exp_free_return;
-    }
-  if (token->type == OP_NON_MATCH_LIST)
-    {
-#ifdef RE_ENABLE_I18N
-      int i;
-      mbcset->non_match = 1;
-#else /* not RE_ENABLE_I18N */
-      non_match = 1;
-#endif /* not RE_ENABLE_I18N */
-      if (syntax & RE_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;
-       }
-#ifdef RE_ENABLE_I18N
-      if (MB_CUR_MAX > 1)
-       for (i = 0; i < SBC_MAX; ++i)
-         if (__btowc (i) == WEOF)
-           bitset_set (sbcset, i);
-#endif /* RE_ENABLE_I18N */
-    }
-
-  /* We treat the first ']' as a normal character.  */
-  if (token->type == OP_CLOSE_BRACKET)
-    token->type = CHARACTER;
-
-  while (1)
-    {
-      bracket_elem_t start_elem, end_elem;
-      unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
-      unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
-      reg_errcode_t ret;
-      int token_len2 = 0, is_range_exp = 0;
-      re_token_t token2;
-
-      start_elem.opr.name = start_name_buf;
-      ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
-                                  syntax);
-      if (BE (ret != REG_NOERROR, 0))
-       {
-         *err = ret;
-         goto parse_bracket_exp_free_return;
-       }
-
-      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_CHARSET_RANGE)
-       {
-         re_string_skip_bytes (regexp, token_len); /* Skip '-'.  */
-         token_len2 = peek_token_bracket (&token2, regexp, syntax);
-         if (BE (token->type == END_OF_RE, 0))
-           {
-             *err = REG_BADPAT;
-             goto parse_bracket_exp_free_return;
-           }
-         if (token2.type == OP_CLOSE_BRACKET)
-           {
-             /* We treat the last '-' as a normal character.  */
-             re_string_skip_bytes (regexp, -token_len);
-             token->type = CHARACTER;
-           }
-         else
-           is_range_exp = 1;
-       }
-
-      if (is_range_exp == 1)
-       {
-         end_elem.opr.name = end_name_buf;
-         ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
-                                      dfa, syntax);
-         if (BE (ret != REG_NOERROR, 0))
-           {
-             *err = ret;
-             goto parse_bracket_exp_free_return;
-           }
-
-         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;
-           }
-         *err = build_range_exp (sbcset,
-#ifdef RE_ENABLE_I18N
-                                 mbcset, &range_alloc,
-#endif /* RE_ENABLE_I18N */
-                                 &start_elem, &end_elem);
-         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 (mbchar_alloc == mbcset->nmbchars)
-               {
-                 /* Not enough, realloc it.  */
-                 /* +1 in case of mbcset->nmbchars is 0.  */
-                 mbchar_alloc = 2 * mbcset->nmbchars + 1;
-                 /* Use realloc since array is NULL if *alloc == 0.  */
-                 mbcset->mbchars = re_realloc (mbcset->mbchars, wchar_t,
-                                               mbchar_alloc);
-                 if (BE (mbcset->mbchars == NULL, 0))
-                   goto parse_bracket_exp_espace;
-               }
-             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 (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 (token->type == OP_CLOSE_BRACKET)
-       break;
-    }
-
-  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
-
-  /* If it is non-matching list.  */
-#ifdef RE_ENABLE_I18N
-  if (mbcset->non_match)
-#else /* not RE_ENABLE_I18N */
-  if (non_match)
-#endif /* not RE_ENABLE_I18N */
-    bitset_not (sbcset);
-
-  /* Build a tree for simple bracket.  */
-  br_token.type = SIMPLE_BRACKET;
-  br_token.opr.sbcset = sbcset;
-  new_idx = re_dfa_add_node (dfa, br_token, 0);
-  work_tree = create_tree (NULL, NULL, 0, new_idx);
-  if (BE (new_idx == -1 || work_tree == NULL, 0))
-    goto parse_bracket_exp_espace;
-
-#ifdef RE_ENABLE_I18N
-  if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
-      || mbcset->nranges || (MB_CUR_MAX > 1 && (mbcset->nchar_classes
-                                               || mbcset->non_match)))
-    {
-      re_token_t alt_token;
-      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;
-      new_idx = re_dfa_add_node (dfa, br_token, 0);
-      mbc_tree = create_tree (NULL, NULL, 0, new_idx);
-      if (BE (new_idx == -1 || mbc_tree == NULL, 0))
-       goto parse_bracket_exp_espace;
-      /* Then join them by ALT node.  */
-      dfa->has_plural_match = 1;
-      alt_token.type = OP_ALT;
-      new_idx = re_dfa_add_node (dfa, alt_token, 0);
-      work_tree = create_tree (work_tree, mbc_tree, 0, new_idx);
-      if (BE (new_idx != -1 && mbc_tree != NULL, 1))
-       return work_tree;
-    }
-  else
-    {
-      free_charset (mbcset);
-      return work_tree;
-    }
-#else /* not RE_ENABLE_I18N */
-  return work_tree;
-#endif /* not RE_ENABLE_I18N */
-
- 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 (elem, regexp, token, token_len, dfa, syntax)
-     bracket_elem_t *elem;
-     re_string_t *regexp;
-     re_token_t *token;
-     int token_len;
-     re_dfa_t *dfa;
-     reg_syntax_t syntax;
-{
-#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);
-  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 (elem, regexp, token)
-     bracket_elem_t *elem;
-     re_string_t *regexp;
-     re_token_t *token;
-{
-  unsigned char ch, delim = token->opr.c;
-  int i = 0;
-  for (;; ++i)
-    {
-      if (re_string_eoi(regexp) || 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 (ch == delim && re_string_peek_byte (regexp, 0) == ']')
-       break;
-      elem->opr.name[i] = ch;
-    }
-  re_string_skip_bytes (regexp, 1);
-  elem->opr.name[i] = '\0';
-  switch (token->type)
-    {
-    case OP_OPEN_COLL_ELEM:
-      elem->type = COLL_SYM;
-      break;
-    case OP_OPEN_EQUIV_CLASS:
-      elem->type = EQUIV_CLASS;
-      break;
-    case OP_OPEN_CHAR_CLASS:
-      elem->type = CHAR_CLASS;
-      break;
-    default:
-      break;
-    }
-  return REG_NOERROR;
-}
-
-  /* Helper function for parse_bracket_exp.
-     Build the equivalence class which is represented by NAME.
-     The result are written to MBCSET and SBCSET.
-     EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
-     is a pointer argument sinse we may update it.  */
-
-static reg_errcode_t
-#ifdef RE_ENABLE_I18N
-build_equiv_class (sbcset, mbcset, equiv_class_alloc, name)
-     re_charset_t *mbcset;
-     int *equiv_class_alloc;
-#else /* not RE_ENABLE_I18N */
-build_equiv_class (sbcset, name)
-#endif /* not RE_ENABLE_I18N */
-     re_bitset_ptr_t sbcset;
-     const unsigned char *name;
-{
-#if defined _LIBC && defined RE_ENABLE_I18N
-  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 (*equiv_class_alloc == mbcset->nequiv_classes)
-       {
-         /* Not enough, realloc it.  */
-         /* +1 in case of mbcset->nequiv_classes is 0.  */
-         *equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
-         /* Use realloc since the array is NULL if *alloc == 0.  */
-         mbcset->equiv_classes = re_realloc (mbcset->equiv_classes, int32_t,
-                                             *equiv_class_alloc);
-         if (BE (mbcset->equiv_classes == NULL, 0))
-           return REG_ESPACE;
-       }
-      mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
-    }
-  else
-#endif /* _LIBC && RE_ENABLE_I18N */
-    {
-      if (BE (strlen ((const char *) name) != 1, 0))
-       return REG_ECOLLATE;
-      bitset_set (sbcset, *name);
-    }
-  return REG_NOERROR;
-}
-
-  /* Helper function for parse_bracket_exp.
-     Build the character class which is represented by NAME.
-     The result are written to MBCSET and SBCSET.
-     CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
-     is a pointer argument sinse we may update it.  */
-
-static reg_errcode_t
-#ifdef RE_ENABLE_I18N
-build_charclass (sbcset, mbcset, char_class_alloc, class_name, syntax)
-     re_charset_t *mbcset;
-     int *char_class_alloc;
-#else /* not RE_ENABLE_I18N */
-build_charclass (sbcset, class_name, syntax)
-#endif /* not RE_ENABLE_I18N */
-     re_bitset_ptr_t sbcset;
-     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 & RE_ICASE)
-      && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
-    name = "alpha";
-
-#ifdef RE_ENABLE_I18N
-  /* Check the space of the arrays.  */
-  if (*char_class_alloc == mbcset->nchar_classes)
-    {
-      /* Not enough, realloc it.  */
-      /* +1 in case of mbcset->nchar_classes is 0.  */
-      *char_class_alloc = 2 * mbcset->nchar_classes + 1;
-      /* Use realloc since array is NULL if *alloc == 0.  */
-      mbcset->char_classes = re_realloc (mbcset->char_classes, wctype_t,
-                                        *char_class_alloc);
-      if (BE (mbcset->char_classes == NULL, 0))
-       return REG_ESPACE;
-    }
-  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))             \
-         bitset_set (sbcset, i);       \
-      }
-
-  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_word_op (dfa, not, err)
-     re_dfa_t *dfa;
-     int not;
-     reg_errcode_t *err;
-{
-  re_bitset_ptr_t sbcset;
-#ifdef RE_ENABLE_I18N
-  re_charset_t *mbcset;
-  int alloc = 0;
-#else /* not RE_ENABLE_I18N */
-  int non_match = 0;
-#endif /* not RE_ENABLE_I18N */
-  reg_errcode_t ret;
-  re_token_t br_token;
-  bin_tree_t *tree;
-  int new_idx;
-
-  sbcset = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS);
-#ifdef RE_ENABLE_I18N
-  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
-#endif /* RE_ENABLE_I18N */
-
-#ifdef RE_ENABLE_I18N
-  if (BE (sbcset == NULL || mbcset == NULL, 0))
-#else /* not RE_ENABLE_I18N */
-  if (BE (sbcset == NULL, 0))
-#endif /* not RE_ENABLE_I18N */
-    {
-      *err = REG_ESPACE;
-      return NULL;
-    }
-
-  if (not)
-    {
-#ifdef RE_ENABLE_I18N
-      int i;
-      /*
-      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
-       bitset_set(cset->sbcset, '\0');
-      */
-      mbcset->non_match = 1;
-      if (MB_CUR_MAX > 1)
-       for (i = 0; i < SBC_MAX; ++i)
-         if (__btowc (i) == WEOF)
-           bitset_set (sbcset, i);
-#else /* not RE_ENABLE_I18N */
-      non_match = 1;
-#endif /* not RE_ENABLE_I18N */
-    }
-
-  /* We don't care the syntax in this case.  */
-  ret = build_charclass (sbcset,
-#ifdef RE_ENABLE_I18N
-                        mbcset, &alloc,
-#endif /* RE_ENABLE_I18N */
-                        (const unsigned char *) "alpha", 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.  */
-  bitset_set (sbcset, '_');
-
-  /* If it is non-matching list.  */
-#ifdef RE_ENABLE_I18N
-  if (mbcset->non_match)
-#else /* not RE_ENABLE_I18N */
-  if (non_match)
-#endif /* not RE_ENABLE_I18N */
-    bitset_not (sbcset);
-
-  /* Build a tree for simple bracket.  */
-  br_token.type = SIMPLE_BRACKET;
-  br_token.opr.sbcset = sbcset;
-  new_idx = re_dfa_add_node (dfa, br_token, 0);
-  tree = create_tree (NULL, NULL, 0, new_idx);
-  if (BE (new_idx == -1 || tree == NULL, 0))
-    goto build_word_op_espace;
-
-#ifdef RE_ENABLE_I18N
-  if (MB_CUR_MAX > 1)
-    {
-      re_token_t alt_token;
-      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;
-      new_idx = re_dfa_add_node (dfa, br_token, 0);
-      mbc_tree = create_tree (NULL, NULL, 0, new_idx);
-      if (BE (new_idx == -1 || mbc_tree == NULL, 0))
-       goto build_word_op_espace;
-      /* Then join them by ALT node.  */
-      alt_token.type = OP_ALT;
-      new_idx = re_dfa_add_node (dfa, alt_token, 0);
-      tree = create_tree (tree, mbc_tree, 0, new_idx);
-      if (BE (new_idx != -1 && mbc_tree != NULL, 1))
-       return tree;
-    }
-  else
-    {
-      free_charset (mbcset);
-      return tree;
-    }
-#else /* not RE_ENABLE_I18N */
-  return tree;
-#endif /* not RE_ENABLE_I18N */
-
- build_word_op_espace:
-  re_free (sbcset);
-#ifdef RE_ENABLE_I18N
-  free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
-  *err = REG_ESPACE;
-  return NULL;
-}
-
-/* This is intended for the expressions like "a{1,3}".
-   Fetch a number from `input', and return the number.
-   Return -1, if the number field is empty like "{,1}".
-   Return -2, If an error is occured.  */
-
-static int
-fetch_number (input, token, syntax)
-     re_string_t *input;
-     re_token_t *token;
-     reg_syntax_t syntax;
-{
-  int num = -1;
-  unsigned char c;
-  while (1)
-    {
-      *token = fetch_token (input, syntax);
-      c = token->opr.c;
-      if (BE (token->type == END_OF_RE, 0))
-       return -2;
-      if (token->type == OP_CLOSE_DUP_NUM || c == ',')
-       break;
-      num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
-            ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));
-      num = (num > RE_DUP_MAX) ? -2 : num;
-    }
-  return num;
-}
-\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 node of tree.
-   Note: This function automatically free left and right if malloc fails.  */
-
-static bin_tree_t *
-create_tree (left, right, type, index)
-     bin_tree_t *left;
-     bin_tree_t *right;
-     re_token_type_t type;
-     int index;
-{
-  bin_tree_t *tree;
-  tree = re_malloc (bin_tree_t, 1);
-  if (BE (tree == NULL, 0))
-    {
-      free_bin_tree (left);
-      free_bin_tree (right);
-      return NULL;
-    }
-  tree->parent = NULL;
-  tree->left = left;
-  tree->right = right;
-  tree->type = type;
-  tree->node_idx = index;
-  tree->first = -1;
-  tree->next = -1;
-  re_node_set_init_empty (&tree->eclosure);
-
-  if (left != NULL)
-    left->parent = tree;
-  if (right != NULL)
-    right->parent = tree;
-  return tree;
-}
-
-/* Free the sub tree pointed by TREE.  */
-
-static void
-free_bin_tree (tree)
-     bin_tree_t *tree;
-{
-  if (tree == NULL)
-    return;
-  /*re_node_set_free (&tree->eclosure);*/
-  free_bin_tree (tree->left);
-  free_bin_tree (tree->right);
-  re_free (tree);
-}
-
-/* Duplicate the node SRC, and return new node.  */
-
-static bin_tree_t *
-duplicate_tree (src, dfa)
-     const bin_tree_t *src;
-     re_dfa_t *dfa;
-{
-  bin_tree_t *left = NULL, *right = NULL, *new_tree;
-  int new_node_idx;
-  /* Since node indies must be according to Post-order of the tree,
-     we must duplicate the left at first.  */
-  if (src->left != NULL)
-    {
-      left = duplicate_tree (src->left, dfa);
-      if (left == NULL)
-       return NULL;
-    }
-
-  /* Secondaly, duplicate the right.  */
-  if (src->right != NULL)
-    {
-      right = duplicate_tree (src->right, dfa);
-      if (right == NULL)
-       {
-         free_bin_tree (left);
-         return NULL;
-       }
-    }
-
-  /* At last, duplicate itself.  */
-  if (src->type == NON_TYPE)
-    {
-      new_node_idx = re_dfa_add_node (dfa, dfa->nodes[src->node_idx], 0);
-      dfa->nodes[new_node_idx].duplicated = 1;
-      if (BE (new_node_idx == -1, 0))
-       {
-         free_bin_tree (left);
-         free_bin_tree (right);
-         return NULL;
-       }
-    }
-  else
-    new_node_idx = src->type;
-
-  new_tree = create_tree (left, right, src->type, new_node_idx);
-  if (BE (new_tree == NULL, 0))
-    {
-      free_bin_tree (left);
-      free_bin_tree (right);
-    }
-  return new_tree;
-}
diff --git a/lib/regex/regex-sh.h b/lib/regex/regex-sh.h
deleted file mode 100644 (file)
index 723d2d8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  Regular Expression Functions from glibc 2.3.2
- *  (renamed to sh_* to avoid clashes with the system libraries)
- */
-
-#ifndef _UCW_REGEX_H
-#define _UCW_REGEX_H
-
-#define regfree sh_regfree
-#define regexec sh_regexec
-#define regcomp sh_regcomp
-#define regerror sh_regerror
-#define re_set_registers sh_re_set_registers
-#define re_match_2 sh_re_match2
-#define re_match sh_re_match
-#define re_search sh_re_search
-#define re_compile_pattern sh_re_compile_pattern
-#define re_set_syntax sh_re_set_syntax
-#define re_search_2 sh_re_search_2
-#define re_compile_fastmap sh_re_compile_fastmap
-
-#include "lib/regex/regex.h"
-
-#endif
diff --git a/lib/regex/regex.c b/lib/regex/regex.c
deleted file mode 100644 (file)
index 7cc5237..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- *  Regular Expression Functions from glibc 2.3.2
- */
-
-#include <sys/types.h>
-#include "regex-sh.h"
-#include "regex_internal.h"
-#include "regex_internal.c"
-#include "regcomp.c"
-#include "regexec.c"
diff --git a/lib/regex/regex.h b/lib/regex/regex.h
deleted file mode 100644 (file)
index fac441d..0000000
+++ /dev/null
@@ -1,574 +0,0 @@
-/* Definitions for data structures and routines for the regular
-   expression library.
-   Copyright (C) 1985,1989-93,1995-98,2000,2001,2002
-   Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#ifndef _REGEX_H
-#define _REGEX_H 1
-
-/* Allow the use in C++ code.  */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* POSIX says that <sys/types.h> must be included (by the caller) before
-   <regex.h>.  */
-
-#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
-/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
-   should be there.  */
-# include <stddef.h>
-#endif
-
-/* The following two types have to be signed and unsigned integer type
-   wide enough to hold a value of a pointer.  For most ANSI compilers
-   ptrdiff_t and size_t should be likely OK.  Still size of these two
-   types is 2 for Microsoft C.  Ugh... */
-typedef long int s_reg_t;
-typedef unsigned long int active_reg_t;
-
-/* The following bits are used to determine the regexp syntax we
-   recognize.  The set/not-set meanings are chosen so that Emacs syntax
-   remains the value 0.  The bits are given in alphabetical order, and
-   the definitions shifted by one from the previous bit; thus, when we
-   add or remove a bit, only one other definition need change.  */
-typedef unsigned long int reg_syntax_t;
-
-/* If this bit is not set, then \ inside a bracket expression is literal.
-   If set, then such a \ quotes the following character.  */
-#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
-
-/* If this bit is not set, then + and ? are operators, and \+ and \? are
-     literals.
-   If set, then \+ and \? are operators and + and ? are literals.  */
-#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
-
-/* If this bit is set, then character classes are supported.  They are:
-     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
-     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
-   If not set, then character classes are not supported.  */
-#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
-
-/* If this bit is set, then ^ and $ are always anchors (outside bracket
-     expressions, of course).
-   If this bit is not set, then it depends:
-        ^  is an anchor if it is at the beginning of a regular
-           expression or after an open-group or an alternation operator;
-        $  is an anchor if it is at the end of a regular expression, or
-           before a close-group or an alternation operator.
-
-   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
-   POSIX draft 11.2 says that * etc. in leading positions is undefined.
-   We already implemented a previous draft which made those constructs
-   invalid, though, so we haven't changed the code back.  */
-#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
-
-/* If this bit is set, then special characters are always special
-     regardless of where they are in the pattern.
-   If this bit is not set, then special characters are special only in
-     some contexts; otherwise they are ordinary.  Specifically,
-     * + ? and intervals are only special when not after the beginning,
-     open-group, or alternation operator.  */
-#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
-
-/* If this bit is set, then *, +, ?, and { cannot be first in an re or
-     immediately after an alternation or begin-group operator.  */
-#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
-
-/* If this bit is set, then . matches newline.
-   If not set, then it doesn't.  */
-#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
-
-/* If this bit is set, then . doesn't match NUL.
-   If not set, then it does.  */
-#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
-
-/* If this bit is set, nonmatching lists [^...] do not match newline.
-   If not set, they do.  */
-#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
-
-/* If this bit is set, either \{...\} or {...} defines an
-     interval, depending on RE_NO_BK_BRACES.
-   If not set, \{, \}, {, and } are literals.  */
-#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
-
-/* If this bit is set, +, ? and | aren't recognized as operators.
-   If not set, they are.  */
-#define RE_LIMITED_OPS (RE_INTERVALS << 1)
-
-/* If this bit is set, newline is an alternation operator.
-   If not set, newline is literal.  */
-#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
-
-/* If this bit is set, then `{...}' defines an interval, and \{ and \}
-     are literals.
-  If not set, then `\{...\}' defines an interval.  */
-#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
-
-/* If this bit is set, (...) defines a group, and \( and \) are literals.
-   If not set, \(...\) defines a group, and ( and ) are literals.  */
-#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
-
-/* If this bit is set, then \<digit> matches <digit>.
-   If not set, then \<digit> is a back-reference.  */
-#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
-
-/* If this bit is set, then | is an alternation operator, and \| is literal.
-   If not set, then \| is an alternation operator, and | is literal.  */
-#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
-
-/* If this bit is set, then an ending range point collating higher
-     than the starting range point, as in [z-a], is invalid.
-   If not set, then when ending range point collates higher than the
-     starting range point, the range is ignored.  */
-#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
-
-/* If this bit is set, then an unmatched ) is ordinary.
-   If not set, then an unmatched ) is invalid.  */
-#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
-
-/* If this bit is set, succeed as soon as we match the whole pattern,
-   without further backtracking.  */
-#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
-
-/* If this bit is set, do not process the GNU regex operators.
-   If not set, then the GNU regex operators are recognized. */
-#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
-
-/* If this bit is set, turn on internal regex debugging.
-   If not set, and debugging was on, turn it off.
-   This only works if regex.c is compiled -DDEBUG.
-   We define this bit always, so that all that's needed to turn on
-   debugging is to recompile regex.c; the calling code can always have
-   this bit set, and it won't affect anything in the normal case. */
-#define RE_DEBUG (RE_NO_GNU_OPS << 1)
-
-/* If this bit is set, a syntactically invalid interval is treated as
-   a string of ordinary characters.  For example, the ERE 'a{1' is
-   treated as 'a\{1'.  */
-#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
-
-/* If this bit is set, then ignore case when matching.
-   If not set, then case is significant.  */
-#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
-
-/* This global variable defines the particular regexp syntax to use (for
-   some interfaces).  When a regexp is compiled, the syntax used is
-   stored in the pattern buffer, so changing this does not affect
-   already-compiled regexps.  */
-extern reg_syntax_t re_syntax_options;
-\f
-/* Define combinations of the above bits for the standard possibilities.
-   (The [[[ comments delimit what gets put into the Texinfo file, so
-   don't delete them!)  */
-/* [[[begin syntaxes]]] */
-#define RE_SYNTAX_EMACS 0
-
-#define RE_SYNTAX_AWK                                                  \
-  (RE_BACKSLASH_ESCAPE_IN_LISTS   | RE_DOT_NOT_NULL                    \
-   | RE_NO_BK_PARENS              | RE_NO_BK_REFS                      \
-   | RE_NO_BK_VBAR                | RE_NO_EMPTY_RANGES                 \
-   | RE_DOT_NEWLINE              | RE_CONTEXT_INDEP_ANCHORS            \
-   | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
-
-#define RE_SYNTAX_GNU_AWK                                              \
-  ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG)        \
-   & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS           \
-       | RE_CONTEXT_INVALID_OPS ))
-
-#define RE_SYNTAX_POSIX_AWK                                            \
-  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS             \
-   | RE_INTERVALS          | RE_NO_GNU_OPS)
-
-#define RE_SYNTAX_GREP                                                 \
-  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES                                \
-   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS                           \
-   | RE_NEWLINE_ALT)
-
-#define RE_SYNTAX_EGREP                                                        \
-  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS                   \
-   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE                   \
-   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS                            \
-   | RE_NO_BK_VBAR)
-
-#define RE_SYNTAX_POSIX_EGREP                                          \
-  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES                    \
-   | RE_INVALID_INTERVAL_ORD)
-
-/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */
-#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
-
-#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
-
-/* Syntax bits common to both basic and extended POSIX regex syntax.  */
-#define _RE_SYNTAX_POSIX_COMMON                                                \
-  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL             \
-   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
-
-#define RE_SYNTAX_POSIX_BASIC                                          \
-  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
-
-/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
-   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
-   isn't minimal, since other operators, such as \`, aren't disabled.  */
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC                                  \
-  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
-
-#define RE_SYNTAX_POSIX_EXTENDED                                       \
-  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS                 \
-   | RE_CONTEXT_INDEP_OPS   | RE_NO_BK_BRACES                          \
-   | RE_NO_BK_PARENS        | RE_NO_BK_VBAR                            \
-   | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
-
-/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
-   removed and RE_NO_BK_REFS is added.  */
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED                               \
-  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS                 \
-   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES                          \
-   | RE_NO_BK_PARENS        | RE_NO_BK_REFS                            \
-   | RE_NO_BK_VBAR         | RE_UNMATCHED_RIGHT_PAREN_ORD)
-/* [[[end syntaxes]]] */
-\f
-/* Maximum number of duplicates an interval can allow.  Some systems
-   (erroneously) define this in other header files, but we want our
-   value, so remove any previous define.  */
-#ifdef RE_DUP_MAX
-# undef RE_DUP_MAX
-#endif
-/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows.  */
-#define RE_DUP_MAX (0x7fff)
-
-
-/* POSIX `cflags' bits (i.e., information for `regcomp').  */
-
-/* If this bit is set, then use extended regular expression syntax.
-   If not set, then use basic regular expression syntax.  */
-#define REG_EXTENDED 1
-
-/* If this bit is set, then ignore case when matching.
-   If not set, then case is significant.  */
-#define REG_ICASE (REG_EXTENDED << 1)
-
-/* If this bit is set, then anchors do not match at newline
-     characters in the string.
-   If not set, then anchors do match at newlines.  */
-#define REG_NEWLINE (REG_ICASE << 1)
-
-/* If this bit is set, then report only success or fail in regexec.
-   If not set, then returns differ between not matching and errors.  */
-#define REG_NOSUB (REG_NEWLINE << 1)
-
-
-/* POSIX `eflags' bits (i.e., information for regexec).  */
-
-/* If this bit is set, then the beginning-of-line operator doesn't match
-     the beginning of the string (presumably because it's not the
-     beginning of a line).
-   If not set, then the beginning-of-line operator does match the
-     beginning of the string.  */
-#define REG_NOTBOL 1
-
-/* Like REG_NOTBOL, except for the end-of-line.  */
-#define REG_NOTEOL (1 << 1)
-
-
-/* If any error codes are removed, changed, or added, update the
-   `re_error_msg' table in regex.c.  */
-typedef enum
-{
-#ifdef _XOPEN_SOURCE
-  REG_ENOSYS = -1,     /* This will never happen for this implementation.  */
-#endif
-
-  REG_NOERROR = 0,     /* Success.  */
-  REG_NOMATCH,         /* Didn't find a match (for regexec).  */
-
-  /* POSIX regcomp return error codes.  (In the order listed in the
-     standard.)  */
-  REG_BADPAT,          /* Invalid pattern.  */
-  REG_ECOLLATE,                /* Not implemented.  */
-  REG_ECTYPE,          /* Invalid character class name.  */
-  REG_EESCAPE,         /* Trailing backslash.  */
-  REG_ESUBREG,         /* Invalid back reference.  */
-  REG_EBRACK,          /* Unmatched left bracket.  */
-  REG_EPAREN,          /* Parenthesis imbalance.  */
-  REG_EBRACE,          /* Unmatched \{.  */
-  REG_BADBR,           /* Invalid contents of \{\}.  */
-  REG_ERANGE,          /* Invalid range end.  */
-  REG_ESPACE,          /* Ran out of memory.  */
-  REG_BADRPT,          /* No preceding re for repetition op.  */
-
-  /* Error codes we've added.  */
-  REG_EEND,            /* Premature end.  */
-  REG_ESIZE,           /* Compiled pattern bigger than 2^16 bytes.  */
-  REG_ERPAREN          /* Unmatched ) or \); not returned from regcomp.  */
-} reg_errcode_t;
-\f
-/* This data structure represents a compiled pattern.  Before calling
-   the pattern compiler, the fields `buffer', `allocated', `fastmap',
-   `translate', and `no_sub' can be set.  After the pattern has been
-   compiled, the `re_nsub' field is available.  All other fields are
-   private to the regex routines.  */
-
-#ifndef RE_TRANSLATE_TYPE
-# define RE_TRANSLATE_TYPE char *
-#endif
-
-struct re_pattern_buffer
-{
-/* [[[begin pattern_buffer]]] */
-       /* Space that holds the compiled pattern.  It is declared as
-          `unsigned char *' because its elements are
-           sometimes used as array indexes.  */
-  unsigned char *buffer;
-
-       /* Number of bytes to which `buffer' points.  */
-  unsigned long int allocated;
-
-       /* Number of bytes actually used in `buffer'.  */
-  unsigned long int used;
-
-        /* Syntax setting with which the pattern was compiled.  */
-  reg_syntax_t syntax;
-
-        /* Pointer to a fastmap, if any, otherwise zero.  re_search uses
-           the fastmap, if there is one, to skip over impossible
-           starting points for matches.  */
-  char *fastmap;
-
-        /* Either a translate table to apply to all characters before
-           comparing them, or zero for no translation.  The translation
-           is applied to a pattern when it is compiled and to a string
-           when it is matched.  */
-  RE_TRANSLATE_TYPE translate;
-
-       /* Number of subexpressions found by the compiler.  */
-  size_t re_nsub;
-
-        /* Zero if this pattern cannot match the empty string, one else.
-           Well, in truth it's used only in `re_search_2', to see
-           whether or not we should use the fastmap, so we don't set
-           this absolutely perfectly; see `re_compile_fastmap' (the
-           `duplicate' case).  */
-  unsigned can_be_null : 1;
-
-        /* If REGS_UNALLOCATED, allocate space in the `regs' structure
-             for `max (RE_NREGS, re_nsub + 1)' groups.
-           If REGS_REALLOCATE, reallocate space if necessary.
-           If REGS_FIXED, use what's there.  */
-#define REGS_UNALLOCATED 0
-#define REGS_REALLOCATE 1
-#define REGS_FIXED 2
-  unsigned regs_allocated : 2;
-
-        /* Set to zero when `regex_compile' compiles a pattern; set to one
-           by `re_compile_fastmap' if it updates the fastmap.  */
-  unsigned fastmap_accurate : 1;
-
-        /* If set, `re_match_2' does not return information about
-           subexpressions.  */
-  unsigned no_sub : 1;
-
-        /* If set, a beginning-of-line anchor doesn't match at the
-           beginning of the string.  */
-  unsigned not_bol : 1;
-
-        /* Similarly for an end-of-line anchor.  */
-  unsigned not_eol : 1;
-
-        /* If true, an anchor at a newline matches.  */
-  unsigned newline_anchor : 1;
-
-/* [[[end pattern_buffer]]] */
-};
-
-typedef struct re_pattern_buffer regex_t;
-\f
-/* Type for byte offsets within the string.  POSIX mandates this.  */
-typedef int regoff_t;
-
-
-/* This is the structure we store register match data in.  See
-   regex.texinfo for a full description of what registers match.  */
-struct re_registers
-{
-  unsigned num_regs;
-  regoff_t *start;
-  regoff_t *end;
-};
-
-
-/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
-   `re_match_2' returns information about at least this many registers
-   the first time a `regs' structure is passed.  */
-#ifndef RE_NREGS
-# define RE_NREGS 30
-#endif
-
-
-/* POSIX specification for registers.  Aside from the different names than
-   `re_registers', POSIX uses an array of structures, instead of a
-   structure of arrays.  */
-typedef struct
-{
-  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
-  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
-} regmatch_t;
-\f
-/* Declarations for routines.  */
-
-/* To avoid duplicating every routine declaration -- once with a
-   prototype (if we are ANSI), and once without (if we aren't) -- we
-   use the following macro to declare argument types.  This
-   unfortunately clutters up the declarations a bit, but I think it's
-   worth it.  */
-
-#if __STDC__
-
-# define _RE_ARGS(args) args
-
-#else /* not __STDC__ */
-
-# define _RE_ARGS(args) ()
-
-#endif /* not __STDC__ */
-
-/* Sets the current default syntax to SYNTAX, and return the old syntax.
-   You can also simply assign to the `re_syntax_options' variable.  */
-extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
-
-/* Compile the regular expression PATTERN, with length LENGTH
-   and syntax given by the global `re_syntax_options', into the buffer
-   BUFFER.  Return NULL if successful, and an error string if not.  */
-extern const char *re_compile_pattern
-  _RE_ARGS ((const char *pattern, size_t length,
-             struct re_pattern_buffer *buffer));
-
-
-/* Compile a fastmap for the compiled pattern in BUFFER; used to
-   accelerate searches.  Return 0 if successful and -2 if was an
-   internal error.  */
-extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
-
-
-/* Search in the string STRING (with length LENGTH) for the pattern
-   compiled into BUFFER.  Start searching at position START, for RANGE
-   characters.  Return the starting position of the match, -1 for no
-   match, or -2 for an internal error.  Also return register
-   information in REGS (if REGS and BUFFER->no_sub are nonzero).  */
-extern int re_search
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
-            int length, int start, int range, struct re_registers *regs));
-
-
-/* Like `re_search', but search in the concatenation of STRING1 and
-   STRING2.  Also, stop searching at index START + STOP.  */
-extern int re_search_2
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
-             int length1, const char *string2, int length2,
-             int start, int range, struct re_registers *regs, int stop));
-
-
-/* Like `re_search', but return how many characters in STRING the regexp
-   in BUFFER matched, starting at position START.  */
-extern int re_match
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
-             int length, int start, struct re_registers *regs));
-
-
-/* Relates to `re_match' as `re_search_2' relates to `re_search'.  */
-extern int re_match_2
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
-             int length1, const char *string2, int length2,
-             int start, struct re_registers *regs, int stop));
-
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
-   ENDS.  Subsequent matches using BUFFER and REGS will use this memory
-   for recording register information.  STARTS and ENDS must be
-   allocated with malloc, and must each be at least `NUM_REGS * sizeof
-   (regoff_t)' bytes long.
-
-   If NUM_REGS == 0, then subsequent matches should allocate their own
-   register data.
-
-   Unless this function is called, the first search or match using
-   PATTERN_BUFFER will allocate its own register data, without
-   freeing the old data.  */
-extern void re_set_registers
-  _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
-             unsigned num_regs, regoff_t *starts, regoff_t *ends));
-
-#if defined _REGEX_RE_COMP || defined _LIBC
-# ifndef _CRAY
-/* 4.2 bsd compatibility.  */
-extern char *re_comp _RE_ARGS ((const char *));
-extern int re_exec _RE_ARGS ((const char *));
-# endif
-#endif
-
-/* GCC 2.95 and later have "__restrict"; C99 compilers have
-   "restrict", and "configure" may have defined "restrict".  */
-#ifndef __restrict
-# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
-#  if defined restrict || 199901L <= __STDC_VERSION__
-#   define __restrict restrict
-#  else
-#   define __restrict
-#  endif
-# endif
-#endif
-/* gcc 3.1 and up support the [restrict] syntax.  */
-#ifndef __restrict_arr
-# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
-#  define __restrict_arr __restrict
-# else
-#  define __restrict_arr
-# endif
-#endif
-
-/* POSIX compatibility.  */
-extern int regcomp _RE_ARGS ((regex_t *__restrict __preg,
-                             const char *__restrict __pattern,
-                             int __cflags));
-
-extern int regexec _RE_ARGS ((const regex_t *__restrict __preg,
-                             const char *__restrict __string, size_t __nmatch,
-                             regmatch_t __pmatch[__restrict_arr],
-                             int __eflags));
-
-extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
-                                 char *__errbuf, size_t __errbuf_size));
-
-extern void regfree _RE_ARGS ((regex_t *__preg));
-
-
-#ifdef __cplusplus
-}
-#endif /* C++ */
-
-#endif /* regex.h */
-\f
-/*
-Local variables:
-make-backup-files: t
-version-control: t
-trim-versions-without-asking: nil
-End:
-*/
diff --git a/lib/regex/regex_internal.c b/lib/regex/regex_internal.c
deleted file mode 100644 (file)
index f969c7c..0000000
+++ /dev/null
@@ -1,1263 +0,0 @@
-/* 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>.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-static void re_string_construct_common (const char *str, int len,
-                                       re_string_t *pstr,
-                                       RE_TRANSLATE_TYPE trans, int icase);
-#ifdef RE_ENABLE_I18N
-static int re_string_skip_chars (re_string_t *pstr, int new_raw_idx,
-                                wint_t *last_wc);
-#endif /* RE_ENABLE_I18N */
-static re_dfastate_t *create_newstate_common (re_dfa_t *dfa,
-                                             const re_node_set *nodes,
-                                             unsigned int hash);
-static reg_errcode_t register_state (re_dfa_t *dfa, re_dfastate_t *newstate,
-                                    unsigned int hash);
-static re_dfastate_t *create_ci_newstate (re_dfa_t *dfa,
-                                         const re_node_set *nodes,
-                                         unsigned int hash);
-static re_dfastate_t *create_cd_newstate (re_dfa_t *dfa,
-                                         const re_node_set *nodes,
-                                         unsigned int context,
-                                         unsigned int hash);
-static unsigned int inline calc_state_hash (const re_node_set *nodes,
-                                           unsigned int context);
-\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
-re_string_allocate (pstr, str, len, init_len, trans, icase)
-     re_string_t *pstr;
-     const char *str;
-     int len, init_len, icase;
-     RE_TRANSLATE_TYPE trans;
-{
-  reg_errcode_t ret;
-  int init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
-  re_string_construct_common (str, len, pstr, trans, icase);
-  pstr->stop = pstr->len;
-
-  ret = re_string_realloc_buffers (pstr, init_buf_len);
-  if (BE (ret != REG_NOERROR, 0))
-    return ret;
-
-  pstr->mbs_case = (MBS_CASE_ALLOCATED (pstr) ? pstr->mbs_case
-                   : (unsigned char *) str);
-  pstr->mbs = MBS_ALLOCATED (pstr) ? pstr->mbs : pstr->mbs_case;
-  pstr->valid_len = (MBS_CASE_ALLOCATED (pstr) || MBS_ALLOCATED (pstr)
-                    || MB_CUR_MAX > 1) ? pstr->valid_len : len;
-  return REG_NOERROR;
-}
-
-/* This function allocate the buffers, and initialize them.  */
-
-static reg_errcode_t
-re_string_construct (pstr, str, len, trans, icase)
-     re_string_t *pstr;
-     const char *str;
-     int len, icase;
-     RE_TRANSLATE_TYPE trans;
-{
-  reg_errcode_t ret;
-  re_string_construct_common (str, len, pstr, trans, icase);
-  pstr->stop = pstr->len;
-  /* Set 0 so that this function can initialize whole buffers.  */
-  pstr->valid_len = 0;
-
-  if (len > 0)
-    {
-      ret = re_string_realloc_buffers (pstr, len + 1);
-      if (BE (ret != REG_NOERROR, 0))
-       return ret;
-    }
-  pstr->mbs_case = (MBS_CASE_ALLOCATED (pstr) ? pstr->mbs_case
-                   : (unsigned char *) str);
-  pstr->mbs = MBS_ALLOCATED (pstr) ? pstr->mbs : pstr->mbs_case;
-
-  if (icase)
-    {
-#ifdef RE_ENABLE_I18N
-      if (MB_CUR_MAX > 1)
-       build_wcs_upper_buffer (pstr);
-      else
-#endif /* RE_ENABLE_I18N  */
-       build_upper_buffer (pstr);
-    }
-  else
-    {
-#ifdef RE_ENABLE_I18N
-      if (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 = len;
-       }
-    }
-
-  /* Initialized whole buffers, then valid_len == bufs_len.  */
-  pstr->valid_len = pstr->bufs_len;
-  return REG_NOERROR;
-}
-
-/* Helper functions for re_string_allocate, and re_string_construct.  */
-
-static reg_errcode_t
-re_string_realloc_buffers (pstr, new_buf_len)
-     re_string_t *pstr;
-     int new_buf_len;
-{
-#ifdef RE_ENABLE_I18N
-  if (MB_CUR_MAX > 1)
-    {
-      wint_t *new_array = re_realloc (pstr->wcs, wint_t, new_buf_len);
-      if (BE (new_array == NULL, 0))
-       return REG_ESPACE;
-      pstr->wcs = new_array;
-    }
-#endif /* RE_ENABLE_I18N  */
-  if (MBS_ALLOCATED (pstr))
-    {
-      unsigned char *new_array = re_realloc (pstr->mbs, unsigned char,
-                                            new_buf_len);
-      if (BE (new_array == NULL, 0))
-       return REG_ESPACE;
-      pstr->mbs = new_array;
-    }
-  if (MBS_CASE_ALLOCATED (pstr))
-    {
-      unsigned char *new_array = re_realloc (pstr->mbs_case, unsigned char,
-                                            new_buf_len);
-      if (BE (new_array == NULL, 0))
-       return REG_ESPACE;
-      pstr->mbs_case = new_array;
-      if (!MBS_ALLOCATED (pstr))
-       pstr->mbs = pstr->mbs_case;
-    }
-  pstr->bufs_len = new_buf_len;
-  return REG_NOERROR;
-}
-
-
-static void
-re_string_construct_common (str, len, pstr, trans, icase)
-     const char *str;
-     int len;
-     re_string_t *pstr;
-     RE_TRANSLATE_TYPE trans;
-     int icase;
-{
-  memset (pstr, '\0', sizeof (re_string_t));
-  pstr->raw_mbs = (const unsigned char *) str;
-  pstr->len = len;
-  pstr->trans = trans;
-  pstr->icase = icase ? 1 : 0;
-}
-
-#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
-build_wcs_buffer (pstr)
-     re_string_t *pstr;
-{
-  mbstate_t prev_st;
-  int byte_idx, end_idx, mbclen, remain_len;
-  /* 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;
-      remain_len = end_idx - byte_idx;
-      prev_st = pstr->cur_state;
-      mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
-                             + byte_idx), remain_len, &pstr->cur_state);
-      if (BE (mbclen == (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];
-         pstr->cur_state = prev_st;
-       }
-
-      /* Apply the translateion if we need.  */
-      if (pstr->trans != NULL && mbclen == 1)
-       {
-         int ch = pstr->trans[pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]];
-         pstr->mbs_case[byte_idx] = ch;
-       }
-      /* 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;
-}
-
-/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
-   but for REG_ICASE.  */
-
-static void
-build_wcs_upper_buffer (pstr)
-     re_string_t *pstr;
-{
-  mbstate_t prev_st;
-  int byte_idx, end_idx, mbclen, remain_len;
-  /* 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;
-      remain_len = end_idx - byte_idx;
-      prev_st = pstr->cur_state;
-      mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
-                             + byte_idx), remain_len, &pstr->cur_state);
-      if (BE (mbclen == (size_t) -2, 0))
-       {
-         /* The buffer doesn't have enough space, finish to build.  */
-         pstr->cur_state = prev_st;
-         break;
-       }
-      else if (mbclen == 1 || mbclen == (size_t) -1 || mbclen == 0)
-       {
-         /* In case of a singlebyte character.  */
-         int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
-         /* Apply the translateion if we need.  */
-         if (pstr->trans != NULL && mbclen == 1)
-           {
-             ch = pstr->trans[ch];
-             pstr->mbs_case[byte_idx] = ch;
-           }
-         pstr->wcs[byte_idx] = iswlower (wc) ? toupper (wc) : wc;
-         pstr->mbs[byte_idx++] = islower (ch) ? toupper (ch) : ch;
-         if (BE (mbclen == (size_t) -1, 0))
-           pstr->cur_state = prev_st;
-       }
-      else /* mbclen > 1 */
-       {
-         if (iswlower (wc))
-           wcrtomb ((char *) pstr->mbs + byte_idx, towupper (wc), &prev_st);
-         else
-           memcpy (pstr->mbs + byte_idx,
-                   pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
-         pstr->wcs[byte_idx++] = iswlower (wc) ? toupper (wc) : wc;
-         /* Write paddings.  */
-         for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
-           pstr->wcs[byte_idx++] = WEOF;
-       }
-    }
-  pstr->valid_len = byte_idx;
-}
-
-/* Skip characters until the index becomes greater than NEW_RAW_IDX.
-   Return the index.  */
-
-static int
-re_string_skip_chars (pstr, new_raw_idx, last_wc)
-     re_string_t *pstr;
-     int new_raw_idx;
-     wint_t *last_wc;
-{
-  mbstate_t prev_st;
-  int rawbuf_idx, mbclen;
-  wchar_t wc = 0;
-
-  /* Skip the characters which are not necessary to check.  */
-  for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_len;
-       rawbuf_idx < new_raw_idx;)
-    {
-      int remain_len;
-      remain_len = pstr->len - rawbuf_idx;
-      prev_st = pstr->cur_state;
-      mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx,
-                       remain_len, &pstr->cur_state);
-      if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
-       {
-         /* We treat these cases as a 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
-build_upper_buffer (pstr)
-     re_string_t *pstr;
-{
-  int char_idx, end_idx;
-  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
-
-  for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
-    {
-      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
-      if (pstr->trans != NULL)
-       {
-         ch =  pstr->trans[ch];
-         pstr->mbs_case[char_idx] = ch;
-       }
-      if (islower (ch))
-       pstr->mbs[char_idx] = toupper (ch);
-      else
-       pstr->mbs[char_idx] = ch;
-    }
-  pstr->valid_len = char_idx;
-}
-
-/* Apply TRANS to the buffer in PSTR.  */
-
-static void
-re_string_translate_buffer (pstr)
-     re_string_t *pstr;
-{
-  int buf_idx, end_idx;
-  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
-
-  for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
-    {
-      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
-      pstr->mbs_case[buf_idx] = pstr->trans[ch];
-    }
-
-  pstr->valid_len = buf_idx;
-}
-
-/* This function re-construct the buffers.
-   Concretely, convert to wide character in case of MB_CUR_MAX > 1,
-   convert to upper case in case of REG_ICASE, apply translation.  */
-
-static reg_errcode_t
-re_string_reconstruct (pstr, idx, eflags, newline)
-     re_string_t *pstr;
-     int idx, eflags, newline;
-{
-  int offset = idx - pstr->raw_mbs_idx;
-  if (offset < 0)
-    {
-      /* Reset buffer.  */
-#ifdef RE_ENABLE_I18N
-      if (MB_CUR_MAX > 1)
-       memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
-#endif /* RE_ENABLE_I18N */
-      pstr->len += pstr->raw_mbs_idx;
-      pstr->stop += pstr->raw_mbs_idx;
-      pstr->valid_len = pstr->raw_mbs_idx = 0;
-      pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
-                          : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
-      if (!MBS_CASE_ALLOCATED (pstr))
-       pstr->mbs_case = (unsigned char *) pstr->raw_mbs;
-      if (!MBS_ALLOCATED (pstr) && !MBS_CASE_ALLOCATED (pstr))
-       pstr->mbs = (unsigned char *) pstr->raw_mbs;
-      offset = idx;
-    }
-
-  if (offset != 0)
-    {
-      /* Are the characters which are already checked remain?  */
-      if (offset < pstr->valid_len)
-       {
-         /* Yes, move them to the front of the buffer.  */
-         pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags,
-                                                   newline);
-#ifdef RE_ENABLE_I18N
-         if (MB_CUR_MAX > 1)
-           memmove (pstr->wcs, pstr->wcs + offset,
-                    (pstr->valid_len - offset) * sizeof (wint_t));
-#endif /* RE_ENABLE_I18N */
-         if (MBS_ALLOCATED (pstr))
-           memmove (pstr->mbs, pstr->mbs + offset,
-                    pstr->valid_len - offset);
-         if (MBS_CASE_ALLOCATED (pstr))
-           memmove (pstr->mbs_case, pstr->mbs_case + offset,
-                    pstr->valid_len - offset);
-         pstr->valid_len -= offset;
-#if DEBUG
-         assert (pstr->valid_len > 0);
-#endif
-       }
-      else
-       {
-         /* No, skip all characters until IDX.  */
-         pstr->valid_len = 0;
-#ifdef RE_ENABLE_I18N
-         if (MB_CUR_MAX > 1)
-           {
-             int wcs_idx;
-             wint_t wc;
-             pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
-             for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
-               pstr->wcs[wcs_idx] = WEOF;
-             if (pstr->trans && wc <= 0xff)
-               wc = pstr->trans[wc];
-             pstr->tip_context = (IS_WIDE_WORD_CHAR (wc) ? CONTEXT_WORD
-                                  : ((newline && IS_WIDE_NEWLINE (wc))
-                                     ? 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 = (IS_WORD_CHAR (c) ? CONTEXT_WORD
-                                  : ((newline && IS_NEWLINE (c))
-                                     ? CONTEXT_NEWLINE : 0));
-           }
-       }
-      if (!MBS_CASE_ALLOCATED (pstr))
-       {
-         pstr->mbs_case += offset;
-         /* In case of !MBS_ALLOCATED && !MBS_CASE_ALLOCATED.  */
-         if (!MBS_ALLOCATED (pstr))
-           pstr->mbs += offset;
-       }
-    }
-  pstr->raw_mbs_idx = idx;
-  pstr->len -= offset;
-  pstr->stop -= offset;
-
-  /* Then build the buffers.  */
-#ifdef RE_ENABLE_I18N
-  if (MB_CUR_MAX > 1)
-    {
-      if (pstr->icase)
-       build_wcs_upper_buffer (pstr);
-      else
-       build_wcs_buffer (pstr);
-    }
-  else
-#endif /* RE_ENABLE_I18N */
-    {
-      if (pstr->icase)
-       build_upper_buffer (pstr);
-      else if (pstr->trans != NULL)
-       re_string_translate_buffer (pstr);
-    }
-  pstr->cur_idx = 0;
-
-  return REG_NOERROR;
-}
-
-static void
-re_string_destruct (pstr)
-     re_string_t *pstr;
-{
-#ifdef RE_ENABLE_I18N
-  re_free (pstr->wcs);
-#endif /* RE_ENABLE_I18N  */
-  if (MBS_ALLOCATED (pstr))
-    re_free (pstr->mbs);
-  if (MBS_CASE_ALLOCATED (pstr))
-    re_free (pstr->mbs_case);
-}
-
-/* Return the context at IDX in INPUT.  */
-
-static unsigned int
-re_string_context_at (input, idx, eflags, newline_anchor)
-     const re_string_t *input;
-     int idx, eflags, newline_anchor;
-{
-  int c;
-  if (idx < 0 || idx == input->len)
-    {
-      if (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;
-      else /* (idx == input->len) */
-       return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
-               : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
-    }
-#ifdef RE_ENABLE_I18N
-  if (MB_CUR_MAX > 1)
-    {
-      wint_t wc;
-      int wc_idx = idx;
-      while(input->wcs[wc_idx] == WEOF)
-       {
-#ifdef DEBUG
-         /* It must not happen.  */
-         assert (wc_idx >= 0);
-#endif
-         --wc_idx;
-         if (wc_idx < 0)
-           return input->tip_context;
-       }
-      wc = input->wcs[wc_idx];
-      if (IS_WIDE_WORD_CHAR (wc))
-       return CONTEXT_WORD;
-      return (newline_anchor && IS_WIDE_NEWLINE (wc)) ? CONTEXT_NEWLINE : 0;
-    }
-  else
-#endif
-    {
-      c = re_string_byte_at (input, idx);
-      if (IS_WORD_CHAR (c))
-       return CONTEXT_WORD;
-      return (newline_anchor && IS_NEWLINE (c)) ? CONTEXT_NEWLINE : 0;
-    }
-}
-\f
-/* Functions for set operation.  */
-
-static reg_errcode_t
-re_node_set_alloc (set, size)
-     re_node_set *set;
-     int size;
-{
-  set->alloc = size;
-  set->nelem = 0;
-  set->elems = re_malloc (int, size);
-  if (BE (set->elems == NULL, 0))
-    return REG_ESPACE;
-  return REG_NOERROR;
-}
-
-static reg_errcode_t
-re_node_set_init_1 (set, elem)
-     re_node_set *set;
-     int elem;
-{
-  set->alloc = 1;
-  set->nelem = 1;
-  set->elems = re_malloc (int, 1);
-  if (BE (set->elems == NULL, 0))
-    {
-      set->alloc = set->nelem = 0;
-      return REG_ESPACE;
-    }
-  set->elems[0] = elem;
-  return REG_NOERROR;
-}
-
-static reg_errcode_t
-re_node_set_init_2 (set, elem1, elem2)
-     re_node_set *set;
-     int elem1, elem2;
-{
-  set->alloc = 2;
-  set->elems = re_malloc (int, 2);
-  if (BE (set->elems == NULL, 0))
-    return REG_ESPACE;
-  if (elem1 == elem2)
-    {
-      set->nelem = 1;
-      set->elems[0] = elem1;
-    }
-  else
-    {
-      set->nelem = 2;
-      if (elem1 < elem2)
-       {
-         set->elems[0] = elem1;
-         set->elems[1] = elem2;
-       }
-      else
-       {
-         set->elems[0] = elem2;
-         set->elems[1] = elem1;
-       }
-    }
-  return REG_NOERROR;
-}
-
-static reg_errcode_t
-re_node_set_init_copy (dest, src)
-     re_node_set *dest;
-     const re_node_set *src;
-{
-  dest->nelem = src->nelem;
-  if (src->nelem > 0)
-    {
-      dest->alloc = dest->nelem;
-      dest->elems = re_malloc (int, dest->alloc);
-      if (BE (dest->elems == NULL, 0))
-       {
-         dest->alloc = dest->nelem = 0;
-         return REG_ESPACE;
-       }
-      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
-    }
-  else
-    re_node_set_init_empty (dest);
-  return REG_NOERROR;
-}
-
-/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
-   DEST. Return value indicate the error code or REG_NOERROR if succeeded.
-   Note: We assume dest->elems is NULL, when dest->alloc is 0.  */
-
-static reg_errcode_t
-re_node_set_add_intersect (dest, src1, src2)
-     re_node_set *dest;
-     const re_node_set *src1, *src2;
-{
-  int i1, i2, id;
-  if (src1->nelem > 0 && src2->nelem > 0)
-    {
-      if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
-       {
-         dest->alloc = src1->nelem + src2->nelem + dest->nelem;
-         dest->elems = re_realloc (dest->elems, int, dest->alloc);
-         if (BE (dest->elems == NULL, 0))
-           return REG_ESPACE;
-       }
-    }
-  else
-    return REG_NOERROR;
-
-  for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
-    {
-      if (src1->elems[i1] > src2->elems[i2])
-       {
-         ++i2;
-         continue;
-       }
-      if (src1->elems[i1] == src2->elems[i2])
-       {
-         while (id < dest->nelem && dest->elems[id] < src2->elems[i2])
-           ++id;
-         if (id < dest->nelem && dest->elems[id] == src2->elems[i2])
-           ++id;
-         else
-           {
-             memmove (dest->elems + id + 1, dest->elems + id,
-                      sizeof (int) * (dest->nelem - id));
-             dest->elems[id++] = src2->elems[i2++];
-             ++dest->nelem;
-           }
-       }
-      ++i1;
-    }
-  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
-re_node_set_init_union (dest, src1, src2)
-     re_node_set *dest;
-     const re_node_set *src1, *src2;
-{
-  int i1, i2, id;
-  if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
-    {
-      dest->alloc = src1->nelem + src2->nelem;
-      dest->elems = re_malloc (int, dest->alloc);
-      if (BE (dest->elems == NULL, 0))
-       return REG_ESPACE;
-    }
-  else
-    {
-      if (src1 != NULL && src1->nelem > 0)
-       return re_node_set_init_copy (dest, src1);
-      else if (src2 != NULL && src2->nelem > 0)
-       return re_node_set_init_copy (dest, src2);
-      else
-       re_node_set_init_empty (dest);
-      return REG_NOERROR;
-    }
-  for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
-    {
-      if (src1->elems[i1] > src2->elems[i2])
-       {
-         dest->elems[id++] = src2->elems[i2++];
-         continue;
-       }
-      if (src1->elems[i1] == src2->elems[i2])
-       ++i2;
-      dest->elems[id++] = src1->elems[i1++];
-    }
-  if (i1 < src1->nelem)
-    {
-      memcpy (dest->elems + id, src1->elems + i1,
-            (src1->nelem - i1) * sizeof (int));
-      id += src1->nelem - i1;
-    }
-  else if (i2 < src2->nelem)
-    {
-      memcpy (dest->elems + id, src2->elems + i2,
-            (src2->nelem - i2) * sizeof (int));
-      id += src2->nelem - i2;
-    }
-  dest->nelem = id;
-  return REG_NOERROR;
-}
-
-/* Calculate the union set of the sets DEST and SRC. And store it to
-   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
-
-static reg_errcode_t
-re_node_set_merge (dest, src)
-     re_node_set *dest;
-     const re_node_set *src;
-{
-  int si, di;
-  if (src == NULL || src->nelem == 0)
-    return REG_NOERROR;
-  if (dest->alloc < src->nelem + dest->nelem)
-    {
-      int *new_buffer;
-      dest->alloc = 2 * (src->nelem + dest->alloc);
-      new_buffer = re_realloc (dest->elems, int, dest->alloc);
-      if (BE (new_buffer == NULL, 0))
-       return REG_ESPACE;
-      dest->elems = new_buffer;
-    }
-
-  for (si = 0, di = 0 ; si < src->nelem && di < dest->nelem ;)
-    {
-      int cp_from, ncp, mid, right, src_elem = src->elems[si];
-      /* Binary search the spot we will add the new element.  */
-      right = dest->nelem;
-      while (di < right)
-       {
-         mid = (di + right) / 2;
-         if (dest->elems[mid] < src_elem)
-           di = mid + 1;
-         else
-           right = mid;
-       }
-      if (di >= dest->nelem)
-       break;
-
-      if (dest->elems[di] == src_elem)
-       {
-         /* Skip since, DEST already has the element.  */
-         ++di;
-         ++si;
-         continue;
-       }
-
-      /* Skip the src elements which are less than dest->elems[di].  */
-      cp_from = si;
-      while (si < src->nelem && src->elems[si] < dest->elems[di])
-       ++si;
-      /* Copy these src elements.  */
-      ncp = si - cp_from;
-      memmove (dest->elems + di + ncp, dest->elems + di,
-              sizeof (int) * (dest->nelem - di));
-      memcpy (dest->elems + di, src->elems + cp_from,
-             sizeof (int) * ncp);
-      /* Update counters.  */
-      di += ncp;
-      dest->nelem += ncp;
-    }
-
-  /* Copy remaining src elements.  */
-  if (si < src->nelem)
-    {
-      memcpy (dest->elems + di, src->elems + si,
-             sizeof (int) * (src->nelem - si));
-      dest->nelem += src->nelem - si;
-    }
-  return REG_NOERROR;
-}
-
-/* Insert the new element ELEM to the re_node_set* SET.
-   return 0 if SET already has ELEM,
-   return -1 if an error is occured, return 1 otherwise.  */
-
-static int
-re_node_set_insert (set, elem)
-     re_node_set *set;
-     int elem;
-{
-  int idx, right, mid;
-  /* In case of the set is empty.  */
-  if (set->elems == NULL || set->alloc == 0)
-    {
-      if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
-       return 1;
-      else
-       return -1;
-    }
-
-  /* Binary search the spot we will add the new element.  */
-  idx = 0;
-  right = set->nelem;
-  while (idx < right)
-    {
-      mid = (idx + right) / 2;
-      if (set->elems[mid] < elem)
-       idx = mid + 1;
-      else
-       right = mid;
-    }
-
-  /* Realloc if we need.  */
-  if (set->alloc < set->nelem + 1)
-    {
-      int *new_array;
-      set->alloc = set->alloc * 2;
-      new_array = re_malloc (int, set->alloc);
-      if (BE (new_array == NULL, 0))
-       return -1;
-      /* Copy the elements they are followed by the new element.  */
-      if (idx > 0)
-       memcpy (new_array, set->elems, sizeof (int) * (idx));
-      /* Copy the elements which follows the new element.  */
-      if (set->nelem - idx > 0)
-       memcpy (new_array + idx + 1, set->elems + idx,
-               sizeof (int) * (set->nelem - idx));
-      re_free (set->elems);
-      set->elems = new_array;
-    }
-  else
-    {
-      /* Move the elements which follows the new element.  */
-      if (set->nelem - idx > 0)
-       memmove (set->elems + idx + 1, set->elems + idx,
-                sizeof (int) * (set->nelem - idx));
-    }
-  /* Insert the new element.  */
-  set->elems[idx] = elem;
-  ++set->nelem;
-  return 1;
-}
-
-/* Compare two node sets SET1 and SET2.
-   return 1 if SET1 and SET2 are equivalent, retrun 0 otherwise.  */
-
-static int
-re_node_set_compare (set1, set2)
-     const re_node_set *set1, *set2;
-{
-  int i;
-  if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
-    return 0;
-  for (i = 0 ; i < set1->nelem ; i++)
-    if (set1->elems[i] != set2->elems[i])
-      return 0;
-  return 1;
-}
-
-/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise.  */
-
-static int
-re_node_set_contains (set, elem)
-     const re_node_set *set;
-     int elem;
-{
-  int idx, right, mid;
-  if (set->nelem <= 0)
-    return 0;
-
-  /* Binary search the element.  */
-  idx = 0;
-  right = set->nelem - 1;
-  while (idx < right)
-    {
-      mid = (idx + right) / 2;
-      if (set->elems[mid] < elem)
-       idx = mid + 1;
-      else
-       right = mid;
-    }
-  return set->elems[idx] == elem ? idx + 1 : 0;
-}
-
-static void
-re_node_set_remove_at (set, idx)
-     re_node_set *set;
-     int idx;
-{
-  if (idx < 0 || idx >= set->nelem)
-    return;
-  if (idx < set->nelem - 1)
-    memmove (set->elems + idx, set->elems + idx + 1,
-            sizeof (int) * (set->nelem - idx - 1));
-  --set->nelem;
-}
-\f
-
-/* Add the token TOKEN to dfa->nodes, and return the index of the token.
-   Or return -1, if an error will be occured.  */
-
-static int
-re_dfa_add_node (dfa, token, mode)
-     re_dfa_t *dfa;
-     re_token_t token;
-     int mode;
-{
-  if (dfa->nodes_len >= dfa->nodes_alloc)
-    {
-      re_token_t *new_array;
-      dfa->nodes_alloc *= 2;
-      new_array = re_realloc (dfa->nodes, re_token_t, dfa->nodes_alloc);
-      if (BE (new_array == NULL, 0))
-       return -1;
-      else
-       dfa->nodes = new_array;
-      if (mode)
-       {
-         int *new_nexts, *new_indices;
-         re_node_set *new_edests, *new_eclosures, *new_inveclosures;
-
-         new_nexts = re_realloc (dfa->nexts, int, dfa->nodes_alloc);
-         new_indices = re_realloc (dfa->org_indices, int, dfa->nodes_alloc);
-         new_edests = re_realloc (dfa->edests, re_node_set, dfa->nodes_alloc);
-         new_eclosures = re_realloc (dfa->eclosures, re_node_set,
-                                     dfa->nodes_alloc);
-         new_inveclosures = re_realloc (dfa->inveclosures, re_node_set,
-                                        dfa->nodes_alloc);
-         if (BE (new_nexts == NULL || new_indices == NULL
-                 || new_edests == NULL || new_eclosures == NULL
-                 || new_inveclosures == NULL, 0))
-           return -1;
-         dfa->nexts = new_nexts;
-         dfa->org_indices = new_indices;
-         dfa->edests = new_edests;
-         dfa->eclosures = new_eclosures;
-         dfa->inveclosures = new_inveclosures;
-       }
-    }
-  dfa->nodes[dfa->nodes_len] = token;
-  dfa->nodes[dfa->nodes_len].duplicated = 0;
-  dfa->nodes[dfa->nodes_len].constraint = 0;
-  return dfa->nodes_len++;
-}
-
-static unsigned int inline
-calc_state_hash (nodes, context)
-     const re_node_set *nodes;
-     unsigned int context;
-{
-  unsigned int hash = nodes->nelem + context;
-  int i;
-  for (i = 0 ; i < nodes->nelem ; i++)
-    hash += nodes->elems[i];
-  return hash;
-}
-
-/* Search for the state whose node_set is equivalent to NODES.
-   Return the pointer to the state, if we found it in the DFA.
-   Otherwise create the new one and return it.  In case of an error
-   return NULL and set the error code in ERR.
-   Note: - We assume NULL as the invalid state, then it is possible that
-          return value is NULL and ERR is REG_NOERROR.
-        - We never return non-NULL value in case of any errors, it is for
-          optimization.  */
-
-static re_dfastate_t*
-re_acquire_state (err, dfa, nodes)
-     reg_errcode_t *err;
-     re_dfa_t *dfa;
-     const re_node_set *nodes;
-{
-  unsigned int hash;
-  re_dfastate_t *new_state;
-  struct re_state_table_entry *spot;
-  int i;
-  if (BE (nodes->nelem == 0, 0))
-    {
-      *err = REG_NOERROR;
-      return NULL;
-    }
-  hash = calc_state_hash (nodes, 0);
-  spot = dfa->state_table + (hash & dfa->state_hash_mask);
-
-  for (i = 0 ; i < spot->num ; i++)
-    {
-      re_dfastate_t *state = spot->array[i];
-      if (hash != state->hash)
-       continue;
-      if (re_node_set_compare (&state->nodes, nodes))
-       return state;
-    }
-
-  /* There are no appropriate state in the dfa, create the new one.  */
-  new_state = create_ci_newstate (dfa, nodes, hash);
-  if (BE (new_state != NULL, 1))
-    return new_state;
-  else
-    {
-      *err = REG_ESPACE;
-      return NULL;
-    }
-}
-
-/* Search for the state whose node_set is equivalent to NODES and
-   whose context is equivalent to CONTEXT.
-   Return the pointer to the state, if we found it in the DFA.
-   Otherwise create the new one and return it.  In case of an error
-   return NULL and set the error code in ERR.
-   Note: - We assume NULL as the invalid state, then it is possible that
-          return value is NULL and ERR is REG_NOERROR.
-        - We never return non-NULL value in case of any errors, it is for
-          optimization.  */
-
-static re_dfastate_t*
-re_acquire_state_context (err, dfa, nodes, context)
-     reg_errcode_t *err;
-     re_dfa_t *dfa;
-     const re_node_set *nodes;
-     unsigned int context;
-{
-  unsigned int hash;
-  re_dfastate_t *new_state;
-  struct re_state_table_entry *spot;
-  int i;
-  if (nodes->nelem == 0)
-    {
-      *err = REG_NOERROR;
-      return NULL;
-    }
-  hash = calc_state_hash (nodes, context);
-  spot = dfa->state_table + (hash & dfa->state_hash_mask);
-
-  for (i = 0 ; i < spot->num ; i++)
-    {
-      re_dfastate_t *state = spot->array[i];
-      if (hash != state->hash)
-       continue;
-      if (re_node_set_compare (state->entrance_nodes, nodes)
-         && state->context == context)
-       return state;
-    }
-  /* There are no appropriate state in `dfa', create the new one.  */
-  new_state = create_cd_newstate (dfa, nodes, context, hash);
-  if (BE (new_state != NULL, 1))
-    return new_state;
-  else
-    {
-      *err = REG_ESPACE;
-      return NULL;
-    }
-}
-
-/* Allocate memory for DFA state and initialize common properties.
-   Return the new state if succeeded, otherwise return NULL.  */
-
-static re_dfastate_t *
-create_newstate_common (dfa, nodes, hash)
-     re_dfa_t *dfa;
-     const re_node_set *nodes;
-     unsigned int hash;
-{
-  re_dfastate_t *newstate;
-  reg_errcode_t err;
-  newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
-  if (BE (newstate == NULL, 0))
-    return NULL;
-  err = re_node_set_init_copy (&newstate->nodes, nodes);
-  if (BE (err != REG_NOERROR, 0))
-    {
-      re_free (newstate);
-      return NULL;
-    }
-  newstate->trtable = NULL;
-  newstate->trtable_search = NULL;
-  newstate->hash = hash;
-  return newstate;
-}
-
-/* Store the new state NEWSTATE whose hash value is HASH in appropriate
-   position.  Return value indicate the error code if failed.  */
-
-static reg_errcode_t
-register_state (dfa, newstate, hash)
-     re_dfa_t *dfa;
-     re_dfastate_t *newstate;
-     unsigned int hash;
-{
-  struct re_state_table_entry *spot;
-  spot = dfa->state_table + (hash & dfa->state_hash_mask);
-
-  if (spot->alloc <= spot->num)
-    {
-      re_dfastate_t **new_array;
-      spot->alloc = 2 * spot->num + 2;
-      new_array = re_realloc (spot->array, re_dfastate_t *, spot->alloc);
-      if (BE (new_array == NULL, 0))
-       return REG_ESPACE;
-      spot->array = new_array;
-    }
-  spot->array[spot->num++] = newstate;
-  return REG_NOERROR;
-}
-
-/* Create the new state which is independ of contexts.
-   Return the new state if succeeded, otherwise return NULL.  */
-
-static re_dfastate_t *
-create_ci_newstate (dfa, nodes, hash)
-     re_dfa_t *dfa;
-     const re_node_set *nodes;
-     unsigned int hash;
-{
-  int i;
-  reg_errcode_t err;
-  re_dfastate_t *newstate;
-  newstate = create_newstate_common (dfa, nodes, hash);
-  if (BE (newstate == NULL, 0))
-    return NULL;
-  newstate->entrance_nodes = &newstate->nodes;
-
-  for (i = 0 ; i < nodes->nelem ; i++)
-    {
-      re_token_t *node = dfa->nodes + nodes->elems[i];
-      re_token_type_t type = node->type;
-      if (type == CHARACTER && !node->constraint)
-       continue;
-
-      /* If the state has the halt node, the state is a halt state.  */
-      else if (type == END_OF_RE)
-       newstate->halt = 1;
-#ifdef RE_ENABLE_I18N
-      else if (type == COMPLEX_BRACKET
-              || (type == OP_PERIOD && MB_CUR_MAX > 1))
-       newstate->accept_mb = 1;
-#endif /* RE_ENABLE_I18N */
-      else if (type == OP_BACK_REF)
-       newstate->has_backref = 1;
-      else if (type == ANCHOR || node->constraint)
-       newstate->has_constraint = 1;
-    }
-  err = register_state (dfa, newstate, hash);
-  if (BE (err != REG_NOERROR, 0))
-    {
-      free_state (newstate);
-      newstate = NULL;
-    }
-  return newstate;
-}
-
-/* Create the new state which is depend on the context CONTEXT.
-   Return the new state if succeeded, otherwise return NULL.  */
-
-static re_dfastate_t *
-create_cd_newstate (dfa, nodes, context, hash)
-     re_dfa_t *dfa;
-     const re_node_set *nodes;
-     unsigned int context, hash;
-{
-  int i, nctx_nodes = 0;
-  reg_errcode_t err;
-  re_dfastate_t *newstate;
-
-  newstate = create_newstate_common (dfa, nodes, hash);
-  if (BE (newstate == NULL, 0))
-    return NULL;
-  newstate->context = context;
-  newstate->entrance_nodes = &newstate->nodes;
-
-  for (i = 0 ; i < nodes->nelem ; i++)
-    {
-      unsigned int constraint = 0;
-      re_token_t *node = dfa->nodes + nodes->elems[i];
-      re_token_type_t type = node->type;
-      if (node->constraint)
-       constraint = node->constraint;
-
-      if (type == CHARACTER && !constraint)
-       continue;
-      /* If the state has the halt node, the state is a halt state.  */
-      else if (type == END_OF_RE)
-       newstate->halt = 1;
-#ifdef RE_ENABLE_I18N
-      else if (type == COMPLEX_BRACKET
-              || (type == OP_PERIOD && MB_CUR_MAX > 1))
-       newstate->accept_mb = 1;
-#endif /* RE_ENABLE_I18N */
-      else if (type == OP_BACK_REF)
-       newstate->has_backref = 1;
-      else if (type == ANCHOR)
-       constraint = node->opr.ctx_type;
-
-      if (constraint)
-       {
-         if (newstate->entrance_nodes == &newstate->nodes)
-           {
-             newstate->entrance_nodes = re_malloc (re_node_set, 1);
-             if (BE (newstate->entrance_nodes == NULL, 0))
-               {
-                 free_state (newstate);
-                 return NULL;
-               }
-             re_node_set_init_copy (newstate->entrance_nodes, nodes);
-             nctx_nodes = 0;
-             newstate->has_constraint = 1;
-           }
-
-         if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
-           {
-             re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
-             ++nctx_nodes;
-           }
-       }
-    }
-  err = register_state (dfa, newstate, hash);
-  if (BE (err != REG_NOERROR, 0))
-    {
-      free_state (newstate);
-      newstate = NULL;
-    }
-  return  newstate;
-}
-
-static void
-free_state (state)
-     re_dfastate_t *state;
-{
-  if (state->entrance_nodes != &state->nodes)
-    {
-      re_node_set_free (state->entrance_nodes);
-      re_free (state->entrance_nodes);
-    }
-  re_node_set_free (&state->nodes);
-  re_free (state->trtable);
-  re_free (state->trtable_search);
-  re_free (state);
-}
diff --git a/lib/regex/regex_internal.h b/lib/regex/regex_internal.h
deleted file mode 100644 (file)
index bf84ad6..0000000
+++ /dev/null
@@ -1,742 +0,0 @@
-/* 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>.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#ifndef _REGEX_INTERNAL_H
-#define _REGEX_INTERNAL_H 1
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <assert.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined HAVE_LOCALE_H || defined _LIBC
-# include <locale.h>
-#endif
-#if defined HAVE_WCHAR_H || defined _LIBC
-# include <wchar.h>
-#endif /* HAVE_WCHAR_H || _LIBC */
-#if defined HAVE_WCTYPE_H || defined _LIBC
-# include <wctype.h>
-#endif /* HAVE_WCTYPE_H || _LIBC */
-
-/* In case that the system doesn't have isblank().  */
-#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank
-# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
-#endif
-
-#ifdef _LIBC
-# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
-#  define _RE_DEFINE_LOCALE_FUNCTIONS 1
-#   include <locale/localeinfo.h>
-#   include <locale/elem-hash.h>
-#   include <locale/coll-lookup.h>
-# endif
-#endif
-
-/* This is for other GNU distributions with internationalized messages.  */
-#if HAVE_LIBINTL_H || defined _LIBC
-# include <libintl.h>
-# ifdef _LIBC
-#  undef gettext
-#  define gettext(msgid) \
-  INTUSE(__dcgettext) (INTUSE(_libc_intl_domainname), msgid, LC_MESSAGES)
-# endif
-#else
-# define gettext(msgid) (msgid)
-#endif
-
-#ifndef gettext_noop
-/* This define is so xgettext can find the internationalizable
-   strings.  */
-# define gettext_noop(String) String
-#endif
-
-#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC
-# define RE_ENABLE_I18N
-#endif
-
-#if __GNUC__ >= 3
-# define BE(expr, val) __builtin_expect (expr, val)
-#else
-# define BE(expr, val) (expr)
-# define inline
-#endif
-
-/* Number of bits in a byte.  */
-#define BYTE_BITS 8
-/* Number of single byte character.  */
-#define SBC_MAX 256
-
-#define COLL_ELEM_LEN_MAX 8
-
-/* The character which represents newline.  */
-#define NEWLINE_CHAR '\n'
-#define WIDE_NEWLINE_CHAR L'\n'
-
-/* Rename to standard API for using out of glibc.  */
-#ifndef _LIBC
-# define __wctype wctype
-# define __iswctype iswctype
-# define __btowc btowc
-# define __mempcpy mempcpy
-# define __wcrtomb wcrtomb
-# define attribute_hidden
-#endif /* not _LIBC */
-
-extern const char __re_error_msgid[] attribute_hidden;
-extern const size_t __re_error_msgid_idx[] attribute_hidden;
-
-/* Number of bits in an unsinged int.  */
-#define UINT_BITS (sizeof (unsigned int) * BYTE_BITS)
-/* Number of unsigned int in an bit_set.  */
-#define BITSET_UINTS ((SBC_MAX + UINT_BITS - 1) / UINT_BITS)
-typedef unsigned int bitset[BITSET_UINTS];
-typedef unsigned int *re_bitset_ptr_t;
-
-#define bitset_set(set,i) (set[i / UINT_BITS] |= 1 << i % UINT_BITS)
-#define bitset_clear(set,i) (set[i / UINT_BITS] &= ~(1 << i % UINT_BITS))
-#define bitset_contain(set,i) (set[i / UINT_BITS] & (1 << i % UINT_BITS))
-#define bitset_empty(set) memset (set, 0, sizeof (unsigned int) * BITSET_UINTS)
-#define bitset_set_all(set) \
-  memset (set, 255, sizeof (unsigned int) * BITSET_UINTS)
-#define bitset_copy(dest,src) \
-  memcpy (dest, src, sizeof (unsigned int) * BITSET_UINTS)
-static inline void bitset_not (bitset set);
-static inline void bitset_merge (bitset dest, const bitset src);
-static inline void bitset_not_merge (bitset dest, const bitset src);
-
-#define PREV_WORD_CONSTRAINT 0x0001
-#define PREV_NOTWORD_CONSTRAINT 0x0002
-#define NEXT_WORD_CONSTRAINT 0x0004
-#define NEXT_NOTWORD_CONSTRAINT 0x0008
-#define PREV_NEWLINE_CONSTRAINT 0x0010
-#define NEXT_NEWLINE_CONSTRAINT 0x0020
-#define PREV_BEGBUF_CONSTRAINT 0x0040
-#define NEXT_ENDBUF_CONSTRAINT 0x0080
-#define DUMMY_CONSTRAINT 0x0100
-
-typedef enum
-{
-  INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
-  WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
-  WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
-  LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
-  LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
-  BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
-  BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
-  WORD_DELIM = DUMMY_CONSTRAINT
-} re_context_type;
-
-typedef struct
-{
-  int alloc;
-  int nelem;
-  int *elems;
-} re_node_set;
-
-typedef enum
-{
-  NON_TYPE = 0,
-
-  /* Token type, these are used only by token.  */
-  OP_OPEN_BRACKET,
-  OP_CLOSE_BRACKET,
-  OP_CHARSET_RANGE,
-  OP_OPEN_DUP_NUM,
-  OP_CLOSE_DUP_NUM,
-  OP_NON_MATCH_LIST,
-  OP_OPEN_COLL_ELEM,
-  OP_CLOSE_COLL_ELEM,
-  OP_OPEN_EQUIV_CLASS,
-  OP_CLOSE_EQUIV_CLASS,
-  OP_OPEN_CHAR_CLASS,
-  OP_CLOSE_CHAR_CLASS,
-  OP_WORD,
-  OP_NOTWORD,
-  BACK_SLASH,
-
-  /* Tree type, these are used only by tree. */
-  CONCAT,
-  ALT,
-  SUBEXP,
-  SIMPLE_BRACKET,
-#ifdef RE_ENABLE_I18N
-  COMPLEX_BRACKET,
-#endif /* RE_ENABLE_I18N */
-
-  /* Node type, These are used by token, node, tree.  */
-  OP_OPEN_SUBEXP,
-  OP_CLOSE_SUBEXP,
-  OP_PERIOD,
-  CHARACTER,
-  END_OF_RE,
-  OP_ALT,
-  OP_DUP_ASTERISK,
-  OP_DUP_PLUS,
-  OP_DUP_QUESTION,
-  OP_BACK_REF,
-  ANCHOR,
-
-  /* Dummy marker.  */
-  END_OF_RE_TOKEN_T
-} re_token_type_t;
-
-#ifdef RE_ENABLE_I18N
-typedef struct
-{
-  /* Multibyte characters.  */
-  wchar_t *mbchars;
-
-  /* Collating symbols.  */
-# ifdef _LIBC
-  int32_t *coll_syms;
-# endif
-
-  /* Equivalence classes. */
-# ifdef _LIBC
-  int32_t *equiv_classes;
-# endif
-
-  /* Range expressions. */
-# ifdef _LIBC
-  uint32_t *range_starts;
-  uint32_t *range_ends;
-# else /* not _LIBC */
-  wchar_t *range_starts;
-  wchar_t *range_ends;
-# endif /* not _LIBC */
-
-  /* Character classes. */
-  wctype_t *char_classes;
-
-  /* If this character set is the non-matching list.  */
-  unsigned int non_match : 1;
-
-  /* # of multibyte characters.  */
-  int nmbchars;
-
-  /* # of collating symbols.  */
-  int ncoll_syms;
-
-  /* # of equivalence classes. */
-  int nequiv_classes;
-
-  /* # of range expressions. */
-  int nranges;
-
-  /* # of character classes. */
-  int nchar_classes;
-} re_charset_t;
-#endif /* RE_ENABLE_I18N */
-
-typedef struct
-{
-  union
-  {
-    unsigned char c;           /* for CHARACTER */
-    re_bitset_ptr_t sbcset;    /* for SIMPLE_BRACKET */
-#ifdef RE_ENABLE_I18N
-    re_charset_t *mbcset;      /* for COMPLEX_BRACKET */
-#endif /* RE_ENABLE_I18N */
-    int idx;                   /* for BACK_REF */
-    re_context_type ctx_type;  /* for ANCHOR */
-  } opr;
-#if __GNUC__ >= 2
-  re_token_type_t type : 8;
-#else
-  re_token_type_t type;
-#endif
-  unsigned int constraint : 10;        /* context constraint */
-  unsigned int duplicated : 1;
-#ifdef RE_ENABLE_I18N
-  unsigned int mb_partial : 1;
-#endif
-} re_token_t;
-
-#define IS_EPSILON_NODE(type) \
-  ((type) == OP_ALT || (type) == OP_DUP_ASTERISK || (type) == OP_DUP_PLUS \
-   || (type) == OP_DUP_QUESTION || (type) == ANCHOR \
-   || (type) == OP_OPEN_SUBEXP || (type) == OP_CLOSE_SUBEXP)
-
-#define ACCEPT_MB_NODE(type) \
-  ((type) == COMPLEX_BRACKET || (type) == OP_PERIOD)
-
-struct re_string_t
-{
-  /* Indicate the raw buffer which is the original string passed as an
-     argument of regexec(), re_search(), etc..  */
-  const unsigned char *raw_mbs;
-  /* Store the multibyte string.  In case of "case insensitive mode" like
-     REG_ICASE, upper cases of the string are stored, otherwise MBS points
-     the same address that RAW_MBS points.  */
-  unsigned char *mbs;
-  /* Store the case sensitive multibyte string.  In case of
-     "case insensitive mode", the original string are stored,
-     otherwise MBS_CASE points the same address that MBS points.  */
-  unsigned char *mbs_case;
-#ifdef RE_ENABLE_I18N
-  /* Store the wide character string which is corresponding to MBS.  */
-  wint_t *wcs;
-  mbstate_t cur_state;
-#endif
-  /* Index in RAW_MBS.  Each character mbs[i] corresponds to
-     raw_mbs[raw_mbs_idx + i].  */
-  int raw_mbs_idx;
-  /* The length of the valid characters in the buffers.  */
-  int valid_len;
-  /* The length of the buffers MBS, MBS_CASE, and WCS.  */
-  int bufs_len;
-  /* The index in MBS, which is updated by re_string_fetch_byte.  */
-  int cur_idx;
-  /* This is length_of_RAW_MBS - RAW_MBS_IDX.  */
-  int len;
-  /* End of the buffer may be shorter than its length in the cases such
-     as re_match_2, re_search_2.  Then, we use STOP for end of the buffer
-     instead of LEN.  */
-  int stop;
-
-  /* The context of mbs[0].  We store the context independently, since
-     the context of mbs[0] may be different from raw_mbs[0], which is
-     the beginning of the input string.  */
-  unsigned int tip_context;
-  /* The translation passed as a part of an argument of re_compile_pattern.  */
-  RE_TRANSLATE_TYPE trans;
-  /* 1 if REG_ICASE.  */
-  unsigned int icase : 1;
-};
-typedef struct re_string_t re_string_t;
-/* In case of REG_ICASE, we allocate the buffer dynamically for mbs.  */
-#define MBS_ALLOCATED(pstr) (pstr->icase)
-/* In case that we need translation, we allocate the buffer dynamically
-   for mbs_case.  Note that mbs == mbs_case if not REG_ICASE.  */
-#define MBS_CASE_ALLOCATED(pstr) (pstr->trans != NULL)
-
-
-static reg_errcode_t re_string_allocate (re_string_t *pstr, const char *str,
-                                        int len, int init_len,
-                                        RE_TRANSLATE_TYPE trans, int icase);
-static reg_errcode_t re_string_construct (re_string_t *pstr, const char *str,
-                                         int len, RE_TRANSLATE_TYPE trans,
-                                         int icase);
-static reg_errcode_t re_string_reconstruct (re_string_t *pstr, int idx,
-                                           int eflags, int newline);
-static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
-                                               int new_buf_len);
-#ifdef RE_ENABLE_I18N
-static void build_wcs_buffer (re_string_t *pstr);
-static void build_wcs_upper_buffer (re_string_t *pstr);
-#endif /* RE_ENABLE_I18N */
-static void build_upper_buffer (re_string_t *pstr);
-static void re_string_translate_buffer (re_string_t *pstr);
-static void re_string_destruct (re_string_t *pstr);
-#ifdef RE_ENABLE_I18N
-static int re_string_elem_size_at (const re_string_t *pstr, int idx);
-static inline int re_string_char_size_at (const re_string_t *pstr, int idx);
-static inline wint_t re_string_wchar_at (const re_string_t *pstr, int idx);
-#endif /* RE_ENABLE_I18N */
-static unsigned int re_string_context_at (const re_string_t *input, int idx,
-                                         int eflags, int newline_anchor);
-#define re_string_peek_byte(pstr, offset) \
-  ((pstr)->mbs[(pstr)->cur_idx + offset])
-#define re_string_peek_byte_case(pstr, offset) \
-  ((pstr)->mbs_case[(pstr)->cur_idx + offset])
-#define re_string_fetch_byte(pstr) \
-  ((pstr)->mbs[(pstr)->cur_idx++])
-#define re_string_fetch_byte_case(pstr) \
-  ((pstr)->mbs_case[(pstr)->cur_idx++])
-#define re_string_first_byte(pstr, idx) \
-  ((idx) == (pstr)->len || (pstr)->wcs[idx] != WEOF)
-#define re_string_is_single_byte_char(pstr, idx) \
-  ((pstr)->wcs[idx] != WEOF && ((pstr)->len == (idx) \
-                               || (pstr)->wcs[(idx) + 1] != WEOF))
-#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
-#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
-#define re_string_get_buffer(pstr) ((pstr)->mbs)
-#define re_string_length(pstr) ((pstr)->len)
-#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
-#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
-#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
-
-#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
-#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
-#define re_free(p) free (p)
-
-struct bin_tree_t
-{
-  struct bin_tree_t *parent;
-  struct bin_tree_t *left;
-  struct bin_tree_t *right;
-
-  /* `node_idx' is the index in dfa->nodes, if `type' == 0.
-     Otherwise `type' indicate the type of this node.  */
-  re_token_type_t type;
-  int node_idx;
-
-  int first;
-  int next;
-  re_node_set eclosure;
-};
-typedef struct bin_tree_t bin_tree_t;
-
-
-#define CONTEXT_WORD 1
-#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
-#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
-#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
-
-#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
-#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
-#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
-#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
-#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
-
-#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
-#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
-#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_')
-#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
-
-#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
- ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
-  || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
-  || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
-  || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
-
-#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
- ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
-  || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
-  || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
-  || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
-
-struct re_dfastate_t
-{
-  unsigned int hash;
-  re_node_set nodes;
-  re_node_set *entrance_nodes;
-  struct re_dfastate_t **trtable;
-  struct re_dfastate_t **trtable_search;
-  /* If this state is a special state.
-     A state is a special state if the state is the halt state, or
-     a anchor.  */
-  unsigned int context : 2;
-  unsigned int halt : 1;
-  /* If this state can accept `multi byte'.
-     Note that we refer to multibyte characters, and multi character
-     collating elements as `multi byte'.  */
-  unsigned int accept_mb : 1;
-  /* If this state has backreference node(s).  */
-  unsigned int has_backref : 1;
-  unsigned int has_constraint : 1;
-};
-typedef struct re_dfastate_t re_dfastate_t;
-
-typedef struct
-{
-  /* start <= node < end  */
-  int start;
-  int end;
-} re_subexp_t;
-
-struct re_state_table_entry
-{
-  int num;
-  int alloc;
-  re_dfastate_t **array;
-};
-
-/* Array type used in re_sub_match_last_t and re_sub_match_top_t.  */
-
-typedef struct
-{
-  int next_idx;
-  int alloc;
-  re_dfastate_t **array;
-} state_array_t;
-
-/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP.  */
-
-typedef struct
-{
-  int node;
-  int str_idx; /* The position NODE match at.  */
-  state_array_t path;
-} re_sub_match_last_t;
-
-/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
-   And information about the node, whose type is OP_CLOSE_SUBEXP,
-   corresponding to NODE is stored in LASTS.  */
-
-typedef struct
-{
-  int str_idx;
-  int node;
-  int next_last_offset;
-  state_array_t *path;
-  int alasts; /* Allocation size of LASTS.  */
-  int nlasts; /* The number of LASTS.  */
-  re_sub_match_last_t **lasts;
-} re_sub_match_top_t;
-
-struct re_backref_cache_entry
-{
-  int node;
-  int str_idx;
-  int subexp_from;
-  int subexp_to;
-  int flag;
-};
-
-typedef struct
-{
-  /* EFLAGS of the argument of regexec.  */
-  int eflags;
-  /* Where the matching ends.  */
-  int match_last;
-  int last_node;
-  /* The string object corresponding to the input string.  */
-  re_string_t *input;
-  /* The state log used by the matcher.  */
-  re_dfastate_t **state_log;
-  int state_log_top;
-  /* Back reference cache.  */
-  int nbkref_ents;
-  int abkref_ents;
-  struct re_backref_cache_entry *bkref_ents;
-  int max_mb_elem_len;
-  int nsub_tops;
-  int asub_tops;
-  re_sub_match_top_t **sub_tops;
-} re_match_context_t;
-
-typedef struct
-{
-  int cur_bkref;
-  int cls_subexp_idx;
-
-  re_dfastate_t **sifted_states;
-  re_dfastate_t **limited_states;
-
-  re_node_set limits;
-
-  int last_node;
-  int last_str_idx;
-  int check_subexp;
-} re_sift_context_t;
-
-struct re_fail_stack_ent_t
-{
-  int idx;
-  int node;
-  regmatch_t *regs;
-  re_node_set eps_via_nodes;
-};
-
-struct re_fail_stack_t
-{
-  int num;
-  int alloc;
-  struct re_fail_stack_ent_t *stack;
-};
-
-struct re_dfa_t
-{
-  re_bitset_ptr_t word_char;
-
-  /* number of subexpressions `re_nsub' is in regex_t.  */
-  int subexps_alloc;
-  re_subexp_t *subexps;
-
-  re_token_t *nodes;
-  int nodes_alloc;
-  int nodes_len;
-  bin_tree_t *str_tree;
-  int *nexts;
-  int *org_indices;
-  re_node_set *edests;
-  re_node_set *eclosures;
-  re_node_set *inveclosures;
-  struct re_state_table_entry *state_table;
-  unsigned int state_hash_mask;
-  re_dfastate_t *init_state;
-  re_dfastate_t *init_state_word;
-  re_dfastate_t *init_state_nl;
-  re_dfastate_t *init_state_begbuf;
-  int states_alloc;
-  int init_node;
-  int nbackref; /* The number of backreference in this dfa.  */
-  /* Bitmap expressing which backreference is used.  */
-  unsigned int used_bkref_map;
-#ifdef DEBUG
-  char* re_str;
-#endif
-  unsigned int has_plural_match : 1;
-  /* If this dfa has "multibyte node", which is a backreference or
-     a node which can accept multibyte character or multi character
-     collating element.  */
-  unsigned int has_mb_node : 1;
-};
-typedef struct re_dfa_t re_dfa_t;
-
-static reg_errcode_t re_node_set_alloc (re_node_set *set, int size);
-static reg_errcode_t re_node_set_init_1 (re_node_set *set, int elem);
-static reg_errcode_t re_node_set_init_2 (re_node_set *set, int elem1,
-                                        int elem2);
-#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
-static reg_errcode_t re_node_set_init_copy (re_node_set *dest,
-                                           const re_node_set *src);
-static reg_errcode_t re_node_set_add_intersect (re_node_set *dest,
-                                               const re_node_set *src1,
-                                               const re_node_set *src2);
-static reg_errcode_t re_node_set_init_union (re_node_set *dest,
-                                            const re_node_set *src1,
-                                            const re_node_set *src2);
-static reg_errcode_t re_node_set_merge (re_node_set *dest,
-                                       const re_node_set *src);
-static int re_node_set_insert (re_node_set *set, int elem);
-static int re_node_set_compare (const re_node_set *set1,
-                               const re_node_set *set2);
-static int re_node_set_contains (const re_node_set *set, int elem);
-static void re_node_set_remove_at (re_node_set *set, int idx);
-#define re_node_set_remove(set,id) \
-  (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
-#define re_node_set_empty(p) ((p)->nelem = 0)
-#define re_node_set_free(set) re_free ((set)->elems)
-static int re_dfa_add_node (re_dfa_t *dfa, re_token_t token, int mode);
-static re_dfastate_t *re_acquire_state (reg_errcode_t *err, re_dfa_t *dfa,
-                                       const re_node_set *nodes);
-static re_dfastate_t *re_acquire_state_context (reg_errcode_t *err,
-                                               re_dfa_t *dfa,
-                                               const re_node_set *nodes,
-                                               unsigned int context);
-static void free_state (re_dfastate_t *state);
-\f
-
-typedef enum
-{
-  SB_CHAR,
-  MB_CHAR,
-  EQUIV_CLASS,
-  COLL_SYM,
-  CHAR_CLASS
-} bracket_elem_type;
-
-typedef struct
-{
-  bracket_elem_type type;
-  union
-  {
-    unsigned char ch;
-    unsigned char *name;
-    wchar_t wch;
-  } opr;
-} bracket_elem_t;
-
-
-/* Inline functions for bitset operation.  */
-static inline void
-bitset_not (set)
-     bitset set;
-{
-  int bitset_i;
-  for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
-    set[bitset_i] = ~set[bitset_i];
-}
-
-static inline void
-bitset_merge (dest, src)
-     bitset dest;
-     const bitset src;
-{
-  int bitset_i;
-  for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
-    dest[bitset_i] |= src[bitset_i];
-}
-
-static inline void
-bitset_not_merge (dest, src)
-     bitset dest;
-     const bitset src;
-{
-  int i;
-  for (i = 0; i < BITSET_UINTS; ++i)
-    dest[i] |= ~src[i];
-}
-
-#ifdef RE_ENABLE_I18N
-/* Inline functions for re_string.  */
-static inline int
-re_string_char_size_at (pstr, idx)
-     const re_string_t *pstr;
-     int idx;
-{
-  int byte_idx;
-  if (MB_CUR_MAX == 1)
-    return 1;
-  for (byte_idx = 1; idx + byte_idx < pstr->len; ++byte_idx)
-    if (pstr->wcs[idx + byte_idx] != WEOF)
-      break;
-  return byte_idx;
-}
-
-static inline wint_t
-re_string_wchar_at (pstr, idx)
-     const re_string_t *pstr;
-     int idx;
-{
-  if (MB_CUR_MAX == 1)
-    return (wint_t) pstr->mbs[idx];
-  return (wint_t) pstr->wcs[idx];
-}
-
-static int
-re_string_elem_size_at (pstr, idx)
-     const re_string_t *pstr;
-     int idx;
-{
-#ifdef _LIBC
-  const unsigned char *p, *extra;
-  const int32_t *table, *indirect;
-  int32_t tmp;
-# include <locale/weight.h>
-  uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-
-  if (nrules != 0)
-    {
-      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
-      extra = (const unsigned char *)
-       _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
-      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
-                                               _NL_COLLATE_INDIRECTMB);
-      p = pstr->mbs + idx;
-      tmp = findidx (&p);
-      return p - pstr->mbs - idx;
-    }
-  else
-#endif /* _LIBC */
-    return 1;
-}
-#endif /* RE_ENABLE_I18N */
-
-#endif /*  _REGEX_INTERNAL_H */
diff --git a/lib/regex/regexec.c b/lib/regex/regexec.c
deleted file mode 100644 (file)
index 6ea14a6..0000000
+++ /dev/null
@@ -1,3977 +0,0 @@
-/* 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>.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
-                                    re_string_t *input, int n);
-static void match_ctx_clean (re_match_context_t *mctx);
-static void match_ctx_free (re_match_context_t *cache);
-static void match_ctx_free_subtops (re_match_context_t *mctx);
-static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node,
-                                         int str_idx, int from, int to);
-static int search_cur_bkref_entry (re_match_context_t *mctx, int str_idx);
-static void match_ctx_clear_flag (re_match_context_t *mctx);
-static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node,
-                                          int str_idx);
-static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,
-                                                  int node, int str_idx);
-static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
-                          re_dfastate_t **limited_sts, int last_node,
-                          int last_str_idx, int check_subexp);
-static reg_errcode_t re_search_internal (const regex_t *preg,
-                                        const char *string, int length,
-                                        int start, int range, int stop,
-                                        size_t nmatch, regmatch_t pmatch[],
-                                        int eflags);
-static int re_search_2_stub (struct re_pattern_buffer *bufp,
-                            const char *string1, int length1,
-                            const char *string2, int length2,
-                            int start, int range, struct re_registers *regs,
-                            int stop, int ret_len);
-static int re_search_stub (struct re_pattern_buffer *bufp,
-                          const char *string, int length, int start,
-                          int range, int stop, struct re_registers *regs,
-                          int ret_len);
-static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
-                             int nregs, int regs_allocated);
-static inline re_dfastate_t *acquire_init_state_context (reg_errcode_t *err,
-                                                        const regex_t *preg,
-                                                        const re_match_context_t *mctx,
-                                                        int idx);
-static reg_errcode_t prune_impossible_nodes (const regex_t *preg,
-                                            re_match_context_t *mctx);
-static int check_matching (const regex_t *preg, re_match_context_t *mctx,
-                          int fl_search, int fl_longest_match);
-static int check_halt_node_context (const re_dfa_t *dfa, int node,
-                                   unsigned int context);
-static int check_halt_state_context (const regex_t *preg,
-                                    const re_dfastate_t *state,
-                                    const re_match_context_t *mctx, int idx);
-static void update_regs (re_dfa_t *dfa, regmatch_t *pmatch, int cur_node,
-                        int cur_idx, int nmatch);
-static int proceed_next_node (const regex_t *preg, int nregs, regmatch_t *regs,
-                             const re_match_context_t *mctx,
-                             int *pidx, int node, re_node_set *eps_via_nodes,
-                             struct re_fail_stack_t *fs);
-static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
-                                     int str_idx, int *dests, int nregs,
-                                     regmatch_t *regs,
-                                     re_node_set *eps_via_nodes);
-static int pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
-                          regmatch_t *regs, re_node_set *eps_via_nodes);
-static reg_errcode_t set_regs (const regex_t *preg,
-                              const re_match_context_t *mctx,
-                              size_t nmatch, regmatch_t *pmatch,
-                              int fl_backtrack);
-static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs);
-
-#ifdef RE_ENABLE_I18N
-static int sift_states_iter_mb (const regex_t *preg,
-                               const re_match_context_t *mctx,
-                               re_sift_context_t *sctx,
-                               int node_idx, int str_idx, int max_str_idx);
-#endif /* RE_ENABLE_I18N */
-static reg_errcode_t sift_states_backward (const regex_t *preg,
-                                          re_match_context_t *mctx,
-                                          re_sift_context_t *sctx);
-static reg_errcode_t update_cur_sifted_state (const regex_t *preg,
-                                             re_match_context_t *mctx,
-                                             re_sift_context_t *sctx,
-                                             int str_idx,
-                                             re_node_set *dest_nodes);
-static reg_errcode_t add_epsilon_src_nodes (re_dfa_t *dfa,
-                                           re_node_set *dest_nodes,
-                                           const re_node_set *candidates);
-static reg_errcode_t sub_epsilon_src_nodes (re_dfa_t *dfa, int node,
-                                           re_node_set *dest_nodes,
-                                           const re_node_set *and_nodes);
-static int check_dst_limits (re_dfa_t *dfa, re_node_set *limits,
-                            re_match_context_t *mctx, int dst_node,
-                            int dst_idx, int src_node, int src_idx);
-static int check_dst_limits_calc_pos (re_dfa_t *dfa, re_match_context_t *mctx,
-                                     int limit, re_node_set *eclosures,
-                                     int subexp_idx, int node, int str_idx);
-static reg_errcode_t check_subexp_limits (re_dfa_t *dfa,
-                                         re_node_set *dest_nodes,
-                                         const re_node_set *candidates,
-                                         re_node_set *limits,
-                                         struct re_backref_cache_entry *bkref_ents,
-                                         int str_idx);
-static reg_errcode_t sift_states_bkref (const regex_t *preg,
-                                       re_match_context_t *mctx,
-                                       re_sift_context_t *sctx,
-                                       int str_idx, re_node_set *dest_nodes);
-static reg_errcode_t clean_state_log_if_need (re_match_context_t *mctx,
-                                             int next_state_log_idx);
-static reg_errcode_t merge_state_array (re_dfa_t *dfa, re_dfastate_t **dst,
-                                       re_dfastate_t **src, int num);
-static re_dfastate_t *transit_state (reg_errcode_t *err, const regex_t *preg,
-                                    re_match_context_t *mctx,
-                                    re_dfastate_t *state, int fl_search);
-static reg_errcode_t check_subexp_matching_top (re_dfa_t *dfa,
-                                               re_match_context_t *mctx,
-                                               re_node_set *cur_nodes,
-                                               int str_idx);
-static re_dfastate_t *transit_state_sb (reg_errcode_t *err, const regex_t *preg,
-                                       re_dfastate_t *pstate,
-                                       int fl_search,
-                                       re_match_context_t *mctx);
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t transit_state_mb (const regex_t *preg,
-                                      re_dfastate_t *pstate,
-                                      re_match_context_t *mctx);
-#endif /* RE_ENABLE_I18N */
-static reg_errcode_t transit_state_bkref (const regex_t *preg,
-                                         re_node_set *nodes,
-                                         re_match_context_t *mctx);
-static reg_errcode_t get_subexp (const regex_t *preg, re_match_context_t *mctx,
-                                int bkref_node, int bkref_str_idx);
-static reg_errcode_t get_subexp_sub (const regex_t *preg,
-                                    re_match_context_t *mctx,
-                                    re_sub_match_top_t *sub_top,
-                                    re_sub_match_last_t *sub_last,
-                                    int bkref_node, int bkref_str);
-static int find_subexp_node (re_dfa_t *dfa, re_node_set *nodes,
-                            int subexp_idx, int fl_open);
-static reg_errcode_t check_arrival (const regex_t *preg,
-                                   re_match_context_t *mctx,
-                                   state_array_t *path, int top_node,
-                                   int top_str, int last_node, int last_str,
-                                   int fl_open);
-static reg_errcode_t check_arrival_add_next_nodes (const regex_t *preg,
-                                                  re_dfa_t *dfa,
-                                                  re_match_context_t *mctx,
-                                                  int str_idx,
-                                                  re_node_set *cur_nodes,
-                                                  re_node_set *next_nodes);
-static reg_errcode_t check_arrival_expand_ecl (re_dfa_t *dfa,
-                                              re_node_set *cur_nodes,
-                                              int ex_subexp, int fl_open);
-static reg_errcode_t check_arrival_expand_ecl_sub (re_dfa_t *dfa,
-                                                  re_node_set *dst_nodes,
-                                                  int target, int ex_subexp,
-                                                  int fl_open);
-static reg_errcode_t expand_bkref_cache (const regex_t *preg,
-                                        re_match_context_t *mctx,
-                                        re_node_set *cur_nodes, int cur_str,
-                                        int last_str, int subexp_num,
-                                        int fl_open);
-static re_dfastate_t **build_trtable (const regex_t *dfa,
-                                     const re_dfastate_t *state,
-                                     int fl_search);
-#ifdef RE_ENABLE_I18N
-static int check_node_accept_bytes (const regex_t *preg, int node_idx,
-                                   const re_string_t *input, int idx);
-# ifdef _LIBC
-static unsigned int find_collation_sequence_value (const unsigned char *mbs,
-                                                  size_t name_len);
-# endif /* _LIBC */
-#endif /* RE_ENABLE_I18N */
-static int group_nodes_into_DFAstates (const regex_t *dfa,
-                                      const re_dfastate_t *state,
-                                      re_node_set *states_node,
-                                      bitset *states_ch);
-static int check_node_accept (const regex_t *preg, const re_token_t *node,
-                             const re_match_context_t *mctx, int idx);
-static reg_errcode_t extend_buffers (re_match_context_t *mctx);
-\f
-/* Entry point for POSIX code.  */
-
-/* regexec searches for a given pattern, specified by PREG, in the
-   string STRING.
-
-   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
-   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
-   least NMATCH elements, and we set them to the offsets of the
-   corresponding matched substrings.
-
-   EFLAGS specifies `execution flags' which affect matching: if
-   REG_NOTBOL is set, then ^ does not match at the beginning of the
-   string; if REG_NOTEOL is set, then $ does not match at the end.
-
-   We return 0 if we find a match and REG_NOMATCH if not.  */
-
-int
-regexec (preg, string, nmatch, pmatch, eflags)
-    const regex_t *__restrict preg;
-    const char *__restrict string;
-    size_t nmatch;
-    regmatch_t pmatch[];
-    int eflags;
-{
-  reg_errcode_t err;
-  int length = strlen (string);
-  if (preg->no_sub)
-    err = re_search_internal (preg, string, length, 0, length, length, 0,
-                             NULL, eflags);
-  else
-    err = re_search_internal (preg, string, length, 0, length, length, nmatch,
-                             pmatch, eflags);
-  return err != REG_NOERROR;
-}
-#ifdef _LIBC
-weak_alias (__regexec, regexec)
-#endif
-
-/* Entry points for GNU code.  */
-
-/* re_match, re_search, re_match_2, re_search_2
-
-   The former two functions operate on STRING with length LENGTH,
-   while the later two operate on concatenation of STRING1 and STRING2
-   with lengths LENGTH1 and LENGTH2, respectively.
-
-   re_match() matches the compiled pattern in BUFP against the string,
-   starting at index START.
-
-   re_search() first tries matching at index START, then it tries to match
-   starting from index START + 1, and so on.  The last start position tried
-   is START + RANGE.  (Thus RANGE = 0 forces re_search to operate the same
-   way as re_match().)
-
-   The parameter STOP of re_{match,search}_2 specifies that no match exceeding
-   the first STOP characters of the concatenation of the strings should be
-   concerned.
-
-   If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
-   and all groups is stroed in REGS.  (For the "_2" variants, the offsets are
-   computed relative to the concatenation, not relative to the individual
-   strings.)
-
-   On success, re_match* functions return the length of the match, re_search*
-   return the position of the start of the match.  Return value -1 means no
-   match was found and -2 indicates an internal error.  */
-
-int
-re_match (bufp, string, length, start, regs)
-    struct re_pattern_buffer *bufp;
-    const char *string;
-    int length, start;
-    struct re_registers *regs;
-{
-  return re_search_stub (bufp, string, length, start, 0, length, regs, 1);
-}
-#ifdef _LIBC
-weak_alias (__re_match, re_match)
-#endif
-
-int
-re_search (bufp, string, length, start, range, regs)
-    struct re_pattern_buffer *bufp;
-    const char *string;
-    int length, start, range;
-    struct re_registers *regs;
-{
-  return re_search_stub (bufp, string, length, start, range, length, regs, 0);
-}
-#ifdef _LIBC
-weak_alias (__re_search, re_search)
-#endif
-
-int
-re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop)
-    struct re_pattern_buffer *bufp;
-    const char *string1, *string2;
-    int length1, length2, start, stop;
-    struct re_registers *regs;
-{
-  return re_search_2_stub (bufp, string1, length1, string2, length2,
-                          start, 0, regs, stop, 1);
-}
-#ifdef _LIBC
-weak_alias (__re_match_2, re_match_2)
-#endif
-
-int
-re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop)
-    struct re_pattern_buffer *bufp;
-    const char *string1, *string2;
-    int length1, length2, start, range, stop;
-    struct re_registers *regs;
-{
-  return re_search_2_stub (bufp, string1, length1, string2, length2,
-                          start, range, regs, stop, 0);
-}
-#ifdef _LIBC
-weak_alias (__re_search_2, re_search_2)
-#endif
-
-static int
-re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs,
-                 stop, ret_len)
-    struct re_pattern_buffer *bufp;
-    const char *string1, *string2;
-    int length1, length2, start, range, stop, ret_len;
-    struct re_registers *regs;
-{
-  const char *str;
-  int rval;
-  int len = length1 + length2;
-  int free_str = 0;
-
-  if (BE (length1 < 0 || length2 < 0 || stop < 0, 0))
-    return -2;
-
-  /* Concatenate the strings.  */
-  if (length2 > 0)
-    if (length1 > 0)
-      {
-       char *s = re_malloc (char, len);
-
-       if (BE (s == NULL, 0))
-         return -2;
-       memcpy (s, string1, length1);
-       memcpy (s + length1, string2, length2);
-       str = s;
-       free_str = 1;
-      }
-    else
-      str = string2;
-  else
-    str = string1;
-
-  rval = re_search_stub (bufp, str, len, start, range, stop, regs,
-                        ret_len);
-  if (free_str)
-    re_free ((char *) str);
-  return rval;
-}
-
-/* The parameters have the same meaning as those of re_search.
-   Additional parameters:
-   If RET_LEN is nonzero the length of the match is returned (re_match style);
-   otherwise the position of the match is returned.  */
-
-static int
-re_search_stub (bufp, string, length, start, range, stop, regs, ret_len)
-    struct re_pattern_buffer *bufp;
-    const char *string;
-    int length, start, range, stop, ret_len;
-    struct re_registers *regs;
-{
-  reg_errcode_t result;
-  regmatch_t *pmatch;
-  int nregs, rval;
-  int eflags = 0;
-
-  /* Check for out-of-range.  */
-  if (BE (start < 0 || start > length, 0))
-    return -1;
-  if (BE (start + range > length, 0))
-    range = length - start;
-  else if (BE (start + range < 0, 0))
-    range = -start;
-
-  eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
-  eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
-
-  /* Compile fastmap if we haven't yet.  */
-  if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate)
-    re_compile_fastmap (bufp);
-
-  if (BE (bufp->no_sub, 0))
-    regs = NULL;
-
-  /* We need at least 1 register.  */
-  if (regs == NULL)
-    nregs = 1;
-  else if (BE (bufp->regs_allocated == REGS_FIXED &&
-              regs->num_regs < bufp->re_nsub + 1, 0))
-    {
-      nregs = regs->num_regs;
-      if (BE (nregs < 1, 0))
-       {
-         /* Nothing can be copied to regs.  */
-         regs = NULL;
-         nregs = 1;
-       }
-    }
-  else
-    nregs = bufp->re_nsub + 1;
-  pmatch = re_malloc (regmatch_t, nregs);
-  if (BE (pmatch == NULL, 0))
-    return -2;
-
-  result = re_search_internal (bufp, string, length, start, range, stop,
-                              nregs, pmatch, eflags);
-
-  rval = 0;
-
-  /* I hope we needn't fill ther regs with -1's when no match was found.  */
-  if (result != REG_NOERROR)
-    rval = -1;
-  else if (regs != NULL)
-    {
-      /* If caller wants register contents data back, copy them.  */
-      bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
-                                          bufp->regs_allocated);
-      if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0))
-       rval = -2;
-    }
-
-  if (BE (rval == 0, 1))
-    {
-      if (ret_len)
-       {
-         assert (pmatch[0].rm_so == start);
-         rval = pmatch[0].rm_eo - start;
-       }
-      else
-       rval = pmatch[0].rm_so;
-    }
-  re_free (pmatch);
-  return rval;
-}
-
-static unsigned
-re_copy_regs (regs, pmatch, nregs, regs_allocated)
-    struct re_registers *regs;
-    regmatch_t *pmatch;
-    int nregs, regs_allocated;
-{
-  int rval = REGS_REALLOCATE;
-  int i;
-  int need_regs = nregs + 1;
-  /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
-     uses.  */
-
-  /* Have the register data arrays been allocated?  */
-  if (regs_allocated == REGS_UNALLOCATED)
-    { /* No.  So allocate them with malloc.  */
-      regs->start = re_malloc (regoff_t, need_regs);
-      if (BE (regs->start == NULL, 0))
-       return REGS_UNALLOCATED;
-      regs->end = re_malloc (regoff_t, need_regs);
-      if (BE (regs->end == NULL, 0))
-       {
-         re_free (regs->start);
-         return REGS_UNALLOCATED;
-       }
-      regs->num_regs = need_regs;
-    }
-  else if (regs_allocated == REGS_REALLOCATE)
-    { /* Yes.  If we need more elements than were already
-        allocated, reallocate them.  If we need fewer, just
-        leave it alone.  */
-      if (need_regs > regs->num_regs)
-       {
-         regs->start = re_realloc (regs->start, regoff_t, need_regs);
-         if (BE (regs->start == NULL, 0))
-           {
-             if (regs->end != NULL)
-               re_free (regs->end);
-             return REGS_UNALLOCATED;
-           }
-         regs->end = re_realloc (regs->end, regoff_t, need_regs);
-         if (BE (regs->end == NULL, 0))
-           {
-             re_free (regs->start);
-             return REGS_UNALLOCATED;
-           }
-         regs->num_regs = need_regs;
-       }
-    }
-  else
-    {
-      assert (regs_allocated == REGS_FIXED);
-      /* This function may not be called with REGS_FIXED and nregs too big.  */
-      assert (regs->num_regs >= nregs);
-      rval = REGS_FIXED;
-    }
-
-  /* Copy the regs.  */
-  for (i = 0; i < nregs; ++i)
-    {
-      regs->start[i] = pmatch[i].rm_so;
-      regs->end[i] = pmatch[i].rm_eo;
-    }
-  for ( ; i < regs->num_regs; ++i)
-    regs->start[i] = regs->end[i] = -1;
-
-  return rval;
-}
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
-   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
-   this memory for recording register information.  STARTS and ENDS
-   must be allocated using the malloc library routine, and must each
-   be at least NUM_REGS * sizeof (regoff_t) bytes long.
-
-   If NUM_REGS == 0, then subsequent matches should allocate their own
-   register data.
-
-   Unless this function is called, the first search or match using
-   PATTERN_BUFFER will allocate its own register data, without
-   freeing the old data.  */
-
-void
-re_set_registers (bufp, regs, num_regs, starts, ends)
-    struct re_pattern_buffer *bufp;
-    struct re_registers *regs;
-    unsigned num_regs;
-    regoff_t *starts, *ends;
-{
-  if (num_regs)
-    {
-      bufp->regs_allocated = REGS_REALLOCATE;
-      regs->num_regs = num_regs;
-      regs->start = starts;
-      regs->end = ends;
-    }
-  else
-    {
-      bufp->regs_allocated = REGS_UNALLOCATED;
-      regs->num_regs = 0;
-      regs->start = regs->end = (regoff_t *) 0;
-    }
-}
-#ifdef _LIBC
-weak_alias (__re_set_registers, re_set_registers)
-#endif
-\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
-int
-# ifdef _LIBC
-weak_function
-# endif
-re_exec (s)
-     const char *s;
-{
-  return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);
-}
-#endif /* _REGEX_RE_COMP */
-\f
-static re_node_set empty_set;
-
-/* Internal entry point.  */
-
-/* Searches for a compiled pattern PREG in the string STRING, whose
-   length is LENGTH.  NMATCH, PMATCH, and EFLAGS have the same
-   mingings with regexec.  START, and RANGE have the same meanings
-   with re_search.
-   Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
-   otherwise return the error code.
-   Note: We assume front end functions already check ranges.
-   (START + RANGE >= 0 && START + RANGE <= LENGTH)  */
-
-static reg_errcode_t
-re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
-                   eflags)
-    const regex_t *preg;
-    const char *string;
-    int length, start, range, stop, eflags;
-    size_t nmatch;
-    regmatch_t pmatch[];
-{
-  reg_errcode_t err;
-  re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
-  re_string_t input;
-  int left_lim, right_lim, incr;
-  int fl_longest_match, match_first, match_last = -1;
-  int fast_translate, sb;
-  re_match_context_t mctx;
-  char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate
-                   && range && !preg->can_be_null) ? preg->fastmap : NULL);
-
-  /* Check if the DFA haven't been compiled.  */
-  if (BE (preg->used == 0 || dfa->init_state == NULL
-         || dfa->init_state_word == NULL || dfa->init_state_nl == NULL
-         || dfa->init_state_begbuf == NULL, 0))
-    return REG_NOMATCH;
-
-  re_node_set_init_empty (&empty_set);
-  memset (&mctx, '\0', sizeof (re_match_context_t));
-
-  /* We must check the longest matching, if nmatch > 0.  */
-  fl_longest_match = (nmatch != 0 || dfa->nbackref);
-
-  err = re_string_allocate (&input, string, length, dfa->nodes_len + 1,
-                           preg->translate, preg->syntax & RE_ICASE);
-  if (BE (err != REG_NOERROR, 0))
-    goto free_return;
-  input.stop = stop;
-
-  err = match_ctx_init (&mctx, eflags, &input, dfa->nbackref * 2);
-  if (BE (err != REG_NOERROR, 0))
-    goto free_return;
-
-  /* We will log all the DFA states through which the dfa pass,
-     if nmatch > 1, or this dfa has "multibyte node", which is a
-     back-reference or a node which can accept multibyte character or
-     multi character collating element.  */
-  if (nmatch > 1 || dfa->has_mb_node)
-    {
-      mctx.state_log = re_malloc (re_dfastate_t *, dfa->nodes_len + 1);
-      if (BE (mctx.state_log == NULL, 0))
-       {
-         err = REG_ESPACE;
-         goto free_return;
-       }
-    }
-  else
-    mctx.state_log = NULL;
-
-#ifdef DEBUG
-  /* We assume front-end functions already check them.  */
-  assert (start + range >= 0 && start + range <= length);
-#endif
-
-  match_first = start;
-  input.tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
-                      : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
-
-  /* Check incrementally whether of not the input string match.  */
-  incr = (range < 0) ? -1 : 1;
-  left_lim = (range < 0) ? start + range : start;
-  right_lim = (range < 0) ? start : start + range;
-  sb = MB_CUR_MAX == 1;
-  fast_translate = sb || !(preg->syntax & RE_ICASE || preg->translate);
-
-  for (;;)
-    {
-      /* At first get the current byte from input string.  */
-      if (fastmap)
-       {
-         if (BE (fast_translate, 1))
-           {
-             unsigned RE_TRANSLATE_TYPE t
-               = (unsigned RE_TRANSLATE_TYPE) preg->translate;
-             if (BE (range >= 0, 1))
-               {
-                 if (BE (t != NULL, 0))
-                   {
-                     while (BE (match_first < right_lim, 1)
-                            && !fastmap[t[(unsigned char) string[match_first]]])
-                       ++match_first;
-                   }
-                 else
-                   {
-                     while (BE (match_first < right_lim, 1)
-                            && !fastmap[(unsigned char) string[match_first]])
-                       ++match_first;
-                   }
-                 if (BE (match_first == right_lim, 0))
-                   {
-                     int ch = match_first >= length
-                              ? 0 : (unsigned char) string[match_first];
-                     if (!fastmap[t ? t[ch] : ch])
-                       break;
-                   }
-               }
-             else
-               {
-                 while (match_first >= left_lim)
-                   {
-                     int ch = match_first >= length
-                              ? 0 : (unsigned char) string[match_first];
-                     if (fastmap[t ? t[ch] : ch])
-                       break;
-                     --match_first;
-                   }
-                 if (match_first < left_lim)
-                   break;
-               }
-           }
-         else
-           {
-             int ch;
-
-             do
-               {
-                 /* In this case, we can't determine easily the current byte,
-                    since it might be a component byte of a multibyte
-                    character.  Then we use the constructed buffer
-                    instead.  */
-                 /* If MATCH_FIRST is out of the valid range, reconstruct the
-                    buffers.  */
-                 if (input.raw_mbs_idx + input.valid_len <= match_first
-                     || match_first < input.raw_mbs_idx)
-                   {
-                     err = re_string_reconstruct (&input, match_first, eflags,
-                                                  preg->newline_anchor);
-                     if (BE (err != REG_NOERROR, 0))
-                       goto free_return;
-                   }
-                 /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
-                    Note that MATCH_FIRST must not be smaller than 0.  */
-                 ch = ((match_first >= length) ? 0
-                      : re_string_byte_at (&input,
-                                           match_first - input.raw_mbs_idx));
-                 if (fastmap[ch])
-                   break;
-                 match_first += incr;
-               }
-             while (match_first >= left_lim && match_first <= right_lim);
-             if (! fastmap[ch])
-               break;
-           }
-       }
-
-      /* Reconstruct the buffers so that the matcher can assume that
-        the matching starts from the begining of the buffer.  */
-      err = re_string_reconstruct (&input, match_first, eflags,
-                                  preg->newline_anchor);
-      if (BE (err != REG_NOERROR, 0))
-       goto free_return;
-#ifdef RE_ENABLE_I18N
-     /* Eliminate it when it is a component of a multibyte character
-        and isn't the head of a multibyte character.  */
-      if (sb || re_string_first_byte (&input, 0))
-#endif
-       {
-         /* It seems to be appropriate one, then use the matcher.  */
-         /* We assume that the matching starts from 0.  */
-         mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
-         match_last = check_matching (preg, &mctx, 0, fl_longest_match);
-         if (match_last != -1)
-           {
-             if (BE (match_last == -2, 0))
-               {
-                 err = REG_ESPACE;
-                 goto free_return;
-               }
-             else
-               {
-                 mctx.match_last = match_last;
-                 if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
-                   {
-                     re_dfastate_t *pstate = mctx.state_log[match_last];
-                     mctx.last_node = check_halt_state_context (preg, pstate,
-                                                                &mctx, match_last);
-                   }
-                 if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
-                     || dfa->nbackref)
-                   {
-                     err = prune_impossible_nodes (preg, &mctx);
-                     if (err == REG_NOERROR)
-                       break;
-                     if (BE (err != REG_NOMATCH, 0))
-                       goto free_return;
-                   }
-                 else
-                   break; /* We found a matching.  */
-               }
-           }
-         match_ctx_clean (&mctx);
-       }
-      /* Update counter.  */
-      match_first += incr;
-      if (match_first < left_lim || right_lim < match_first)
-       break;
-    }
-
-  /* Set pmatch[] if we need.  */
-  if (match_last != -1 && nmatch > 0)
-    {
-      int reg_idx;
-
-      /* Initialize registers.  */
-      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
-       pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;
-
-      /* Set the points where matching start/end.  */
-      pmatch[0].rm_so = 0;
-      pmatch[0].rm_eo = mctx.match_last;
-
-      if (!preg->no_sub && nmatch > 1)
-       {
-         err = set_regs (preg, &mctx, nmatch, pmatch,
-                         dfa->has_plural_match && dfa->nbackref > 0);
-         if (BE (err != REG_NOERROR, 0))
-           goto free_return;
-       }
-
-      /* At last, add the offset to the each registers, since we slided
-        the buffers so that We can assume that the matching starts from 0.  */
-      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
-       if (pmatch[reg_idx].rm_so != -1)
-         {
-           pmatch[reg_idx].rm_so += match_first;
-           pmatch[reg_idx].rm_eo += match_first;
-         }
-    }
-  err = (match_last == -1) ? REG_NOMATCH : REG_NOERROR;
- free_return:
-  re_free (mctx.state_log);
-  if (dfa->nbackref)
-    match_ctx_free (&mctx);
-  re_string_destruct (&input);
-  return err;
-}
-
-static reg_errcode_t
-prune_impossible_nodes (preg, mctx)
-     const regex_t *preg;
-     re_match_context_t *mctx;
-{
-  int halt_node, match_last;
-  reg_errcode_t ret;
-  re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
-  re_dfastate_t **sifted_states;
-  re_dfastate_t **lim_states = NULL;
-  re_sift_context_t sctx;
-#ifdef DEBUG
-  assert (mctx->state_log != NULL);
-#endif
-  match_last = mctx->match_last;
-  halt_node = mctx->last_node;
-  sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
-  if (BE (sifted_states == NULL, 0))
-    {
-      ret = REG_ESPACE;
-      goto free_return;
-    }
-  if (dfa->nbackref)
-    {
-      lim_states = re_malloc (re_dfastate_t *, match_last + 1);
-      if (BE (lim_states == NULL, 0))
-       {
-         ret = REG_ESPACE;
-         goto free_return;
-       }
-      while (1)
-       {
-         memset (lim_states, '\0',
-                 sizeof (re_dfastate_t *) * (match_last + 1));
-         match_ctx_clear_flag (mctx);
-         sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
-                        match_last, 0);
-         ret = sift_states_backward (preg, mctx, &sctx);
-         re_node_set_free (&sctx.limits);
-         if (BE (ret != REG_NOERROR, 0))
-             goto free_return;
-         if (sifted_states[0] != NULL || lim_states[0] != NULL)
-           break;
-         do
-           {
-             --match_last;
-             if (match_last < 0)
-               {
-                 ret = REG_NOMATCH;
-                 goto free_return;
-               }
-           } while (!mctx->state_log[match_last]->halt);
-         halt_node = check_halt_state_context (preg,
-                                               mctx->state_log[match_last],
-                                               mctx, match_last);
-       }
-      ret = merge_state_array (dfa, sifted_states, lim_states,
-                              match_last + 1);
-      re_free (lim_states);
-      lim_states = NULL;
-      if (BE (ret != REG_NOERROR, 0))
-       goto free_return;
-    }
-  else
-    {
-      sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
-                    match_last, 0);
-      ret = sift_states_backward (preg, mctx, &sctx);
-      re_node_set_free (&sctx.limits);
-      if (BE (ret != REG_NOERROR, 0))
-       goto free_return;
-    }
-  re_free (mctx->state_log);
-  mctx->state_log = sifted_states;
-  sifted_states = NULL;
-  mctx->last_node = halt_node;
-  mctx->match_last = match_last;
-  ret = REG_NOERROR;
- free_return:
-  re_free (sifted_states);
-  re_free (lim_states);
-  return ret;
-}
-
-/* Acquire an initial state and return it.
-   We must select appropriate initial state depending on the context,
-   since initial states may have constraints like "\<", "^", etc..  */
-
-static inline re_dfastate_t *
-acquire_init_state_context (err, preg, mctx, idx)
-     reg_errcode_t *err;
-     const regex_t *preg;
-     const re_match_context_t *mctx;
-     int idx;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-
-  *err = REG_NOERROR;
-  if (dfa->init_state->has_constraint)
-    {
-      unsigned int context;
-      context =  re_string_context_at (mctx->input, idx - 1, mctx->eflags,
-                                      preg->newline_anchor);
-      if (IS_WORD_CONTEXT (context))
-       return dfa->init_state_word;
-      else if (IS_ORDINARY_CONTEXT (context))
-       return dfa->init_state;
-      else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
-       return dfa->init_state_begbuf;
-      else if (IS_NEWLINE_CONTEXT (context))
-       return dfa->init_state_nl;
-      else if (IS_BEGBUF_CONTEXT (context))
-       {
-         /* It is relatively rare case, then calculate on demand.  */
-         return  re_acquire_state_context (err, dfa,
-                                           dfa->init_state->entrance_nodes,
-                                           context);
-       }
-      else
-       /* Must not happen?  */
-       return dfa->init_state;
-    }
-  else
-    return dfa->init_state;
-}
-
-/* Check whether the regular expression match input string INPUT or not,
-   and return the index where the matching end, return -1 if not match,
-   or return -2 in case of an error.
-   FL_SEARCH means we must search where the matching starts,
-   FL_LONGEST_MATCH means we want the POSIX longest matching.
-   Note that the matcher assume that the maching starts from the current
-   index of the buffer.  */
-
-static int
-check_matching (preg, mctx, fl_search, fl_longest_match)
-    const regex_t *preg;
-    re_match_context_t *mctx;
-    int fl_search, fl_longest_match;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  reg_errcode_t err;
-  int match = 0;
-  int match_last = -1;
-  int cur_str_idx = re_string_cur_idx (mctx->input);
-  re_dfastate_t *cur_state;
-
-  cur_state = acquire_init_state_context (&err, preg, mctx, cur_str_idx);
-  /* An initial state must not be NULL(invalid state).  */
-  if (BE (cur_state == NULL, 0))
-    return -2;
-  if (mctx->state_log != NULL)
-    mctx->state_log[cur_str_idx] = cur_state;
-
-  /* Check OP_OPEN_SUBEXP in the initial state in case that we use them
-     later.  E.g. Processing back references.  */
-  if (dfa->nbackref)
-    {
-      err = check_subexp_matching_top (dfa, mctx, &cur_state->nodes, 0);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-    }
-
-  if (cur_state->has_backref)
-    {
-      err = transit_state_bkref (preg, &cur_state->nodes, mctx);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-    }
-
-  /* If the RE accepts NULL string.  */
-  if (cur_state->halt)
-    {
-      if (!cur_state->has_constraint
-         || check_halt_state_context (preg, cur_state, mctx, cur_str_idx))
-       {
-         if (!fl_longest_match)
-           return cur_str_idx;
-         else
-           {
-             match_last = cur_str_idx;
-             match = 1;
-           }
-       }
-    }
-
-  while (!re_string_eoi (mctx->input))
-    {
-      cur_state = transit_state (&err, preg, mctx, cur_state,
-                                fl_search && !match);
-      if (cur_state == NULL) /* Reached at the invalid state or an error.  */
-       {
-         cur_str_idx = re_string_cur_idx (mctx->input);
-         if (BE (err != REG_NOERROR, 0))
-           return -2;
-         if (fl_search && !match)
-           {
-             /* Restart from initial state, since we are searching
-                the point from where matching start.  */
-#ifdef RE_ENABLE_I18N
-             if (MB_CUR_MAX == 1
-                 || re_string_first_byte (mctx->input, cur_str_idx))
-#endif /* RE_ENABLE_I18N */
-               cur_state = acquire_init_state_context (&err, preg, mctx,
-                                                       cur_str_idx);
-             if (BE (cur_state == NULL && err != REG_NOERROR, 0))
-               return -2;
-             if (mctx->state_log != NULL)
-               mctx->state_log[cur_str_idx] = cur_state;
-           }
-         else if (!fl_longest_match && match)
-           break;
-         else /* (fl_longest_match && match) || (!fl_search && !match)  */
-           {
-             if (mctx->state_log == NULL)
-               break;
-             else
-               {
-                 int max = mctx->state_log_top;
-                 for (; cur_str_idx <= max; ++cur_str_idx)
-                   if (mctx->state_log[cur_str_idx] != NULL)
-                     break;
-                 if (cur_str_idx > max)
-                   break;
-               }
-           }
-       }
-
-      if (cur_state != NULL && cur_state->halt)
-       {
-         /* Reached at a halt state.
-            Check the halt state can satisfy the current context.  */
-         if (!cur_state->has_constraint
-             || check_halt_state_context (preg, cur_state, mctx,
-                                          re_string_cur_idx (mctx->input)))
-           {
-             /* We found an appropriate halt state.  */
-             match_last = re_string_cur_idx (mctx->input);
-             match = 1;
-             if (!fl_longest_match)
-               break;
-           }
-       }
-   }
-  return match_last;
-}
-
-/* Check NODE match the current context.  */
-
-static int check_halt_node_context (dfa, node, context)
-    const re_dfa_t *dfa;
-    int node;
-    unsigned int context;
-{
-  re_token_type_t type = dfa->nodes[node].type;
-  unsigned int constraint = dfa->nodes[node].constraint;
-  if (type != END_OF_RE)
-    return 0;
-  if (!constraint)
-    return 1;
-  if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))
-    return 0;
-  return 1;
-}
-
-/* Check the halt state STATE match the current context.
-   Return 0 if not match, if the node, STATE has, is a halt node and
-   match the context, return the node.  */
-
-static int
-check_halt_state_context (preg, state, mctx, idx)
-    const regex_t *preg;
-    const re_dfastate_t *state;
-    const re_match_context_t *mctx;
-    int idx;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  int i;
-  unsigned int context;
-#ifdef DEBUG
-  assert (state->halt);
-#endif
-  context = re_string_context_at (mctx->input, idx, mctx->eflags,
-                                 preg->newline_anchor);
-  for (i = 0; i < state->nodes.nelem; ++i)
-    if (check_halt_node_context (dfa, state->nodes.elems[i], context))
-      return state->nodes.elems[i];
-  return 0;
-}
-
-/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
-   corresponding to the DFA).
-   Return the destination node, and update EPS_VIA_NODES, return -1 in case
-   of errors.  */
-
-static int
-proceed_next_node (preg, nregs, regs, mctx, pidx, node, eps_via_nodes, fs)
-    const regex_t *preg;
-    regmatch_t *regs;
-    const re_match_context_t *mctx;
-    int nregs, *pidx, node;
-    re_node_set *eps_via_nodes;
-    struct re_fail_stack_t *fs;
-{
-  re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
-  int i, err, dest_node;
-  dest_node = -1;
-  if (IS_EPSILON_NODE (dfa->nodes[node].type))
-    {
-      re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
-      int ndest, dest_nodes[2];
-      err = re_node_set_insert (eps_via_nodes, node);
-      if (BE (err < 0, 0))
-       return -1;
-      /* Pick up valid destinations.  */
-      for (ndest = 0, i = 0; i < dfa->edests[node].nelem; ++i)
-       {
-         int candidate = dfa->edests[node].elems[i];
-         if (!re_node_set_contains (cur_nodes, candidate))
-           continue;
-         dest_nodes[0] = (ndest == 0) ? candidate : dest_nodes[0];
-         dest_nodes[1] = (ndest == 1) ? candidate : dest_nodes[1];
-         ++ndest;
-       }
-      if (ndest <= 1)
-       return ndest == 0 ? -1 : (ndest == 1 ? dest_nodes[0] : 0);
-      /* In order to avoid infinite loop like "(a*)*".  */
-      if (re_node_set_contains (eps_via_nodes, dest_nodes[0]))
-       return dest_nodes[1];
-      if (fs != NULL)
-       push_fail_stack (fs, *pidx, dest_nodes, nregs, regs, eps_via_nodes);
-      return dest_nodes[0];
-    }
-  else
-    {
-      int naccepted = 0;
-      re_token_type_t type = dfa->nodes[node].type;
-
-#ifdef RE_ENABLE_I18N
-      if (ACCEPT_MB_NODE (type))
-       naccepted = check_node_accept_bytes (preg, node, mctx->input, *pidx);
-      else
-#endif /* RE_ENABLE_I18N */
-      if (type == OP_BACK_REF)
-       {
-         int subexp_idx = dfa->nodes[node].opr.idx;
-         naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
-         if (fs != NULL)
-           {
-             if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)
-               return -1;
-             else if (naccepted)
-               {
-                 char *buf = (char *) re_string_get_buffer (mctx->input);
-                 if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
-                             naccepted) != 0)
-                   return -1;
-               }
-           }
-
-         if (naccepted == 0)
-           {
-             err = re_node_set_insert (eps_via_nodes, node);
-             if (BE (err < 0, 0))
-               return -2;
-             dest_node = dfa->edests[node].elems[0];
-             if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
-                                       dest_node))
-               return dest_node;
-           }
-       }
-
-      if (naccepted != 0
-         || check_node_accept (preg, dfa->nodes + node, mctx, *pidx))
-       {
-         dest_node = dfa->nexts[node];
-         *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
-         if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
-                    || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
-                                              dest_node)))
-           return -1;
-         re_node_set_empty (eps_via_nodes);
-         return dest_node;
-       }
-    }
-  return -1;
-}
-
-static reg_errcode_t
-push_fail_stack (fs, str_idx, dests, nregs, regs, eps_via_nodes)
-     struct re_fail_stack_t *fs;
-     int str_idx, *dests, nregs;
-     regmatch_t *regs;
-     re_node_set *eps_via_nodes;
-{
-  reg_errcode_t err;
-  int num = fs->num++;
-  if (fs->num == fs->alloc)
-    {
-      struct re_fail_stack_ent_t *new_array;
-      fs->alloc *= 2;
-      new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)
-                                      * fs->alloc));
-      if (new_array == NULL)
-       return REG_ESPACE;
-      fs->stack = new_array;
-    }
-  fs->stack[num].idx = str_idx;
-  fs->stack[num].node = dests[1];
-  fs->stack[num].regs = re_malloc (regmatch_t, nregs);
-  memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
-  err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
-  return err;
-}
-
-static int
-pop_fail_stack (fs, pidx, nregs, regs, eps_via_nodes)
-     struct re_fail_stack_t *fs;
-     int *pidx, nregs;
-     regmatch_t *regs;
-     re_node_set *eps_via_nodes;
-{
-  int num = --fs->num;
-  assert (num >= 0);
- *pidx = fs->stack[num].idx;
-  memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
-  re_node_set_free (eps_via_nodes);
-  re_free (fs->stack[num].regs);
-  *eps_via_nodes = fs->stack[num].eps_via_nodes;
-  return fs->stack[num].node;
-}
-
-/* Set the positions where the subexpressions are starts/ends to registers
-   PMATCH.
-   Note: We assume that pmatch[0] is already set, and
-   pmatch[i].rm_so == pmatch[i].rm_eo == -1 (i > 1).  */
-
-static reg_errcode_t
-set_regs (preg, mctx, nmatch, pmatch, fl_backtrack)
-     const regex_t *preg;
-     const re_match_context_t *mctx;
-     size_t nmatch;
-     regmatch_t *pmatch;
-     int fl_backtrack;
-{
-  re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
-  int idx, cur_node, real_nmatch;
-  re_node_set eps_via_nodes;
-  struct re_fail_stack_t *fs;
-  struct re_fail_stack_t fs_body = {0, 2, NULL};
-#ifdef DEBUG
-  assert (nmatch > 1);
-  assert (mctx->state_log != NULL);
-#endif
-  if (fl_backtrack)
-    {
-      fs = &fs_body;
-      fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
-    }
-  else
-    fs = NULL;
-  cur_node = dfa->init_node;
-  real_nmatch = (nmatch <= preg->re_nsub) ? nmatch : preg->re_nsub + 1;
-  re_node_set_init_empty (&eps_via_nodes);
-  for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
-    {
-      update_regs (dfa, pmatch, cur_node, idx, real_nmatch);
-      if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
-       {
-         int reg_idx;
-         if (fs)
-           {
-             for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
-               if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
-                 break;
-             if (reg_idx == nmatch)
-               {
-                 re_node_set_free (&eps_via_nodes);
-                 return free_fail_stack_return (fs);
-               }
-             cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
-                                        &eps_via_nodes);
-           }
-         else
-           {
-             re_node_set_free (&eps_via_nodes);
-             return REG_NOERROR;
-           }
-       }
-
-      /* Proceed to next node.  */
-      cur_node = proceed_next_node (preg, nmatch, pmatch, mctx, &idx, cur_node,
-                                   &eps_via_nodes, fs);
-
-      if (BE (cur_node < 0, 0))
-       {
-         if (cur_node == -2)
-           return REG_ESPACE;
-         if (fs)
-           cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
-                                      &eps_via_nodes);
-         else
-           {
-             re_node_set_free (&eps_via_nodes);
-             return REG_NOMATCH;
-           }
-       }
-    }
-  re_node_set_free (&eps_via_nodes);
-  return free_fail_stack_return (fs);
-}
-
-static reg_errcode_t
-free_fail_stack_return (fs)
-     struct re_fail_stack_t *fs;
-{
-  if (fs)
-    {
-      int fs_idx;
-      for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)
-       {
-         re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);
-         re_free (fs->stack[fs_idx].regs);
-       }
-      re_free (fs->stack);
-    }
-  return REG_NOERROR;
-}
-
-static void
-update_regs (dfa, pmatch, cur_node, cur_idx, nmatch)
-     re_dfa_t *dfa;
-     regmatch_t *pmatch;
-     int cur_node, cur_idx, nmatch;
-{
-  int type = dfa->nodes[cur_node].type;
-  int reg_num;
-  if (type != OP_OPEN_SUBEXP && type != OP_CLOSE_SUBEXP)
-    return;
-  reg_num = dfa->nodes[cur_node].opr.idx + 1;
-  if (reg_num >= nmatch)
-    return;
-  if (type == OP_OPEN_SUBEXP)
-    {
-      /* We are at the first node of this sub expression.  */
-      pmatch[reg_num].rm_so = cur_idx;
-      pmatch[reg_num].rm_eo = -1;
-    }
-  else if (type == OP_CLOSE_SUBEXP)
-    /* We are at the first node of this sub expression.  */
-    pmatch[reg_num].rm_eo = cur_idx;
-}
-
-#define NUMBER_OF_STATE 1
-
-/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0
-   and sift the nodes in each states according to the following rules.
-   Updated state_log will be wrote to STATE_LOG.
-
-   Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...
-     1. When STR_IDX == MATCH_LAST(the last index in the state_log):
-       If `a' isn't the LAST_NODE and `a' can't epsilon transit to
-       the LAST_NODE, we throw away the node `a'.
-     2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts
-       string `s' and transit to `b':
-       i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
-          away the node `a'.
-       ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
-           throwed away, we throw away the node `a'.
-     3. When 0 <= STR_IDX < n and 'a' epsilon transit to 'b':
-       i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
-          node `a'.
-       ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is throwed away,
-           we throw away the node `a'.  */
-
-#define STATE_NODE_CONTAINS(state,node) \
-  ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
-
-static reg_errcode_t
-sift_states_backward (preg, mctx, sctx)
-     const regex_t *preg;
-     re_match_context_t *mctx;
-     re_sift_context_t *sctx;
-{
-  reg_errcode_t err;
-  re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
-  int null_cnt = 0;
-  int str_idx = sctx->last_str_idx;
-  re_node_set cur_dest;
-  re_node_set *cur_src; /* Points the state_log[str_idx]->nodes  */
-
-#ifdef DEBUG
-  assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
-#endif
-  cur_src = &mctx->state_log[str_idx]->nodes;
-
-  /* Build sifted state_log[str_idx].  It has the nodes which can epsilon
-     transit to the last_node and the last_node itself.  */
-  err = re_node_set_init_1 (&cur_dest, sctx->last_node);
-  if (BE (err != REG_NOERROR, 0))
-    return err;
-  err = update_cur_sifted_state (preg, mctx, sctx, str_idx, &cur_dest);
-  if (BE (err != REG_NOERROR, 0))
-    goto free_return;
-
-  /* Then check each states in the state_log.  */
-  while (str_idx > 0)
-    {
-      int i, ret;
-      /* Update counters.  */
-      null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;
-      if (null_cnt > mctx->max_mb_elem_len)
-       {
-         memset (sctx->sifted_states, '\0',
-                 sizeof (re_dfastate_t *) * str_idx);
-         re_node_set_free (&cur_dest);
-         return REG_NOERROR;
-       }
-      re_node_set_empty (&cur_dest);
-      --str_idx;
-      cur_src = ((mctx->state_log[str_idx] == NULL) ? &empty_set
-                : &mctx->state_log[str_idx]->nodes);
-
-      /* Then build the next sifted state.
-        We build the next sifted state on `cur_dest', and update
-        `sifted_states[str_idx]' with `cur_dest'.
-        Note:
-        `cur_dest' is the sifted state from `state_log[str_idx + 1]'.
-        `cur_src' points the node_set of the old `state_log[str_idx]'.  */
-      for (i = 0; i < cur_src->nelem; i++)
-       {
-         int prev_node = cur_src->elems[i];
-         int naccepted = 0;
-         re_token_type_t type = dfa->nodes[prev_node].type;
-
-         if (IS_EPSILON_NODE(type))
-           continue;
-#ifdef RE_ENABLE_I18N
-         /* If the node may accept `multi byte'.  */
-         if (ACCEPT_MB_NODE (type))
-           naccepted = sift_states_iter_mb (preg, mctx, sctx, prev_node,
-                                            str_idx, sctx->last_str_idx);
-
-#endif /* RE_ENABLE_I18N */
-         /* We don't check backreferences here.
-            See update_cur_sifted_state().  */
-
-         if (!naccepted
-             && check_node_accept (preg, dfa->nodes + prev_node, mctx,
-                                   str_idx)
-             && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],
-                                     dfa->nexts[prev_node]))
-           naccepted = 1;
-
-         if (naccepted == 0)
-           continue;
-
-         if (sctx->limits.nelem)
-           {
-             int to_idx = str_idx + naccepted;
-             if (check_dst_limits (dfa, &sctx->limits, mctx,
-                                   dfa->nexts[prev_node], to_idx,
-                                   prev_node, str_idx))
-               continue;
-           }
-         ret = re_node_set_insert (&cur_dest, prev_node);
-         if (BE (ret == -1, 0))
-           {
-             err = REG_ESPACE;
-             goto free_return;
-           }
-       }
-
-      /* Add all the nodes which satisfy the following conditions:
-        - It can epsilon transit to a node in CUR_DEST.
-        - It is in CUR_SRC.
-        And update state_log.  */
-      err = update_cur_sifted_state (preg, mctx, sctx, str_idx, &cur_dest);
-      if (BE (err != REG_NOERROR, 0))
-       goto free_return;
-    }
-  err = REG_NOERROR;
- free_return:
-  re_node_set_free (&cur_dest);
-  return err;
-}
-
-/* Helper functions.  */
-
-static inline reg_errcode_t
-clean_state_log_if_need (mctx, next_state_log_idx)
-    re_match_context_t *mctx;
-    int next_state_log_idx;
-{
-  int top = mctx->state_log_top;
-
-  if (next_state_log_idx >= mctx->input->bufs_len
-      || (next_state_log_idx >= mctx->input->valid_len
-         && mctx->input->valid_len < mctx->input->len))
-    {
-      reg_errcode_t err;
-      err = extend_buffers (mctx);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-    }
-
-  if (top < next_state_log_idx)
-    {
-      memset (mctx->state_log + top + 1, '\0',
-             sizeof (re_dfastate_t *) * (next_state_log_idx - top));
-      mctx->state_log_top = next_state_log_idx;
-    }
-  return REG_NOERROR;
-}
-
-static reg_errcode_t
-merge_state_array (dfa, dst, src, num)
-     re_dfa_t *dfa;
-     re_dfastate_t **dst;
-     re_dfastate_t **src;
-     int num;
-{
-  int st_idx;
-  reg_errcode_t err;
-  for (st_idx = 0; st_idx < num; ++st_idx)
-    {
-      if (dst[st_idx] == NULL)
-       dst[st_idx] = src[st_idx];
-      else if (src[st_idx] != NULL)
-       {
-         re_node_set merged_set;
-         err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,
-                                       &src[st_idx]->nodes);
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-         dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);
-         re_node_set_free (&merged_set);
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-       }
-    }
-  return REG_NOERROR;
-}
-
-static reg_errcode_t
-update_cur_sifted_state (preg, mctx, sctx, str_idx, dest_nodes)
-     const regex_t *preg;
-     re_match_context_t *mctx;
-     re_sift_context_t *sctx;
-     int str_idx;
-     re_node_set *dest_nodes;
-{
-  reg_errcode_t err;
-  re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
-  const re_node_set *candidates;
-  candidates = ((mctx->state_log[str_idx] == NULL) ? &empty_set
-               : &mctx->state_log[str_idx]->nodes);
-
-  /* At first, add the nodes which can epsilon transit to a node in
-     DEST_NODE.  */
-  if (dest_nodes->nelem)
-    {
-      err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-    }
-
-  /* Then, check the limitations in the current sift_context.  */
-  if (dest_nodes->nelem && sctx->limits.nelem)
-    {
-      err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,
-                                mctx->bkref_ents, str_idx);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-    }
-
-  /* Update state_log.  */
-  sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
-  if (BE (sctx->sifted_states[str_idx] == NULL && err != REG_NOERROR, 0))
-    return err;
-
-  if ((mctx->state_log[str_idx] != NULL
-       && mctx->state_log[str_idx]->has_backref))
-    {
-      err = sift_states_bkref (preg, mctx, sctx, str_idx, dest_nodes);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-    }
-  return REG_NOERROR;
-}
-
-static reg_errcode_t
-add_epsilon_src_nodes (dfa, dest_nodes, candidates)
-     re_dfa_t *dfa;
-     re_node_set *dest_nodes;
-     const re_node_set *candidates;
-{
-  reg_errcode_t err;
-  int src_idx;
-  re_node_set src_copy;
-
-  err = re_node_set_init_copy (&src_copy, dest_nodes);
-  if (BE (err != REG_NOERROR, 0))
-    return err;
-  for (src_idx = 0; src_idx < src_copy.nelem; ++src_idx)
-    {
-      err = re_node_set_add_intersect (dest_nodes, candidates,
-                                      dfa->inveclosures
-                                      + src_copy.elems[src_idx]);
-      if (BE (err != REG_NOERROR, 0))
-       {
-         re_node_set_free (&src_copy);
-         return err;
-       }
-    }
-  re_node_set_free (&src_copy);
-  return REG_NOERROR;
-}
-
-static reg_errcode_t
-sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates)
-     re_dfa_t *dfa;
-     int node;
-     re_node_set *dest_nodes;
-     const re_node_set *candidates;
-{
-    int ecl_idx;
-    reg_errcode_t err;
-    re_node_set *inv_eclosure = dfa->inveclosures + node;
-    re_node_set except_nodes;
-    re_node_set_init_empty (&except_nodes);
-    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
-      {
-       int cur_node = inv_eclosure->elems[ecl_idx];
-       if (cur_node == node)
-         continue;
-       if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))
-         {
-           int edst1 = dfa->edests[cur_node].elems[0];
-           int edst2 = ((dfa->edests[cur_node].nelem > 1)
-                        ? dfa->edests[cur_node].elems[1] : -1);
-           if ((!re_node_set_contains (inv_eclosure, edst1)
-                && re_node_set_contains (dest_nodes, edst1))
-               || (edst2 > 0
-                   && !re_node_set_contains (inv_eclosure, edst2)
-                   && re_node_set_contains (dest_nodes, edst2)))
-             {
-               err = re_node_set_add_intersect (&except_nodes, candidates,
-                                                dfa->inveclosures + cur_node);
-               if (BE (err != REG_NOERROR, 0))
-                 {
-                   re_node_set_free (&except_nodes);
-                   return err;
-                 }
-             }
-         }
-      }
-    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
-      {
-       int cur_node = inv_eclosure->elems[ecl_idx];
-       if (!re_node_set_contains (&except_nodes, cur_node))
-         {
-           int idx = re_node_set_contains (dest_nodes, cur_node) - 1;
-           re_node_set_remove_at (dest_nodes, idx);
-         }
-      }
-    re_node_set_free (&except_nodes);
-    return REG_NOERROR;
-}
-
-static int
-check_dst_limits (dfa, limits, mctx, dst_node, dst_idx, src_node, src_idx)
-     re_dfa_t *dfa;
-     re_node_set *limits;
-     re_match_context_t *mctx;
-     int dst_node, dst_idx, src_node, src_idx;
-{
-  int lim_idx, src_pos, dst_pos;
-
-  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
-    {
-      int subexp_idx;
-      struct re_backref_cache_entry *ent;
-      ent = mctx->bkref_ents + limits->elems[lim_idx];
-      subexp_idx = dfa->nodes[ent->node].opr.idx - 1;
-
-      dst_pos = check_dst_limits_calc_pos (dfa, mctx, limits->elems[lim_idx],
-                                          dfa->eclosures + dst_node,
-                                          subexp_idx, dst_node, dst_idx);
-      src_pos = check_dst_limits_calc_pos (dfa, mctx, limits->elems[lim_idx],
-                                          dfa->eclosures + src_node,
-                                          subexp_idx, src_node, src_idx);
-
-      /* In case of:
-        <src> <dst> ( <subexp> )
-        ( <subexp> ) <src> <dst>
-        ( <subexp1> <src> <subexp2> <dst> <subexp3> )  */
-      if (src_pos == dst_pos)
-       continue; /* This is unrelated limitation.  */
-      else
-       return 1;
-    }
-  return 0;
-}
-
-static int
-check_dst_limits_calc_pos (dfa, mctx, limit, eclosures, subexp_idx, node,
-                          str_idx)
-     re_dfa_t *dfa;
-     re_match_context_t *mctx;
-     re_node_set *eclosures;
-     int limit, subexp_idx, node, str_idx;
-{
-  struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
-  int pos = (str_idx < lim->subexp_from ? -1
-            : (lim->subexp_to < str_idx ? 1 : 0));
-  if (pos == 0
-      && (str_idx == lim->subexp_from || str_idx == lim->subexp_to))
-    {
-      int node_idx;
-      for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
-       {
-         int node = eclosures->elems[node_idx];
-         re_token_type_t type= dfa->nodes[node].type;
-         if (type == OP_BACK_REF)
-           {
-             int bi = search_cur_bkref_entry (mctx, str_idx);
-             for (; bi < mctx->nbkref_ents; ++bi)
-               {
-                 struct re_backref_cache_entry *ent = mctx->bkref_ents + bi;
-                 if (ent->str_idx > str_idx)
-                   break;
-                 if (ent->node == node && ent->subexp_from == ent->subexp_to)
-                   {
-                     int cpos, dst;
-                     dst = dfa->edests[node].elems[0];
-                     cpos = check_dst_limits_calc_pos (dfa, mctx, limit,
-                                                       dfa->eclosures + dst,
-                                                       subexp_idx, dst,
-                                                       str_idx);
-                     if ((str_idx == lim->subexp_from && cpos == -1)
-                         || (str_idx == lim->subexp_to && cpos == 0))
-                       return cpos;
-                   }
-               }
-           }
-         if (type == OP_OPEN_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx
-             && str_idx == lim->subexp_from)
-           {
-             pos = -1;
-             break;
-           }
-         if (type == OP_CLOSE_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx
-             && str_idx == lim->subexp_to)
-           break;
-       }
-      if (node_idx == eclosures->nelem && str_idx == lim->subexp_to)
-       pos = 1;
-    }
-  return pos;
-}
-
-/* Check the limitations of sub expressions LIMITS, and remove the nodes
-   which are against limitations from DEST_NODES. */
-
-static reg_errcode_t
-check_subexp_limits (dfa, dest_nodes, candidates, limits, bkref_ents, str_idx)
-     re_dfa_t *dfa;
-     re_node_set *dest_nodes;
-     const re_node_set *candidates;
-     re_node_set *limits;
-     struct re_backref_cache_entry *bkref_ents;
-     int str_idx;
-{
-  reg_errcode_t err;
-  int node_idx, lim_idx;
-
-  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
-    {
-      int subexp_idx;
-      struct re_backref_cache_entry *ent;
-      ent = bkref_ents + limits->elems[lim_idx];
-
-      if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)
-       continue; /* This is unrelated limitation.  */
-
-      subexp_idx = dfa->nodes[ent->node].opr.idx - 1;
-      if (ent->subexp_to == str_idx)
-       {
-         int ops_node = -1;
-         int cls_node = -1;
-         for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
-           {
-             int node = dest_nodes->elems[node_idx];
-             re_token_type_t type= dfa->nodes[node].type;
-             if (type == OP_OPEN_SUBEXP
-                 && subexp_idx == dfa->nodes[node].opr.idx)
-               ops_node = node;
-             else if (type == OP_CLOSE_SUBEXP
-                      && subexp_idx == dfa->nodes[node].opr.idx)
-               cls_node = node;
-           }
-
-         /* Check the limitation of the open subexpression.  */
-         /* Note that (ent->subexp_to = str_idx != ent->subexp_from).  */
-         if (ops_node >= 0)
-           {
-             err = sub_epsilon_src_nodes(dfa, ops_node, dest_nodes,
-                                         candidates);
-             if (BE (err != REG_NOERROR, 0))
-               return err;
-           }
-         /* Check the limitation of the close subexpression.  */
-         for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
-           {
-             int node = dest_nodes->elems[node_idx];
-             if (!re_node_set_contains (dfa->inveclosures + node, cls_node)
-                 && !re_node_set_contains (dfa->eclosures + node, cls_node))
-               {
-                 /* It is against this limitation.
-                    Remove it form the current sifted state.  */
-                 err = sub_epsilon_src_nodes(dfa, node, dest_nodes,
-                                             candidates);
-                 if (BE (err != REG_NOERROR, 0))
-                   return err;
-                 --node_idx;
-               }
-           }
-       }
-      else /* (ent->subexp_to != str_idx)  */
-       {
-         for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
-           {
-             int node = dest_nodes->elems[node_idx];
-             re_token_type_t type= dfa->nodes[node].type;
-             if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
-               {
-                 if (subexp_idx != dfa->nodes[node].opr.idx)
-                   continue;
-                 if ((type == OP_CLOSE_SUBEXP && ent->subexp_to != str_idx)
-                     || (type == OP_OPEN_SUBEXP))
-                   {
-                     /* It is against this limitation.
-                        Remove it form the current sifted state.  */
-                     err = sub_epsilon_src_nodes(dfa, node, dest_nodes,
-                                                 candidates);
-                     if (BE (err != REG_NOERROR, 0))
-                       return err;
-                   }
-               }
-           }
-       }
-    }
-  return REG_NOERROR;
-}
-
-static reg_errcode_t
-sift_states_bkref (preg, mctx, sctx, str_idx, dest_nodes)
-     const regex_t *preg;
-     re_match_context_t *mctx;
-     re_sift_context_t *sctx;
-     int str_idx;
-     re_node_set *dest_nodes;
-{
-  reg_errcode_t err;
-  re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
-  int node_idx, node;
-  re_sift_context_t local_sctx;
-  const re_node_set *candidates;
-  candidates = ((mctx->state_log[str_idx] == NULL) ? &empty_set
-               : &mctx->state_log[str_idx]->nodes);
-  local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized.  */
-
-  for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
-    {
-      int cur_bkref_idx = re_string_cur_idx (mctx->input);
-      re_token_type_t type;
-      node = candidates->elems[node_idx];
-      type = dfa->nodes[node].type;
-      if (node == sctx->cur_bkref && str_idx == cur_bkref_idx)
-       continue;
-      /* Avoid infinite loop for the REs like "()\1+".  */
-      if (node == sctx->last_node && str_idx == sctx->last_str_idx)
-       continue;
-      if (type == OP_BACK_REF)
-       {
-         int enabled_idx = search_cur_bkref_entry (mctx, str_idx);
-         for (; enabled_idx < mctx->nbkref_ents; ++enabled_idx)
-           {
-             int disabled_idx, subexp_len, to_idx, dst_node;
-             struct re_backref_cache_entry *entry;
-             entry = mctx->bkref_ents + enabled_idx;
-             if (entry->str_idx > str_idx)
-               break;
-             if (entry->node != node)
-                 continue;
-             subexp_len = entry->subexp_to - entry->subexp_from;
-             to_idx = str_idx + subexp_len;
-             dst_node = (subexp_len ? dfa->nexts[node]
-                         : dfa->edests[node].elems[0]);
-
-             if (to_idx > sctx->last_str_idx
-                 || sctx->sifted_states[to_idx] == NULL
-                 || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx],
-                                          dst_node)
-                 || check_dst_limits (dfa, &sctx->limits, mctx, node,
-                                      str_idx, dst_node, to_idx))
-               continue;
-               {
-                 re_dfastate_t *cur_state;
-                 entry->flag = 0;
-                 for (disabled_idx = enabled_idx + 1;
-                      disabled_idx < mctx->nbkref_ents; ++disabled_idx)
-                   {
-                     struct re_backref_cache_entry *entry2;
-                     entry2 = mctx->bkref_ents + disabled_idx;
-                     if (entry2->str_idx > str_idx)
-                       break;
-                     entry2->flag = (entry2->node == node) ? 1 : entry2->flag;
-                   }
-
-                 if (local_sctx.sifted_states == NULL)
-                   {
-                     local_sctx = *sctx;
-                     err = re_node_set_init_copy (&local_sctx.limits,
-                                                  &sctx->limits);
-                     if (BE (err != REG_NOERROR, 0))
-                       goto free_return;
-                   }
-                 local_sctx.last_node = node;
-                 local_sctx.last_str_idx = str_idx;
-                 err = re_node_set_insert (&local_sctx.limits, enabled_idx);
-                 if (BE (err < 0, 0))
-                   {
-                     err = REG_ESPACE;
-                     goto free_return;
-                   }
-                 cur_state = local_sctx.sifted_states[str_idx];
-                 err = sift_states_backward (preg, mctx, &local_sctx);
-                 if (BE (err != REG_NOERROR, 0))
-                   goto free_return;
-                 if (sctx->limited_states != NULL)
-                   {
-                     err = merge_state_array (dfa, sctx->limited_states,
-                                              local_sctx.sifted_states,
-                                              str_idx + 1);
-                     if (BE (err != REG_NOERROR, 0))
-                       goto free_return;
-                   }
-                 local_sctx.sifted_states[str_idx] = cur_state;
-                 re_node_set_remove (&local_sctx.limits, enabled_idx);
-                 /* We must not use the variable entry here, since
-                    mctx->bkref_ents might be realloced.  */
-                 mctx->bkref_ents[enabled_idx].flag = 1;
-               }
-           }
-         enabled_idx = search_cur_bkref_entry (mctx, str_idx);
-         for (; enabled_idx < mctx->nbkref_ents; ++enabled_idx)
-           {
-             struct re_backref_cache_entry *entry;
-             entry = mctx->bkref_ents + enabled_idx;
-             if (entry->str_idx > str_idx)
-               break;
-             if (entry->node == node)
-               entry->flag = 0;
-           }
-       }
-    }
-  err = REG_NOERROR;
- free_return:
-  if (local_sctx.sifted_states != NULL)
-    {
-      re_node_set_free (&local_sctx.limits);
-    }
-
-  return err;
-}
-
-
-#ifdef RE_ENABLE_I18N
-static int
-sift_states_iter_mb (preg, mctx, sctx, node_idx, str_idx, max_str_idx)
-    const regex_t *preg;
-    const re_match_context_t *mctx;
-    re_sift_context_t *sctx;
-    int node_idx, str_idx, max_str_idx;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  int naccepted;
-  /* Check the node can accept `multi byte'.  */
-  naccepted = check_node_accept_bytes (preg, node_idx, mctx->input, str_idx);
-  if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
-      !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
-                           dfa->nexts[node_idx]))
-    /* The node can't accept the `multi byte', or the
-       destination was already throwed away, then the node
-       could't accept the current input `multi byte'.   */
-    naccepted = 0;
-  /* Otherwise, it is sure that the node could accept
-     `naccepted' bytes input.  */
-  return naccepted;
-}
-#endif /* RE_ENABLE_I18N */
-
-\f
-/* Functions for state transition.  */
-
-/* Return the next state to which the current state STATE will transit by
-   accepting the current input byte, and update STATE_LOG if necessary.
-   If STATE can accept a multibyte char/collating element/back reference
-   update the destination of STATE_LOG.  */
-
-static re_dfastate_t *
-transit_state (err, preg, mctx, state, fl_search)
-     reg_errcode_t *err;
-     const regex_t *preg;
-     re_match_context_t *mctx;
-     re_dfastate_t *state;
-     int fl_search;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  re_dfastate_t **trtable, *next_state;
-  unsigned char ch;
-  int cur_idx;
-
-  if (re_string_cur_idx (mctx->input) + 1 >= mctx->input->bufs_len
-      || (re_string_cur_idx (mctx->input) + 1 >= mctx->input->valid_len
-         && mctx->input->valid_len < mctx->input->len))
-    {
-      *err = extend_buffers (mctx);
-      if (BE (*err != REG_NOERROR, 0))
-       return NULL;
-    }
-
-  *err = REG_NOERROR;
-  if (state == NULL)
-    {
-      next_state = state;
-      re_string_skip_bytes (mctx->input, 1);
-    }
-  else
-    {
-#ifdef RE_ENABLE_I18N
-      /* If the current state can accept multibyte.  */
-      if (state->accept_mb)
-       {
-         *err = transit_state_mb (preg, state, mctx);
-         if (BE (*err != REG_NOERROR, 0))
-           return NULL;
-       }
-#endif /* RE_ENABLE_I18N */
-
-      /* Then decide the next state with the single byte.  */
-      if (1)
-       {
-         /* Use transition table  */
-         ch = re_string_fetch_byte (mctx->input);
-         trtable = fl_search ? state->trtable_search : state->trtable;
-         if (trtable == NULL)
-           {
-             trtable = build_trtable (preg, state, fl_search);
-             if (fl_search)
-               state->trtable_search = trtable;
-             else
-               state->trtable = trtable;
-           }
-         next_state = trtable[ch];
-       }
-      else
-       {
-         /* don't use transition table  */
-         next_state = transit_state_sb (err, preg, state, fl_search, mctx);
-         if (BE (next_state == NULL && err != REG_NOERROR, 0))
-           return NULL;
-       }
-    }
-
-  cur_idx = re_string_cur_idx (mctx->input);
-  /* Update the state_log if we need.  */
-  if (mctx->state_log != NULL)
-    {
-      if (cur_idx > mctx->state_log_top)
-       {
-         mctx->state_log[cur_idx] = next_state;
-         mctx->state_log_top = cur_idx;
-       }
-      else if (mctx->state_log[cur_idx] == 0)
-       {
-         mctx->state_log[cur_idx] = next_state;
-       }
-      else
-       {
-         re_dfastate_t *pstate;
-         unsigned int context;
-         re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
-         /* If (state_log[cur_idx] != 0), it implies that cur_idx is
-            the destination of a multibyte char/collating element/
-            back reference.  Then the next state is the union set of
-            these destinations and the results of the transition table.  */
-         pstate = mctx->state_log[cur_idx];
-         log_nodes = pstate->entrance_nodes;
-         if (next_state != NULL)
-           {
-             table_nodes = next_state->entrance_nodes;
-             *err = re_node_set_init_union (&next_nodes, table_nodes,
-                                            log_nodes);
-             if (BE (*err != REG_NOERROR, 0))
-               return NULL;
-           }
-         else
-           next_nodes = *log_nodes;
-         /* Note: We already add the nodes of the initial state,
-                  then we don't need to add them here.  */
-
-         context = re_string_context_at (mctx->input,
-                                         re_string_cur_idx (mctx->input) - 1,
-                                         mctx->eflags, preg->newline_anchor);
-         next_state = mctx->state_log[cur_idx]
-           = re_acquire_state_context (err, dfa, &next_nodes, context);
-         /* We don't need to check errors here, since the return value of
-            this function is next_state and ERR is already set.  */
-
-         if (table_nodes != NULL)
-           re_node_set_free (&next_nodes);
-       }
-    }
-
-  /* Check OP_OPEN_SUBEXP in the current state in case that we use them
-     later.  We must check them here, since the back references in the
-     next state might use them.  */
-  if (dfa->nbackref && next_state/* && fl_process_bkref */)
-    {
-      *err = check_subexp_matching_top (dfa, mctx, &next_state->nodes,
-                                       cur_idx);
-      if (BE (*err != REG_NOERROR, 0))
-       return NULL;
-    }
-
-  /* If the next state has back references.  */
-  if (next_state != NULL && next_state->has_backref)
-    {
-      *err = transit_state_bkref (preg, &next_state->nodes, mctx);
-      if (BE (*err != REG_NOERROR, 0))
-       return NULL;
-      next_state = mctx->state_log[cur_idx];
-    }
-  return next_state;
-}
-
-/* Helper functions for transit_state.  */
-
-/* From the node set CUR_NODES, pick up the nodes whose types are
-   OP_OPEN_SUBEXP and which have corresponding back references in the regular
-   expression. And register them to use them later for evaluating the
-   correspoding back references.  */
-
-static reg_errcode_t
-check_subexp_matching_top (dfa, mctx, cur_nodes, str_idx)
-     re_dfa_t *dfa;
-     re_match_context_t *mctx;
-     re_node_set *cur_nodes;
-     int str_idx;
-{
-  int node_idx;
-  reg_errcode_t err;
-
-  /* TODO: This isn't efficient.
-          Because there might be more than one nodes whose types are
-          OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
-          nodes.
-          E.g. RE: (a){2}  */
-  for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)
-    {
-      int node = cur_nodes->elems[node_idx];
-      if (dfa->nodes[node].type == OP_OPEN_SUBEXP
-         && dfa->used_bkref_map & (1 << dfa->nodes[node].opr.idx))
-       {
-         err = match_ctx_add_subtop (mctx, node, str_idx);
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-       }
-    }
-  return REG_NOERROR;
-}
-
-/* Return the next state to which the current state STATE will transit by
-   accepting the current input byte.  */
-
-static re_dfastate_t *
-transit_state_sb (err, preg, state, fl_search, mctx)
-     reg_errcode_t *err;
-     const regex_t *preg;
-     re_dfastate_t *state;
-     int fl_search;
-     re_match_context_t *mctx;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  re_node_set next_nodes;
-  re_dfastate_t *next_state;
-  int node_cnt, cur_str_idx = re_string_cur_idx (mctx->input);
-  unsigned int context;
-
-  *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
-  if (BE (*err != REG_NOERROR, 0))
-    return NULL;
-  for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
-    {
-      int cur_node = state->nodes.elems[node_cnt];
-      if (check_node_accept (preg, dfa->nodes + cur_node, mctx, cur_str_idx))
-       {
-         *err = re_node_set_merge (&next_nodes,
-                                   dfa->eclosures + dfa->nexts[cur_node]);
-         if (BE (*err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&next_nodes);
-             return NULL;
-           }
-       }
-    }
-  if (fl_search)
-    {
-#ifdef RE_ENABLE_I18N
-      int not_initial = 0;
-      if (MB_CUR_MAX > 1)
-       for (node_cnt = 0; node_cnt < next_nodes.nelem; ++node_cnt)
-         if (dfa->nodes[next_nodes.elems[node_cnt]].type == CHARACTER)
-           {
-             not_initial = dfa->nodes[next_nodes.elems[node_cnt]].mb_partial;
-             break;
-           }
-      if (!not_initial)
-#endif
-       {
-         *err = re_node_set_merge (&next_nodes,
-                                   dfa->init_state->entrance_nodes);
-         if (BE (*err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&next_nodes);
-             return NULL;
-           }
-       }
-    }
-  context = re_string_context_at (mctx->input, cur_str_idx, mctx->eflags,
-                                 preg->newline_anchor);
-  next_state = re_acquire_state_context (err, dfa, &next_nodes, context);
-  /* We don't need to check errors here, since the return value of
-     this function is next_state and ERR is already set.  */
-
-  re_node_set_free (&next_nodes);
-  re_string_skip_bytes (mctx->input, 1);
-  return next_state;
-}
-
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t
-transit_state_mb (preg, pstate, mctx)
-    const regex_t *preg;
-    re_dfastate_t *pstate;
-    re_match_context_t *mctx;
-{
-  reg_errcode_t err;
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  int i;
-
-  for (i = 0; i < pstate->nodes.nelem; ++i)
-    {
-      re_node_set dest_nodes, *new_nodes;
-      int cur_node_idx = pstate->nodes.elems[i];
-      int naccepted = 0, dest_idx;
-      unsigned int context;
-      re_dfastate_t *dest_state;
-
-      if (dfa->nodes[cur_node_idx].constraint)
-       {
-         context = re_string_context_at (mctx->input,
-                                         re_string_cur_idx (mctx->input),
-                                         mctx->eflags, preg->newline_anchor);
-         if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,
-                                          context))
-           continue;
-       }
-
-      /* How many bytes the node can accepts?  */
-      if (ACCEPT_MB_NODE (dfa->nodes[cur_node_idx].type))
-       naccepted = check_node_accept_bytes (preg, cur_node_idx, mctx->input,
-                                            re_string_cur_idx (mctx->input));
-      if (naccepted == 0)
-       continue;
-
-      /* The node can accepts `naccepted' bytes.  */
-      dest_idx = re_string_cur_idx (mctx->input) + naccepted;
-      mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
-                              : mctx->max_mb_elem_len);
-      err = clean_state_log_if_need (mctx, dest_idx);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-#ifdef DEBUG
-      assert (dfa->nexts[cur_node_idx] != -1);
-#endif
-      /* `cur_node_idx' may point the entity of the OP_CONTEXT_NODE,
-        then we use pstate->nodes.elems[i] instead.  */
-      new_nodes = dfa->eclosures + dfa->nexts[pstate->nodes.elems[i]];
-
-      dest_state = mctx->state_log[dest_idx];
-      if (dest_state == NULL)
-       dest_nodes = *new_nodes;
-      else
-       {
-         err = re_node_set_init_union (&dest_nodes,
-                                       dest_state->entrance_nodes, new_nodes);
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-       }
-      context = re_string_context_at (mctx->input, dest_idx - 1, mctx->eflags,
-                                     preg->newline_anchor);
-      mctx->state_log[dest_idx]
-       = re_acquire_state_context (&err, dfa, &dest_nodes, context);
-      if (dest_state != NULL)
-       re_node_set_free (&dest_nodes);
-      if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0))
-       return err;
-    }
-  return REG_NOERROR;
-}
-#endif /* RE_ENABLE_I18N */
-
-static reg_errcode_t
-transit_state_bkref (preg, nodes, mctx)
-    const regex_t *preg;
-    re_node_set *nodes;
-    re_match_context_t *mctx;
-{
-  reg_errcode_t err;
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  int i;
-  int cur_str_idx = re_string_cur_idx (mctx->input);
-
-  for (i = 0; i < nodes->nelem; ++i)
-    {
-      int dest_str_idx, prev_nelem, bkc_idx;
-      int node_idx = nodes->elems[i];
-      unsigned int context;
-      re_token_t *node = dfa->nodes + node_idx;
-      re_node_set *new_dest_nodes;
-
-      /* Check whether `node' is a backreference or not.  */
-      if (node->type != OP_BACK_REF)
-       continue;
-
-      if (node->constraint)
-       {
-         context = re_string_context_at (mctx->input, cur_str_idx,
-                                         mctx->eflags, preg->newline_anchor);
-         if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
-           continue;
-       }
-
-      /* `node' is a backreference.
-        Check the substring which the substring matched.  */
-      bkc_idx = mctx->nbkref_ents;
-      err = get_subexp (preg, mctx, node_idx, cur_str_idx);
-      if (BE (err != REG_NOERROR, 0))
-       goto free_return;
-
-      /* And add the epsilon closures (which is `new_dest_nodes') of
-        the backreference to appropriate state_log.  */
-#ifdef DEBUG
-      assert (dfa->nexts[node_idx] != -1);
-#endif
-      for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
-       {
-         int subexp_len;
-         re_dfastate_t *dest_state;
-         struct re_backref_cache_entry *bkref_ent;
-         bkref_ent = mctx->bkref_ents + bkc_idx;
-         if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)
-           continue;
-         subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;
-         new_dest_nodes = (subexp_len == 0
-                           ? dfa->eclosures + dfa->edests[node_idx].elems[0]
-                           : dfa->eclosures + dfa->nexts[node_idx]);
-         dest_str_idx = (cur_str_idx + bkref_ent->subexp_to
-                         - bkref_ent->subexp_from);
-         context = re_string_context_at (mctx->input, dest_str_idx - 1,
-                                         mctx->eflags, preg->newline_anchor);
-         dest_state = mctx->state_log[dest_str_idx];
-         prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
-                       : mctx->state_log[cur_str_idx]->nodes.nelem);
-         /* Add `new_dest_node' to state_log.  */
-         if (dest_state == NULL)
-           {
-             mctx->state_log[dest_str_idx]
-               = re_acquire_state_context (&err, dfa, new_dest_nodes,
-                                           context);
-             if (BE (mctx->state_log[dest_str_idx] == NULL
-                     && err != REG_NOERROR, 0))
-               goto free_return;
-           }
-         else
-           {
-             re_node_set dest_nodes;
-             err = re_node_set_init_union (&dest_nodes,
-                                           dest_state->entrance_nodes,
-                                           new_dest_nodes);
-             if (BE (err != REG_NOERROR, 0))
-               {
-                 re_node_set_free (&dest_nodes);
-                 goto free_return;
-               }
-             mctx->state_log[dest_str_idx]
-               = re_acquire_state_context (&err, dfa, &dest_nodes, context);
-             re_node_set_free (&dest_nodes);
-             if (BE (mctx->state_log[dest_str_idx] == NULL
-                     && err != REG_NOERROR, 0))
-               goto free_return;
-           }
-         /* We need to check recursively if the backreference can epsilon
-            transit.  */
-         if (subexp_len == 0
-             && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)
-           {
-             err = check_subexp_matching_top (dfa, mctx, new_dest_nodes,
-                                              cur_str_idx);
-             if (BE (err != REG_NOERROR, 0))
-               goto free_return;
-             err = transit_state_bkref (preg, new_dest_nodes, mctx);
-             if (BE (err != REG_NOERROR, 0))
-               goto free_return;
-           }
-       }
-    }
-  err = REG_NOERROR;
- free_return:
-  return err;
-}
-
-/* Enumerate all the candidates which the backreference BKREF_NODE can match
-   at BKREF_STR_IDX, and register them by match_ctx_add_entry().
-   Note that we might collect inappropriate candidates here.
-   However, the cost of checking them strictly here is too high, then we
-   delay these checking for prune_impossible_nodes().  */
-
-static reg_errcode_t
-get_subexp (preg, mctx, bkref_node, bkref_str_idx)
-     const regex_t *preg;
-     re_match_context_t *mctx;
-     int bkref_node, bkref_str_idx;
-{
-  int subexp_num, sub_top_idx;
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  char *buf = (char *) re_string_get_buffer (mctx->input);
-  /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX.  */
-  int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
-  for (; cache_idx < mctx->nbkref_ents; ++cache_idx)
-    {
-      struct re_backref_cache_entry *entry = mctx->bkref_ents + cache_idx;
-      if (entry->str_idx > bkref_str_idx)
-       break;
-      if (entry->node == bkref_node)
-       return REG_NOERROR; /* We already checked it.  */
-    }
-  subexp_num = dfa->nodes[bkref_node].opr.idx - 1;
-
-  /* For each sub expression  */
-  for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx)
-    {
-      reg_errcode_t err;
-      re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];
-      re_sub_match_last_t *sub_last;
-      int sub_last_idx, sl_str;
-      char *bkref_str;
-
-      if (dfa->nodes[sub_top->node].opr.idx != subexp_num)
-       continue; /* It isn't related.  */
-
-      sl_str = sub_top->str_idx;
-      bkref_str = buf + bkref_str_idx;
-      /* At first, check the last node of sub expressions we already
-        evaluated.  */
-      for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)
-       {
-         int sl_str_diff;
-         sub_last = sub_top->lasts[sub_last_idx];
-         sl_str_diff = sub_last->str_idx - sl_str;
-         /* The matched string by the sub expression match with the substring
-            at the back reference?  */
-         if (sl_str_diff > 0
-             && memcmp (bkref_str, buf + sl_str, sl_str_diff) != 0)
-           break; /* We don't need to search this sub expression any more.  */
-         bkref_str += sl_str_diff;
-         sl_str += sl_str_diff;
-         err = get_subexp_sub (preg, mctx, sub_top, sub_last, bkref_node,
-                               bkref_str_idx);
-         if (err == REG_NOMATCH)
-           continue;
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-       }
-      if (sub_last_idx < sub_top->nlasts)
-       continue;
-      if (sub_last_idx > 0)
-       ++sl_str;
-      /* Then, search for the other last nodes of the sub expression.  */
-      for (; sl_str <= bkref_str_idx; ++sl_str)
-       {
-         int cls_node, sl_str_off;
-         re_node_set *nodes;
-         sl_str_off = sl_str - sub_top->str_idx;
-         /* The matched string by the sub expression match with the substring
-            at the back reference?  */
-         if (sl_str_off > 0
-             && memcmp (bkref_str++, buf + sl_str - 1, 1) != 0)
-           break; /* We don't need to search this sub expression any more.  */
-         if (mctx->state_log[sl_str] == NULL)
-           continue;
-         /* Does this state have a ')' of the sub expression?  */
-         nodes = &mctx->state_log[sl_str]->nodes;
-         cls_node = find_subexp_node (dfa, nodes, subexp_num, 0);
-         if (cls_node == -1)
-           continue; /* No.  */
-         if (sub_top->path == NULL)
-           {
-             sub_top->path = calloc (sizeof (state_array_t),
-                                     sl_str - sub_top->str_idx + 1);
-             if (sub_top->path == NULL)
-               return REG_ESPACE;
-           }
-         /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node
-            in the current context?  */
-         err = check_arrival (preg, mctx, sub_top->path, sub_top->node,
-                              sub_top->str_idx, cls_node, sl_str, 0);
-         if (err == REG_NOMATCH)
-             continue;
-         if (BE (err != REG_NOERROR, 0))
-             return err;
-         sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str);
-         if (BE (sub_last == NULL, 0))
-           return REG_ESPACE;
-         err = get_subexp_sub (preg, mctx, sub_top, sub_last, bkref_node,
-                               bkref_str_idx);
-         if (err == REG_NOMATCH)
-           continue;
-       }
-    }
-  return REG_NOERROR;
-}
-
-/* Helper functions for get_subexp().  */
-
-/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR.
-   If it can arrive, register the sub expression expressed with SUB_TOP
-   and SUB_LAST.  */
-
-static reg_errcode_t
-get_subexp_sub (preg, mctx, sub_top, sub_last, bkref_node, bkref_str)
-     const regex_t *preg;
-     re_match_context_t *mctx;
-     re_sub_match_top_t *sub_top;
-     re_sub_match_last_t *sub_last;
-     int bkref_node, bkref_str;
-{
-  reg_errcode_t err;
-  int to_idx;
-  /* Can the subexpression arrive the back reference?  */
-  err = check_arrival (preg, mctx, &sub_last->path, sub_last->node,
-                      sub_last->str_idx, bkref_node, bkref_str, 1);
-  if (err != REG_NOERROR)
-    return err;
-  err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx,
-                            sub_last->str_idx);
-  if (BE (err != REG_NOERROR, 0))
-    return err;
-  to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx;
-  clean_state_log_if_need (mctx, to_idx);
-  return REG_NOERROR;
-}
-
-/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX.
-   Search '(' if FL_OPEN, or search ')' otherwise.
-   TODO: This function isn't efficient...
-        Because there might be more than one nodes whose types are
-        OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
-        nodes.
-        E.g. RE: (a){2}  */
-
-static int
-find_subexp_node (dfa, nodes, subexp_idx, fl_open)
-     re_dfa_t *dfa;
-     re_node_set *nodes;
-     int subexp_idx, fl_open;
-{
-  int cls_idx;
-  for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)
-    {
-      int cls_node = nodes->elems[cls_idx];
-      re_token_t *node = dfa->nodes + cls_node;
-      if (((fl_open && node->type == OP_OPEN_SUBEXP)
-         || (!fl_open && node->type == OP_CLOSE_SUBEXP))
-         && node->opr.idx == subexp_idx)
-       return cls_node;
-    }
-  return -1;
-}
-
-/* Check whether the node TOP_NODE at TOP_STR can arrive to the node
-   LAST_NODE at LAST_STR.  We record the path onto PATH since it will be
-   heavily reused.
-   Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise.  */
-
-static reg_errcode_t
-check_arrival (preg, mctx, path, top_node, top_str, last_node, last_str,
-              fl_open)
-     const regex_t *preg;
-     re_match_context_t *mctx;
-     state_array_t *path;
-     int top_node, top_str, last_node, last_str, fl_open;
-{
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  reg_errcode_t err;
-  int subexp_num, backup_cur_idx, str_idx, null_cnt;
-  re_dfastate_t *cur_state = NULL;
-  re_node_set *cur_nodes, next_nodes;
-  re_dfastate_t **backup_state_log;
-  unsigned int context;
-
-  subexp_num = dfa->nodes[top_node].opr.idx;
-  /* Extend the buffer if we need.  */
-  if (path->alloc < last_str + mctx->max_mb_elem_len + 1)
-    {
-      re_dfastate_t **new_array;
-      int old_alloc = path->alloc;
-      path->alloc += last_str + mctx->max_mb_elem_len + 1;
-      new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);
-      if (new_array == NULL)
-       return REG_ESPACE;
-      path->array = new_array;
-      memset (new_array + old_alloc, '\0',
-             sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
-    }
-
-  str_idx = path->next_idx == 0 ? top_str : path->next_idx;
-
-  /* Temporary modify MCTX.  */
-  backup_state_log = mctx->state_log;
-  backup_cur_idx = mctx->input->cur_idx;
-  mctx->state_log = path->array;
-  mctx->input->cur_idx = str_idx;
-
-  /* Setup initial node set.  */
-  context = re_string_context_at (mctx->input, str_idx - 1, mctx->eflags,
-                                 preg->newline_anchor);
-  if (str_idx == top_str)
-    {
-      err = re_node_set_init_1 (&next_nodes, top_node);
-      if (BE (err != REG_NOERROR, 0))
-       return err;
-      err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, fl_open);
-      if (BE (err != REG_NOERROR, 0))
-       {
-         re_node_set_free (&next_nodes);
-         return err;
-       }
-    }
-  else
-    {
-      cur_state = mctx->state_log[str_idx];
-      if (cur_state && cur_state->has_backref)
-       {
-         err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);
-         if (BE ( err != REG_NOERROR, 0))
-           return err;
-       }
-      else
-       re_node_set_init_empty (&next_nodes);
-    }
-  if (str_idx == top_str || (cur_state && cur_state->has_backref))
-    {
-      if (next_nodes.nelem)
-       {
-         err = expand_bkref_cache (preg, mctx, &next_nodes, str_idx, last_str,
-                                   subexp_num, fl_open);
-         if (BE ( err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&next_nodes);
-             return err;
-           }
-       }
-      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
-      if (BE (cur_state == NULL && err != REG_NOERROR, 0))
-       {
-         re_node_set_free (&next_nodes);
-         return err;
-       }
-      mctx->state_log[str_idx] = cur_state;
-    }
-
-  for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)
-    {
-      re_node_set_empty (&next_nodes);
-      if (mctx->state_log[str_idx + 1])
-       {
-         err = re_node_set_merge (&next_nodes,
-                                  &mctx->state_log[str_idx + 1]->nodes);
-         if (BE (err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&next_nodes);
-             return err;
-           }
-       }
-      if (cur_state)
-       {
-         err = check_arrival_add_next_nodes(preg, dfa, mctx, str_idx,
-                                            &cur_state->nodes, &next_nodes);
-         if (BE (err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&next_nodes);
-             return err;
-           }
-       }
-      ++str_idx;
-      if (next_nodes.nelem)
-       {
-         err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num,
-                                         fl_open);
-         if (BE (err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&next_nodes);
-             return err;
-           }
-         err = expand_bkref_cache (preg, mctx, &next_nodes, str_idx, last_str,
-                                   subexp_num, fl_open);
-         if (BE ( err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&next_nodes);
-             return err;
-           }
-       }
-      context = re_string_context_at (mctx->input, str_idx - 1, mctx->eflags,
-                                     preg->newline_anchor);
-      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
-      if (BE (cur_state == NULL && err != REG_NOERROR, 0))
-       {
-         re_node_set_free (&next_nodes);
-         return err;
-       }
-      mctx->state_log[str_idx] = cur_state;
-      null_cnt = cur_state == NULL ? null_cnt + 1 : 0;
-    }
-  re_node_set_free (&next_nodes);
-  cur_nodes = (mctx->state_log[last_str] == NULL ? NULL
-              : &mctx->state_log[last_str]->nodes);
-  path->next_idx = str_idx;
-
-  /* Fix MCTX.  */
-  mctx->state_log = backup_state_log;
-  mctx->input->cur_idx = backup_cur_idx;
-
-  if (cur_nodes == NULL)
-    return REG_NOMATCH;
-  /* Then check the current node set has the node LAST_NODE.  */
-  return (re_node_set_contains (cur_nodes, last_node)
-         || re_node_set_contains (cur_nodes, last_node) ? REG_NOERROR
-         : REG_NOMATCH);
-}
-
-/* Helper functions for check_arrival.  */
-
-/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them
-   to NEXT_NODES.
-   TODO: This function is similar to the functions transit_state*(),
-        however this function has many additional works.
-        Can't we unify them?  */
-
-static reg_errcode_t
-check_arrival_add_next_nodes (preg, dfa, mctx, str_idx, cur_nodes, next_nodes)
-     const regex_t *preg;
-     re_dfa_t *dfa;
-     re_match_context_t *mctx;
-     int str_idx;
-     re_node_set *cur_nodes, *next_nodes;
-{
-  int cur_idx;
-  reg_errcode_t err;
-  re_node_set union_set;
-  re_node_set_init_empty (&union_set);
-  for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
-    {
-      int naccepted = 0;
-      int cur_node = cur_nodes->elems[cur_idx];
-      re_token_type_t type = dfa->nodes[cur_node].type;
-      if (IS_EPSILON_NODE(type))
-       continue;
-#ifdef RE_ENABLE_I18N
-      /* If the node may accept `multi byte'.  */
-      if (ACCEPT_MB_NODE (type))
-       {
-         naccepted = check_node_accept_bytes (preg, cur_node, mctx->input,
-                                              str_idx);
-         if (naccepted > 1)
-           {
-             re_dfastate_t *dest_state;
-             int next_node = dfa->nexts[cur_node];
-             int next_idx = str_idx + naccepted;
-             dest_state = mctx->state_log[next_idx];
-             re_node_set_empty (&union_set);
-             if (dest_state)
-               {
-                 err = re_node_set_merge (&union_set, &dest_state->nodes);
-                 if (BE (err != REG_NOERROR, 0))
-                   {
-                     re_node_set_free (&union_set);
-                     return err;
-                   }
-                 err = re_node_set_insert (&union_set, next_node);
-                 if (BE (err < 0, 0))
-                   {
-                     re_node_set_free (&union_set);
-                     return REG_ESPACE;
-                   }
-               }
-             else
-               {
-                 err = re_node_set_insert (&union_set, next_node);
-                 if (BE (err < 0, 0))
-                   {
-                     re_node_set_free (&union_set);
-                     return REG_ESPACE;
-                   }
-               }
-             mctx->state_log[next_idx] = re_acquire_state (&err, dfa,
-                                                           &union_set);
-             if (BE (mctx->state_log[next_idx] == NULL
-                     && err != REG_NOERROR, 0))
-               {
-                 re_node_set_free (&union_set);
-                 return err;
-               }
-           }
-       }
-#endif /* RE_ENABLE_I18N */
-      if (naccepted
-         || check_node_accept (preg, dfa->nodes + cur_node, mctx,
-                               str_idx))
-       {
-         err = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
-         if (BE (err < 0, 0))
-           {
-             re_node_set_free (&union_set);
-             return REG_ESPACE;
-           }
-       }
-    }
-  re_node_set_free (&union_set);
-  return REG_NOERROR;
-}
-
-/* For all the nodes in CUR_NODES, add the epsilon closures of them to
-   CUR_NODES, however exclude the nodes which are:
-    - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN.
-    - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN.
-*/
-
-static reg_errcode_t
-check_arrival_expand_ecl (dfa, cur_nodes, ex_subexp, fl_open)
-     re_dfa_t *dfa;
-     re_node_set *cur_nodes;
-     int ex_subexp, fl_open;
-{
-  reg_errcode_t err;
-  int idx, outside_node;
-  re_node_set new_nodes;
-#ifdef DEBUG
-  assert (cur_nodes->nelem);
-#endif
-  err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
-  if (BE (err != REG_NOERROR, 0))
-    return err;
-  /* Create a new node set NEW_NODES with the nodes which are epsilon
-     closures of the node in CUR_NODES.  */
-
-  for (idx = 0; idx < cur_nodes->nelem; ++idx)
-    {
-      int cur_node = cur_nodes->elems[idx];
-      re_node_set *eclosure = dfa->eclosures + cur_node;
-      outside_node = find_subexp_node (dfa, eclosure, ex_subexp, fl_open);
-      if (outside_node == -1)
-       {
-         /* There are no problematic nodes, just merge them.  */
-         err = re_node_set_merge (&new_nodes, eclosure);
-         if (BE (err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&new_nodes);
-             return err;
-           }
-       }
-      else
-       {
-         /* There are problematic nodes, re-calculate incrementally.  */
-         err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,
-                                             ex_subexp, fl_open);
-         if (BE (err != REG_NOERROR, 0))
-           {
-             re_node_set_free (&new_nodes);
-             return err;
-           }
-       }
-    }
-  re_node_set_free (cur_nodes);
-  *cur_nodes = new_nodes;
-  return REG_NOERROR;
-}
-
-/* Helper function for check_arrival_expand_ecl.
-   Check incrementally the epsilon closure of TARGET, and if it isn't
-   problematic append it to DST_NODES.  */
-
-static reg_errcode_t
-check_arrival_expand_ecl_sub (dfa, dst_nodes, target, ex_subexp, fl_open)
-     re_dfa_t *dfa;
-     int target, ex_subexp, fl_open;
-     re_node_set *dst_nodes;
-{
-  int cur_node, type;
-  for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
-    {
-      int err;
-      type = dfa->nodes[cur_node].type;
-
-      if (((type == OP_OPEN_SUBEXP && fl_open)
-          || (type == OP_CLOSE_SUBEXP && !fl_open))
-         && dfa->nodes[cur_node].opr.idx == ex_subexp)
-       {
-         if (!fl_open)
-           {
-             err = re_node_set_insert (dst_nodes, cur_node);
-             if (BE (err == -1, 0))
-               return REG_ESPACE;
-           }
-         break;
-       }
-      err = re_node_set_insert (dst_nodes, cur_node);
-      if (BE (err == -1, 0))
-       return REG_ESPACE;
-      if (dfa->edests[cur_node].nelem == 0)
-       break;
-      if (dfa->edests[cur_node].nelem == 2)
-       {
-         err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
-                                             dfa->edests[cur_node].elems[1],
-                                             ex_subexp, fl_open);
-         if (BE (err != REG_NOERROR, 0))
-           return err;
-       }
-      cur_node = dfa->edests[cur_node].elems[0];
-    }
-  return REG_NOERROR;
-}
-
-
-/* For all the back references in the current state, calculate the
-   destination of the back references by the appropriate entry
-   in MCTX->BKREF_ENTS.  */
-
-static reg_errcode_t
-expand_bkref_cache (preg, mctx, cur_nodes, cur_str, last_str, subexp_num,
-                   fl_open)
-     const regex_t *preg;
-     re_match_context_t *mctx;
-     int cur_str, last_str, subexp_num, fl_open;
-     re_node_set *cur_nodes;
-{
-  reg_errcode_t err;
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  int cache_idx, cache_idx_start;
-  /* The current state.  */
-
-  cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
-  for (cache_idx = cache_idx_start; cache_idx < mctx->nbkref_ents; ++cache_idx)
-    {
-      int to_idx, next_node;
-      struct re_backref_cache_entry *ent = mctx->bkref_ents + cache_idx;
-      if (ent->str_idx > cur_str)
-       break;
-      /* Is this entry ENT is appropriate?  */
-      if (!re_node_set_contains (cur_nodes, ent->node))
-       continue; /* No.  */
-
-      to_idx = cur_str + ent->subexp_to - ent->subexp_from;
-      /* Calculate the destination of the back reference, and append it
-        to MCTX->STATE_LOG.  */
-      if (to_idx == cur_str)
-       {
-         /* The backreference did epsilon transit, we must re-check all the
-            node in the current state.  */
-         re_node_set new_dests;
-         reg_errcode_t err2, err3;
-         next_node = dfa->edests[ent->node].elems[0];
-         if (re_node_set_contains (cur_nodes, next_node))
-           continue;
-         err = re_node_set_init_1 (&new_dests, next_node);
-         err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num,
-                                          fl_open);
-         err3 = re_node_set_merge (cur_nodes, &new_dests);
-         re_node_set_free (&new_dests);
-         if (BE (err != REG_NOERROR || err2 != REG_NOERROR
-                 || err3 != REG_NOERROR, 0))
-           {
-             err = (err != REG_NOERROR ? err
-                    : (err2 != REG_NOERROR ? err2 : err3));
-             return err;
-           }
-         /* TODO: It is still inefficient...  */
-         cache_idx = cache_idx_start - 1;
-         continue;
-       }
-      else
-       {
-         re_node_set union_set;
-         next_node = dfa->nexts[ent->node];
-         if (mctx->state_log[to_idx])
-           {
-             int ret;
-             if (re_node_set_contains (&mctx->state_log[to_idx]->nodes,
-                                       next_node))
-               continue;
-             err = re_node_set_init_copy (&union_set,
-                                          &mctx->state_log[to_idx]->nodes);
-             ret = re_node_set_insert (&union_set, next_node);
-             if (BE (err != REG_NOERROR || ret < 0, 0))
-               {
-                 re_node_set_free (&union_set);
-                 err = err != REG_NOERROR ? err : REG_ESPACE;
-                 return err;
-               }
-           }
-         else
-           {
-             err = re_node_set_init_1 (&union_set, next_node);
-             if (BE (err != REG_NOERROR, 0))
-               return err;
-           }
-         mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set);
-         re_node_set_free (&union_set);
-         if (BE (mctx->state_log[to_idx] == NULL
-                 && err != REG_NOERROR, 0))
-           return err;
-       }
-    }
-  return REG_NOERROR;
-}
-
-/* Build transition table for the state.
-   Return the new table if succeeded, otherwise return NULL.  */
-
-static re_dfastate_t **
-build_trtable (preg, state, fl_search)
-    const regex_t *preg;
-    const re_dfastate_t *state;
-    int fl_search;
-{
-  reg_errcode_t err;
-  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  int i, j, k, ch;
-  int dests_node_malloced = 0, dest_states_malloced = 0;
-  int ndests; /* Number of the destination states from `state'.  */
-  re_dfastate_t **trtable;
-  re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
-  re_node_set follows, *dests_node;
-  bitset *dests_ch;
-  bitset acceptable;
-
-  /* We build DFA states which corresponds to the destination nodes
-     from `state'.  `dests_node[i]' represents the nodes which i-th
-     destination state contains, and `dests_ch[i]' represents the
-     characters which i-th destination state accepts.  */
-#ifdef _LIBC
-  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX))
-    dests_node = (re_node_set *)
-                alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX);
-  else
-#endif
-    {
-      dests_node = (re_node_set *)
-                  malloc ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX);
-      if (BE (dests_node == NULL, 0))
-       return NULL;
-      dests_node_malloced = 1;
-    }
-  dests_ch = (bitset *) (dests_node + SBC_MAX);
-
-  /* Initialize transiton table.  */
-  trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
-  if (BE (trtable == NULL, 0))
-    {
-      if (dests_node_malloced)
-       free (dests_node);
-      return NULL;
-    }
-
-  /* At first, group all nodes belonging to `state' into several
-     destinations.  */
-  ndests = group_nodes_into_DFAstates (preg, state, dests_node, dests_ch);
-  if (BE (ndests <= 0, 0))
-    {
-      if (dests_node_malloced)
-       free (dests_node);
-      /* Return NULL in case of an error, trtable otherwise.  */
-      if (ndests == 0)
-       return trtable;
-      free (trtable);
-      return NULL;
-    }
-
-  err = re_node_set_alloc (&follows, ndests + 1);
-  if (BE (err != REG_NOERROR, 0))
-    goto out_free;
-
-#ifdef _LIBC
-  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX
-                        + ndests * 3 * sizeof (re_dfastate_t *)))
-    dest_states = (re_dfastate_t **)
-                 alloca (ndests * 3 * sizeof (re_dfastate_t *));
-  else
-#endif
-    {
-      dest_states = (re_dfastate_t **)
-                   malloc (ndests * 3 * sizeof (re_dfastate_t *));
-      if (BE (dest_states == NULL, 0))
-       {
-out_free:
-         if (dest_states_malloced)
-           free (dest_states);
-         re_node_set_free (&follows);
-         for (i = 0; i < ndests; ++i)
-           re_node_set_free (dests_node + i);
-         free (trtable);
-         if (dests_node_malloced)
-           free (dests_node);
-         return NULL;
-       }
-      dest_states_malloced = 1;
-    }
-  dest_states_word = dest_states + ndests;
-  dest_states_nl = dest_states_word + ndests;
-  bitset_empty (acceptable);
-
-  /* Then build the states for all destinations.  */
-  for (i = 0; i < ndests; ++i)
-    {
-      int next_node;
-      re_node_set_empty (&follows);
-      /* Merge the follows of this destination states.  */
-      for (j = 0; j < dests_node[i].nelem; ++j)
-       {
-         next_node = dfa->nexts[dests_node[i].elems[j]];
-         if (next_node != -1)
-           {
-             err = re_node_set_merge (&follows, dfa->eclosures + next_node);
-             if (BE (err != REG_NOERROR, 0))
-               goto out_free;
-           }
-       }
-      /* If search flag is set, merge the initial state.  */
-      if (fl_search)
-       {
-#ifdef RE_ENABLE_I18N
-         int not_initial = 0;
-         for (j = 0; j < follows.nelem; ++j)
-           if (dfa->nodes[follows.elems[j]].type == CHARACTER)
-             {
-               not_initial = dfa->nodes[follows.elems[j]].mb_partial;
-               break;
-             }
-         if (!not_initial)
-#endif
-           {
-             err = re_node_set_merge (&follows,
-                                      dfa->init_state->entrance_nodes);
-             if (BE (err != REG_NOERROR, 0))
-               goto out_free;
-           }
-       }
-      dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);
-      if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0))
-       goto out_free;
-      /* If the new state has context constraint,
-        build appropriate states for these contexts.  */
-      if (dest_states[i]->has_constraint)
-       {
-         dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,
-                                                         CONTEXT_WORD);
-         if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
-           goto out_free;
-         dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
-                                                       CONTEXT_NEWLINE);
-         if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))
-           goto out_free;
-       }
-      else
-       {
-         dest_states_word[i] = dest_states[i];
-         dest_states_nl[i] = dest_states[i];
-       }
-      bitset_merge (acceptable, dests_ch[i]);
-    }
-
-  /* Update the transition table.  */
-  /* For all characters ch...:  */
-  for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
-    for (j = 0; j < UINT_BITS; ++j, ++ch)
-      if ((acceptable[i] >> j) & 1)
-       {
-         /* The current state accepts the character ch.  */
-         if (IS_WORD_CHAR (ch))
-           {
-             for (k = 0; k < ndests; ++k)
-               if ((dests_ch[k][i] >> j) & 1)
-                 {
-                   /* k-th destination accepts the word character ch.  */
-                   trtable[ch] = dest_states_word[k];
-                   /* There must be only one destination which accepts
-                      character ch.  See group_nodes_into_DFAstates.  */
-                   break;
-                 }
-           }
-         else /* not WORD_CHAR */
-           {
-             for (k = 0; k < ndests; ++k)
-               if ((dests_ch[k][i] >> j) & 1)
-                 {
-                   /* k-th destination accepts the non-word character ch.  */
-                   trtable[ch] = dest_states[k];
-                   /* There must be only one destination which accepts
-                      character ch.  See group_nodes_into_DFAstates.  */
-                   break;
-                 }
-           }
-       }
-  /* new line */
-  if (bitset_contain (acceptable, NEWLINE_CHAR))
-    {
-      /* The current state accepts newline character.  */
-      for (k = 0; k < ndests; ++k)
-       if (bitset_contain (dests_ch[k], NEWLINE_CHAR))
-         {
-           /* k-th destination accepts newline character.  */
-           trtable[NEWLINE_CHAR] = dest_states_nl[k];
-           /* There must be only one destination which accepts
-              newline.  See group_nodes_into_DFAstates.  */
-           break;
-         }
-    }
-
-  if (dest_states_malloced)
-    free (dest_states);
-
-  re_node_set_free (&follows);
-  for (i = 0; i < ndests; ++i)
-    re_node_set_free (dests_node + i);
-
-  if (dests_node_malloced)
-    free (dests_node);
-
-  return trtable;
-}
-
-/* Group all nodes belonging to STATE into several destinations.
-   Then for all destinations, set the nodes belonging to the destination
-   to DESTS_NODE[i] and set the characters accepted by the destination
-   to DEST_CH[i].  This function return the number of destinations.  */
-
-static int
-group_nodes_into_DFAstates (preg, state, dests_node, dests_ch)
-    const regex_t *preg;
-    const re_dfastate_t *state;
-    re_node_set *dests_node;
-    bitset *dests_ch;
-{
-  reg_errcode_t err;
-  const re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  int i, j, k;
-  int ndests; /* Number of the destinations from `state'.  */
-  bitset accepts; /* Characters a node can accept.  */
-  const re_node_set *cur_nodes = &state->nodes;
-  bitset_empty (accepts);
-  ndests = 0;
-
-  /* For all the nodes belonging to `state',  */
-  for (i = 0; i < cur_nodes->nelem; ++i)
-    {
-      re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];
-      re_token_type_t type = node->type;
-      unsigned int constraint = node->constraint;
-
-      /* Enumerate all single byte character this node can accept.  */
-      if (type == CHARACTER)
-       bitset_set (accepts, node->opr.c);
-      else if (type == SIMPLE_BRACKET)
-       {
-         bitset_merge (accepts, node->opr.sbcset);
-       }
-      else if (type == OP_PERIOD)
-       {
-         bitset_set_all (accepts);
-         if (!(preg->syntax & RE_DOT_NEWLINE))
-           bitset_clear (accepts, '\n');
-         if (preg->syntax & RE_DOT_NOT_NULL)
-           bitset_clear (accepts, '\0');
-       }
-      else
-       continue;
-
-      /* Check the `accepts' and sift the characters which are not
-        match it the context.  */
-      if (constraint)
-       {
-         if (constraint & NEXT_WORD_CONSTRAINT)
-           for (j = 0; j < BITSET_UINTS; ++j)
-             accepts[j] &= dfa->word_char[j];
-         if (constraint & NEXT_NOTWORD_CONSTRAINT)
-           for (j = 0; j < BITSET_UINTS; ++j)
-             accepts[j] &= ~dfa->word_char[j];
-         if (constraint & NEXT_NEWLINE_CONSTRAINT)
-           {
-             int accepts_newline = bitset_contain (accepts, NEWLINE_CHAR);
-             bitset_empty (accepts);
-             if (accepts_newline)
-               bitset_set (accepts, NEWLINE_CHAR);
-             else
-               continue;
-           }
-       }
-
-      /* Then divide `accepts' into DFA states, or create a new
-        state.  */
-      for (j = 0; j < ndests; ++j)
-       {
-         bitset intersec; /* Intersection sets, see below.  */
-         bitset remains;
-         /* Flags, see below.  */
-         int has_intersec, not_subset, not_consumed;
-
-         /* Optimization, skip if this state doesn't accept the character.  */
-         if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))
-           continue;
-
-         /* Enumerate the intersection set of this state and `accepts'.  */
-         has_intersec = 0;
-         for (k = 0; k < BITSET_UINTS; ++k)
-           has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];
-         /* And skip if the intersection set is empty.  */
-         if (!has_intersec)
-           continue;
-
-         /* Then check if this state is a subset of `accepts'.  */
-         not_subset = not_consumed = 0;
-         for (k = 0; k < BITSET_UINTS; ++k)
-           {
-             not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k];
-             not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];
-           }
-
-         /* If this state isn't a subset of `accepts', create a
-            new group state, which has the `remains'. */
-         if (not_subset)
-           {
-             bitset_copy (dests_ch[ndests], remains);
-             bitset_copy (dests_ch[j], intersec);
-             err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]);
-             if (BE (err != REG_NOERROR, 0))
-               goto error_return;
-             ++ndests;
-           }
-
-         /* Put the position in the current group. */
-         err = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
-         if (BE (err < 0, 0))
-           goto error_return;
-
-         /* If all characters are consumed, go to next node. */
-         if (!not_consumed)
-           break;
-       }
-      /* Some characters remain, create a new group. */
-      if (j == ndests)
-       {
-         bitset_copy (dests_ch[ndests], accepts);
-         err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]);
-         if (BE (err != REG_NOERROR, 0))
-           goto error_return;
-         ++ndests;
-         bitset_empty (accepts);
-       }
-    }
-  return ndests;
- error_return:
-  for (j = 0; j < ndests; ++j)
-    re_node_set_free (dests_node + j);
-  return -1;
-}
-
-#ifdef RE_ENABLE_I18N
-/* Check how many bytes the node `dfa->nodes[node_idx]' accepts.
-   Return the number of the bytes the node accepts.
-   STR_IDX is the current index of the input string.
-
-   This function handles the nodes which can accept one character, or
-   one collating element like '.', '[a-z]', opposite to the other nodes
-   can only accept one byte.  */
-
-static int
-check_node_accept_bytes (preg, node_idx, input, str_idx)
-    const regex_t *preg;
-    int node_idx, str_idx;
-    const re_string_t *input;
-{
-  const re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-  const re_token_t *node = dfa->nodes + node_idx;
-  int elem_len = re_string_elem_size_at (input, str_idx);
-  int char_len = re_string_char_size_at (input, str_idx);
-  int i;
-# ifdef _LIBC
-  int j;
-  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-# endif /* _LIBC */
-  if (elem_len <= 1 && char_len <= 1)
-    return 0;
-  if (node->type == OP_PERIOD)
-    {
-      /* '.' accepts any one character except the following two cases.  */
-      if ((!(preg->syntax & RE_DOT_NEWLINE) &&
-          re_string_byte_at (input, str_idx) == '\n') ||
-         ((preg->syntax & RE_DOT_NOT_NULL) &&
-          re_string_byte_at (input, str_idx) == '\0'))
-       return 0;
-      return char_len;
-    }
-  else if (node->type == COMPLEX_BRACKET)
-    {
-      const re_charset_t *cset = node->opr.mbcset;
-# ifdef _LIBC
-      const unsigned char *pin = ((char *) re_string_get_buffer (input)
-                                 + str_idx);
-# endif /* _LIBC */
-      int match_len = 0;
-      wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
-                   ? re_string_wchar_at (input, str_idx) : 0);
-
-      /* match with multibyte character?  */
-      for (i = 0; i < cset->nmbchars; ++i)
-       if (wc == cset->mbchars[i])
-         {
-           match_len = char_len;
-           goto check_node_accept_bytes_match;
-         }
-      /* match with character_class?  */
-      for (i = 0; i < cset->nchar_classes; ++i)
-       {
-         wctype_t wt = cset->char_classes[i];
-         if (__iswctype (wc, wt))
-           {
-             match_len = char_len;
-             goto check_node_accept_bytes_match;
-           }
-       }
-
-# ifdef _LIBC
-      if (nrules != 0)
-       {
-         unsigned int in_collseq = 0;
-         const int32_t *table, *indirect;
-         const unsigned char *weights, *extra;
-         const char *collseqwc;
-         int32_t idx;
-         /* This #include defines a local function!  */
-#  include <locale/weight.h>
-
-         /* match with collating_symbol?  */
-         if (cset->ncoll_syms)
-           extra = (const unsigned char *)
-             _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
-         for (i = 0; i < cset->ncoll_syms; ++i)
-           {
-             const unsigned char *coll_sym = extra + cset->coll_syms[i];
-             /* Compare the length of input collating element and
-                the length of current collating element.  */
-             if (*coll_sym != elem_len)
-               continue;
-             /* Compare each bytes.  */
-             for (j = 0; j < *coll_sym; j++)
-               if (pin[j] != coll_sym[1 + j])
-                 break;
-             if (j == *coll_sym)
-               {
-                 /* Match if every bytes is equal.  */
-                 match_len = j;
-                 goto check_node_accept_bytes_match;
-               }
-           }
-
-         if (cset->nranges)
-           {
-             if (elem_len <= char_len)
-               {
-                 collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
-                 in_collseq = collseq_table_lookup (collseqwc, wc);
-               }
-             else
-               in_collseq = find_collation_sequence_value (pin, elem_len);
-           }
-         /* match with range expression?  */
-         for (i = 0; i < cset->nranges; ++i)
-           if (cset->range_starts[i] <= in_collseq
-               && in_collseq <= cset->range_ends[i])
-             {
-               match_len = elem_len;
-               goto check_node_accept_bytes_match;
-             }
-
-         /* match with equivalence_class?  */
-         if (cset->nequiv_classes)
-           {
-             const unsigned char *cp = pin;
-             table = (const int32_t *)
-               _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
-             weights = (const unsigned char *)
-               _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
-             extra = (const unsigned char *)
-               _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
-             indirect = (const int32_t *)
-               _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
-             idx = findidx (&cp);
-             if (idx > 0)
-               for (i = 0; i < cset->nequiv_classes; ++i)
-                 {
-                   int32_t equiv_class_idx = cset->equiv_classes[i];
-                   size_t weight_len = weights[idx];
-                   if (weight_len == weights[equiv_class_idx])
-                     {
-                       int cnt = 0;
-                       while (cnt <= weight_len
-                              && (weights[equiv_class_idx + 1 + cnt]
-                                  == weights[idx + 1 + cnt]))
-                         ++cnt;
-                       if (cnt > weight_len)
-                         {
-                           match_len = elem_len;
-                           goto check_node_accept_bytes_match;
-                         }
-                     }
-                 }
-           }
-       }
-      else
-# endif /* _LIBC */
-       {
-         /* match with range expression?  */
-#if __GNUC__ >= 2
-         wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
-#else
-         wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
-         cmp_buf[2] = wc;
-#endif
-         for (i = 0; i < cset->nranges; ++i)
-           {
-             cmp_buf[0] = cset->range_starts[i];
-             cmp_buf[4] = cset->range_ends[i];
-             if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
-                 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
-               {
-                 match_len = char_len;
-                 goto check_node_accept_bytes_match;
-               }
-           }
-       }
-    check_node_accept_bytes_match:
-      if (!cset->non_match)
-       return match_len;
-      else
-       {
-         if (match_len > 0)
-           return 0;
-         else
-           return (elem_len > char_len) ? elem_len : char_len;
-       }
-    }
-  return 0;
-}
-
-# ifdef _LIBC
-static unsigned int
-find_collation_sequence_value (mbs, mbs_len)
-    const unsigned char *mbs;
-    size_t mbs_len;
-{
-  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-  if (nrules == 0)
-    {
-      if (mbs_len == 1)
-       {
-         /* No valid character.  Match it as a single byte character.  */
-         const unsigned char *collseq = (const unsigned char *)
-           _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
-         return collseq[mbs[0]];
-       }
-      return UINT_MAX;
-    }
-  else
-    {
-      int32_t idx;
-      const unsigned char *extra = (const unsigned char *)
-       _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
-
-      for (idx = 0; ;)
-       {
-         int mbs_cnt, found = 0;
-         int32_t elem_mbs_len;
-         /* Skip the name of collating element name.  */
-         idx = idx + extra[idx] + 1;
-         elem_mbs_len = extra[idx++];
-         if (mbs_len == elem_mbs_len)
-           {
-             for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt)
-               if (extra[idx + mbs_cnt] != mbs[mbs_cnt])
-                 break;
-             if (mbs_cnt == elem_mbs_len)
-               /* Found the entry.  */
-               found = 1;
-           }
-         /* Skip the byte sequence of the collating element.  */
-         idx += elem_mbs_len;
-         /* Adjust for the alignment.  */
-         idx = (idx + 3) & ~3;
-         /* Skip the collation sequence value.  */
-         idx += sizeof (uint32_t);
-         /* Skip the wide char sequence of the collating element.  */
-         idx = idx + sizeof (uint32_t) * (extra[idx] + 1);
-         /* If we found the entry, return the sequence value.  */
-         if (found)
-           return *(uint32_t *) (extra + idx);
-         /* Skip the collation sequence value.  */
-         idx += sizeof (uint32_t);
-       }
-    }
-}
-# endif /* _LIBC */
-#endif /* RE_ENABLE_I18N */
-
-/* Check whether the node accepts the byte which is IDX-th
-   byte of the INPUT.  */
-
-static int
-check_node_accept (preg, node, mctx, idx)
-    const regex_t *preg;
-    const re_token_t *node;
-    const re_match_context_t *mctx;
-    int idx;
-{
-  unsigned char ch;
-  if (node->constraint)
-    {
-      /* The node has constraints.  Check whether the current context
-        satisfies the constraints.  */
-      unsigned int context = re_string_context_at (mctx->input, idx,
-                                                  mctx->eflags,
-                                                  preg->newline_anchor);
-      if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
-       return 0;
-    }
-  ch = re_string_byte_at (mctx->input, idx);
-  if (node->type == CHARACTER)
-    return node->opr.c == ch;
-  else if (node->type == SIMPLE_BRACKET)
-    return bitset_contain (node->opr.sbcset, ch);
-  else if (node->type == OP_PERIOD)
-    return !((ch == '\n' && !(preg->syntax & RE_DOT_NEWLINE))
-            || (ch == '\0' && (preg->syntax & RE_DOT_NOT_NULL)));
-  else
-    return 0;
-}
-
-/* Extend the buffers, if the buffers have run out.  */
-
-static reg_errcode_t
-extend_buffers (mctx)
-     re_match_context_t *mctx;
-{
-  reg_errcode_t ret;
-  re_string_t *pstr = mctx->input;
-
-  /* Double the lengthes of the buffers.  */
-  ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
-  if (BE (ret != REG_NOERROR, 0))
-    return ret;
-
-  if (mctx->state_log != NULL)
-    {
-      /* And double the length of state_log.  */
-      re_dfastate_t **new_array;
-      new_array = re_realloc (mctx->state_log, re_dfastate_t *,
-                             pstr->bufs_len * 2);
-      if (BE (new_array == NULL, 0))
-       return REG_ESPACE;
-      mctx->state_log = new_array;
-    }
-
-  /* Then reconstruct the buffers.  */
-  if (pstr->icase)
-    {
-#ifdef RE_ENABLE_I18N
-      if (MB_CUR_MAX > 1)
-       build_wcs_upper_buffer (pstr);
-      else
-#endif /* RE_ENABLE_I18N  */
-       build_upper_buffer (pstr);
-    }
-  else
-    {
-#ifdef RE_ENABLE_I18N
-      if (MB_CUR_MAX > 1)
-       build_wcs_buffer (pstr);
-      else
-#endif /* RE_ENABLE_I18N  */
-       {
-         if (pstr->trans != NULL)
-           re_string_translate_buffer (pstr);
-         else
-           pstr->valid_len = pstr->bufs_len;
-       }
-    }
-  return REG_NOERROR;
-}
-
-\f
-/* Functions for matching context.  */
-
-/* Initialize MCTX.  */
-
-static reg_errcode_t
-match_ctx_init (mctx, eflags, input, n)
-    re_match_context_t *mctx;
-    int eflags, n;
-    re_string_t *input;
-{
-  mctx->eflags = eflags;
-  mctx->input = input;
-  mctx->match_last = -1;
-  if (n > 0)
-    {
-      mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
-      mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);
-      if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0))
-       return REG_ESPACE;
-    }
-  else
-    mctx->bkref_ents = NULL;
-  mctx->nbkref_ents = 0;
-  mctx->abkref_ents = n;
-  mctx->max_mb_elem_len = 1;
-  mctx->nsub_tops = 0;
-  mctx->asub_tops = n;
-  return REG_NOERROR;
-}
-
-/* Clean the entries which depend on the current input in MCTX.
-   This function must be invoked when the matcher changes the start index
-   of the input, or changes the input string.  */
-
-static void
-match_ctx_clean (mctx)
-    re_match_context_t *mctx;
-{
-  match_ctx_free_subtops (mctx);
-  mctx->nsub_tops = 0;
-  mctx->nbkref_ents = 0;
-}
-
-/* Free all the memory associated with MCTX.  */
-
-static void
-match_ctx_free (mctx)
-    re_match_context_t *mctx;
-{
-  match_ctx_free_subtops (mctx);
-  re_free (mctx->sub_tops);
-  re_free (mctx->bkref_ents);
-}
-
-/* Free all the memory associated with MCTX->SUB_TOPS.  */
-
-static void
-match_ctx_free_subtops (mctx)
-     re_match_context_t *mctx;
-{
-  int st_idx;
-  for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx)
-    {
-      int sl_idx;
-      re_sub_match_top_t *top = mctx->sub_tops[st_idx];
-      for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx)
-       {
-         re_sub_match_last_t *last = top->lasts[sl_idx];
-         re_free (last->path.array);
-         re_free (last);
-       }
-      re_free (top->lasts);
-      if (top->path)
-       {
-         re_free (top->path->array);
-         re_free (top->path);
-       }
-      free (top);
-    }
-}
-
-/* Add a new backreference entry to MCTX.
-   Note that we assume that caller never call this function with duplicate
-   entry, and call with STR_IDX which isn't smaller than any existing entry.
-*/
-
-static reg_errcode_t
-match_ctx_add_entry (mctx, node, str_idx, from, to)
-     re_match_context_t *mctx;
-     int node, str_idx, from, to;
-{
-  if (mctx->nbkref_ents >= mctx->abkref_ents)
-    {
-      struct re_backref_cache_entry* new_entry;
-      new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,
-                             mctx->abkref_ents * 2);
-      if (BE (new_entry == NULL, 0))
-       {
-         re_free (mctx->bkref_ents);
-         return REG_ESPACE;
-       }
-      mctx->bkref_ents = new_entry;
-      memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
-             sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
-      mctx->abkref_ents *= 2;
-    }
-  mctx->bkref_ents[mctx->nbkref_ents].node = node;
-  mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx;
-  mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from;
-  mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to;
-  mctx->bkref_ents[mctx->nbkref_ents++].flag = 0;
-  if (mctx->max_mb_elem_len < to - from)
-    mctx->max_mb_elem_len = to - from;
-  return REG_NOERROR;
-}
-
-/* Search for the first entry which has the same str_idx.
-   Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX.  */
-
-static int
-search_cur_bkref_entry (mctx, str_idx)
-     re_match_context_t *mctx;
-     int str_idx;
-{
-  int left, right, mid;
-  right = mctx->nbkref_ents;
-  for (left = 0; left < right;)
-    {
-      mid = (left + right) / 2;
-      if (mctx->bkref_ents[mid].str_idx < str_idx)
-       left = mid + 1;
-      else
-       right = mid;
-    }
-  return left;
-}
-
-static void
-match_ctx_clear_flag (mctx)
-     re_match_context_t *mctx;
-{
-  int i;
-  for (i = 0; i < mctx->nbkref_ents; ++i)
-    {
-      mctx->bkref_ents[i].flag = 0;
-    }
-}
-
-/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches
-   at STR_IDX.  */
-
-static reg_errcode_t
-match_ctx_add_subtop (mctx, node, str_idx)
-     re_match_context_t *mctx;
-     int node, str_idx;
-{
-#ifdef DEBUG
-  assert (mctx->sub_tops != NULL);
-  assert (mctx->asub_tops > 0);
-#endif
-  if (mctx->nsub_tops == mctx->asub_tops)
-    {
-      re_sub_match_top_t **new_array;
-      mctx->asub_tops *= 2;
-      new_array = re_realloc (mctx->sub_tops, re_sub_match_top_t *,
-                             mctx->asub_tops);
-      if (BE (new_array == NULL, 0))
-       return REG_ESPACE;
-      mctx->sub_tops = new_array;
-    }
-  mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t));
-  if (mctx->sub_tops[mctx->nsub_tops] == NULL)
-    return REG_ESPACE;
-  mctx->sub_tops[mctx->nsub_tops]->node = node;
-  mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx;
-  return REG_NOERROR;
-}
-
-/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches
-   at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP.  */
-
-static re_sub_match_last_t *
-match_ctx_add_sublast (subtop, node, str_idx)
-     re_sub_match_top_t *subtop;
-     int node, str_idx;
-{
-  re_sub_match_last_t *new_entry;
-  if (subtop->nlasts == subtop->alasts)
-    {
-      re_sub_match_last_t **new_array;
-      subtop->alasts = 2 * subtop->alasts + 1;
-      new_array = re_realloc (subtop->lasts, re_sub_match_last_t *,
-                             subtop->alasts);
-      if (BE (new_array == NULL, 0))
-       return NULL;
-      subtop->lasts = new_array;
-    }
-  new_entry = calloc (1, sizeof (re_sub_match_last_t));
-  if (BE (new_entry == NULL, 0))
-    return NULL;
-  subtop->lasts[subtop->nlasts] = new_entry;
-  new_entry->node = node;
-  new_entry->str_idx = str_idx;
-  ++subtop->nlasts;
-  return new_entry;
-}
-
-static void
-sift_ctx_init (sctx, sifted_sts, limited_sts, last_node, last_str_idx,
-              check_subexp)
-    re_sift_context_t *sctx;
-    re_dfastate_t **sifted_sts, **limited_sts;
-    int last_node, last_str_idx, check_subexp;
-{
-  sctx->sifted_states = sifted_sts;
-  sctx->limited_states = limited_sts;
-  sctx->last_node = last_node;
-  sctx->last_str_idx = last_str_idx;
-  sctx->check_subexp = check_subexp;
-  sctx->cur_bkref = -1;
-  sctx->cls_subexp_idx = -1;
-  re_node_set_init_empty (&sctx->limits);
-}
index 0abca72a269f1c8ccb387e831b8b6037f5116cf0..8c50a53265785502445376e1f27bebc46a8d43ac 100644 (file)
@@ -136,6 +136,14 @@ xml_dtd_find_pentity(struct xml_context *ctx, char *name)
 
 /* Elements */
 
+struct xml_dtd_elems_table;
+
+static void
+xml_dtd_elems_init_data(struct xml_dtd_elems_table *tab UNUSED, struct xml_dtd_elem *e)
+{
+  slist_init(&e->attrs);
+}
+
 #define HASH_PREFIX(x) xml_dtd_elems_##x
 #define HASH_NODE struct xml_dtd_elem
 #define HASH_KEY_STRING name
@@ -144,6 +152,7 @@ xml_dtd_find_pentity(struct xml_context *ctx, char *name)
 #define HASH_WANT_FIND
 #define HASH_WANT_LOOKUP
 #define HASH_GIVE_ALLOC
+#define HASH_GIVE_INIT_DATA
 #define HASH_TABLE_ALLOC
 XML_HASH_GIVE_ALLOC
 #include "lib/hashtable.h"
@@ -214,6 +223,7 @@ xml_dtd_attrs_init_key(struct xml_dtd_attrs_table *tab UNUSED, struct xml_dtd_at
 {
   attr->elem = elem;
   attr->name = name;
+  slist_add_tail(&elem->attrs, &attr->n);
 }
 
 #define HASH_PREFIX(x) xml_dtd_attrs_##x
index c031d348df84c96f9664fac0c5881c519a04e9f2..e2caf98731ca59ea6a52647848b126ae44344142 100644 (file)
@@ -89,6 +89,7 @@ struct xml_dtd_elem {
   uns type;
   char *name;
   struct xml_dtd_elem_node *node;
+  slist attrs;
   void *user;                          /* User-defined */
 };
 
@@ -140,6 +141,7 @@ enum xml_dtd_attr_type {
 };
 
 struct xml_dtd_attr {
+  snode n;
   char *name;                          /* Attribute name */
   struct xml_dtd_elem *elem;           /* Owner element */
   uns type;                            /* See enum xml_dtd_attr_type */
index ef957bc6911632bb4553e63b8ca4f3cb4955255e..5581ed597cc70dce2297d770144aa33bd065e24d 100644 (file)
@@ -421,9 +421,16 @@ xml_flush_chars(struct xml_context *ctx)
   uns len = xml_end_chars(ctx, &text), rlen;
   if (len)
     {
+      if (ctx->flags & XML_NO_CHARS)
+        {
+          if ((ctx->flags & XML_REPORT_CHARS) && ctx->h_ignorable)
+            ctx->h_ignorable(ctx, text, len);
+         mp_restore(ctx->pool, &ctx->chars_state);
+         return 0;
+       }
       if ((ctx->flags & XML_REPORT_CHARS) && ctx->h_block && (rlen = xml_report_chars(ctx, &rtext)))
        ctx->h_block(ctx, rtext, rlen);
-      if (!(ctx->flags & XML_ALLOC_CHARS) && (!(ctx->flags & XML_REPORT_CHARS) || !ctx->h_chars))
+      if (!(ctx->flags & XML_ALLOC_CHARS) && !(ctx->flags & XML_REPORT_CHARS))
         {
          mp_restore(ctx->pool, &ctx->chars_state);
          return 0;
@@ -450,25 +457,51 @@ xml_append_chars(struct xml_context *ctx)
 {
   TRACE(ctx, "append_chars");
   struct fastbuf *out = &ctx->chars;
-  while (xml_get_char(ctx) != '<')
-    if (xml_last_char(ctx) == '&')
-      {
-       xml_inc(ctx);
-        xml_parse_ref(ctx);
-      }
-    else
-      bput_utf8_32(out, xml_last_char(ctx));
+  if (ctx->flags & XML_NO_CHARS)
+    while (xml_get_char(ctx) != '<')
+      if (xml_last_cat(ctx) & XML_CHAR_WHITE)
+       bput_utf8_32(out, xml_last_char(ctx));
+      else
+        {
+         xml_error(ctx, "This element must not contain character data");
+         while (xml_get_char(ctx) != '<');
+         break;
+       }
+  else
+    while (xml_get_char(ctx) != '<')
+      if (xml_last_char(ctx) == '&')
+        {
+         xml_inc(ctx);
+          xml_parse_ref(ctx);
+        }
+      else
+        bput_utf8_32(out, xml_last_char(ctx));
   xml_unget_char(ctx);
 }
 
 /*** CDATA sections ***/
 
+static void
+xml_skip_cdata(struct xml_context *ctx)
+{
+  TRACE(ctx, "skip_cdata");
+  xml_parse_seq(ctx, "CDATA[");
+  while (xml_get_char(ctx) != ']' || xml_get_char(ctx) != ']' || xml_get_char(ctx) != '>');
+  xml_dec(ctx);
+}
+
 static void
 xml_append_cdata(struct xml_context *ctx)
 {
   /* CDSect :== '<![CDATA[' (Char* - (Char* ']]>' Char*)) ']]>'
    * Already parsed: '<![' */
   TRACE(ctx, "append_cdata");
+  if (ctx->flags & XML_NO_CHARS)
+    {
+      xml_error(ctx, "This element must not contain CDATA");
+      xml_skip_cdata(ctx);
+      return;
+    }
   xml_parse_seq(ctx, "CDATA[");
   struct fastbuf *out = &ctx->chars;
   uns rlen;
@@ -493,15 +526,6 @@ xml_append_cdata(struct xml_context *ctx)
   xml_dec(ctx);
 }
 
-static void UNUSED
-xml_skip_cdata(struct xml_context *ctx)
-{
-  TRACE(ctx, "skip_cdata");
-  xml_parse_seq(ctx, "CDATA[");
-  while (xml_get_char(ctx) != ']' || xml_get_char(ctx) != ']' || xml_get_char(ctx) != '>');
-  xml_dec(ctx);
-}
-
 /*** Attribute values ***/
 
 char *
@@ -630,6 +654,18 @@ xml_attr_find(struct xml_context *ctx, struct xml_node *node, char *name)
   return xml_attrs_find(ctx->tab_attrs, node, name);
 }
 
+char *
+xml_attr_value(struct xml_context *ctx, struct xml_node *node, char *name)
+{
+  struct xml_attr *attr = xml_attrs_find(ctx->tab_attrs, node, name);
+  if (attr)
+    return attr->val;
+  if (!node->dtd)
+    return NULL;
+  struct xml_dtd_attr *dtd = xml_dtd_find_attr(ctx, node->dtd, name);
+  return dtd ? dtd->default_value : NULL;
+}
+
 void
 xml_attrs_table_init(struct xml_context *ctx)
 {
@@ -644,6 +680,18 @@ xml_attrs_table_cleanup(struct xml_context *ctx)
 
 /*** Elements ***/
 
+static uns
+xml_validate_element(struct xml_dtd_elem_node *root, struct xml_dtd_elem *elem)
+{
+  if (root->elem)
+    return elem == root->elem;
+  else
+    SLIST_FOR_EACH(struct xml_dtd_elem_node *, son, root->sons)
+      if (xml_validate_element(son, elem))
+       return 1;
+  return 0;
+}
+
 static void
 xml_push_element(struct xml_context *ctx)
 {
@@ -669,7 +717,20 @@ xml_push_element(struct xml_context *ctx)
     xml_error(ctx, "Undefined element <%s>", e->name);
   else
     {
-      // FIXME: validate regular expressions
+      struct xml_dtd_elem *dtd = e->dtd, *parent_dtd = e->parent ? e->parent->dtd : NULL;
+      if (dtd->type == XML_DTD_ELEM_MIXED)
+        ctx->flags &= ~XML_NO_CHARS;
+      else
+       ctx->flags |= XML_NO_CHARS;
+      if (parent_dtd)
+        if (parent_dtd->type == XML_DTD_ELEM_EMPTY)
+         xml_error(ctx, "Empty element must not contain children");
+        else if (parent_dtd->type != XML_DTD_ELEM_ANY)
+         {
+           // FIXME: validate regular expressions
+           if (!xml_validate_element(parent_dtd->node, dtd))
+             xml_error(ctx, "Unexpected element <%s>", e->name);
+         }
     }
   while (1)
     {
@@ -688,6 +749,19 @@ xml_push_element(struct xml_context *ctx)
       xml_unget_char(ctx);
       xml_parse_attr(ctx);
     }
+  if (e->dtd)
+    SLIST_FOR_EACH(struct xml_dtd_attr *, a, e->dtd->attrs)
+      if (a->default_mode == XML_ATTR_REQUIRED)
+        {
+         if (!xml_attrs_find(ctx->tab_attrs, e, a->name))
+           xml_error(ctx, "Missing required attribute %s in element <%s>", a->name, e->name);
+       }
+      else if (a->default_mode != XML_ATTR_IMPLIED && ctx->flags & XML_ALLOC_DEFAULT_ATTRS)
+        {
+         struct xml_attr *attr = xml_attrs_lookup(ctx->tab_attrs, e, a->name);
+         if (!attr->val)
+           attr->val = a->default_value;
+       }
   if ((ctx->flags & XML_REPORT_TAGS) && ctx->h_stag)
     ctx->h_stag(ctx);
 }
@@ -784,7 +858,11 @@ xml_parse_doctype_decl(struct xml_context *ctx)
       ctx->flags |= XML_HAS_EXTERNAL_SUBSET;
     }
   if (xml_peek_char(ctx) == '[')
-    ctx->flags |= XML_HAS_INTERNAL_SUBSET;
+    {
+      ctx->flags |= XML_HAS_INTERNAL_SUBSET;
+      xml_skip_char(ctx);
+      xml_inc(ctx);
+    }
   if (ctx->h_doctype_decl)
     ctx->h_doctype_decl(ctx);
 }
@@ -796,12 +874,19 @@ xml_parse_doctype_decl(struct xml_context *ctx)
 /* DTD: Internal subset */
 
 static void
-xml_parse_internal_subset(struct xml_context *ctx)
+xml_parse_subset(struct xml_context *ctx, uns external)
 {
-  // FIXME: comments/pi have no parent
+  // FIXME:
+  // -- comments/pi have no parent
+  // -- conditional sections in external subset
+  // -- check corectness of parameter entities
+
   /* '[' intSubset ']'
    * intSubset :== (markupdecl | DeclSep)
-   * Already parsed: ']' */
+   * Already parsed: '['
+   *
+   * extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)*
+   */
   while (1)
     {
       xml_parse_white(ctx, 0);
@@ -849,16 +934,21 @@ xml_parse_internal_subset(struct xml_context *ctx)
          goto invalid_markup;
       else if (c == '%')
        xml_parse_pe_ref(ctx);
-      else if (c == ']')
-       break;
+      else if (c == ']' && !external)
+        {
+         break;
+       }
+      else if (c == '>' && external)
+        {
+         break;
+       }
       else
        goto invalid_markup;
     }
   xml_dec(ctx);
-  xml_dec(ctx);
   return;
-invalid_markup:
-  xml_fatal(ctx, "Invalid markup in the internal subset");
+invalid_markup: ;
+  xml_fatal(ctx, "Invalid markup in the %s subset", external ? "external" : "internal");
 }
 
 /*** The State Machine ***/
@@ -933,24 +1023,37 @@ error:
                xml_unget_char(ctx);
                xml_parse_doctype_decl(ctx);
                PULL(DOCTYPE_DECL);
-               if (xml_peek_char(ctx) == '[')
-                 {
-                   xml_skip_char(ctx);
-                   xml_inc(ctx);
-                   if (ctx->flags & XML_PARSE_DTD)
-                     {
-                       xml_dtd_init(ctx);
-                       if (ctx->h_dtd_start)
-                         ctx->h_dtd_start(ctx);
-                       // FIXME: pull iface?
-                       xml_parse_internal_subset(ctx);
-                       // FIXME: external subset
-                       if (ctx->h_dtd_end)
-                         ctx->h_dtd_end(ctx);
-                     }
-                   else
-                     xml_skip_internal_subset(ctx);
-                 }
+               if (ctx->flags & XML_HAS_DTD)
+                 if (ctx->flags & XML_PARSE_DTD)
+                   {
+                     xml_dtd_init(ctx);
+                     if (ctx->h_dtd_start)
+                       ctx->h_dtd_start(ctx);
+                     if (ctx->flags & XML_HAS_INTERNAL_SUBSET)
+                       {
+                         xml_parse_subset(ctx, 0);
+                         xml_dec(ctx);
+                       }
+                     if (ctx->flags & XML_HAS_EXTERNAL_SUBSET)
+                       {
+                         struct xml_dtd_entity ent = {
+                           .system_id = ctx->system_id,
+                           .public_id = ctx->public_id,
+                         };
+                         xml_parse_white(ctx, 0);
+                         xml_parse_char(ctx, '>');
+                         xml_unget_char(ctx);
+                         ASSERT(ctx->h_resolve_entity);
+                         ctx->h_resolve_entity(ctx, &ent);
+                         ctx->flags |= XML_SRC_EXPECTED_DECL;
+                         xml_parse_subset(ctx, 1);
+                         xml_unget_char(ctx);;
+                       }
+                     if (ctx->h_dtd_end)
+                       ctx->h_dtd_end(ctx);
+                   }
+                 else if (ctx->flags & XML_HAS_INTERNAL_SUBSET)
+                   xml_skip_internal_subset(ctx);
                xml_parse_white(ctx, 0);
                xml_parse_char(ctx, '>');
                xml_dec(ctx);
@@ -1108,6 +1211,28 @@ epilog:
   ASSERT(0);
 }
 
+uns
+xml_next_state(struct xml_context *ctx, uns pull)
+{
+  uns saved = ctx->pull;
+  ctx->pull = pull;
+  uns res = xml_next(ctx);
+  ctx->pull = saved;
+  return res;
+}
+
+uns
+xml_skip_element(struct xml_context *ctx)
+{
+  ASSERT(ctx->state == XML_STATE_STAG);
+  struct xml_node *node = ctx->node;
+  uns saved = ctx->pull, res;
+  ctx->pull = XML_PULL_ETAG;
+  while ((res = xml_next(ctx)) && ctx->node != node);
+  ctx->pull = saved;
+  return res;
+}
+
 uns
 xml_parse(struct xml_context *ctx)
 {
@@ -1119,3 +1244,44 @@ xml_parse(struct xml_context *ctx)
   while (xml_next(ctx));
   return ctx->err_code;
 }
+
+char *
+xml_merge_chars(struct xml_context *ctx UNUSED, struct xml_node *node, struct mempool *pool)
+{
+  ASSERT(node->type == XML_NODE_ELEM);
+  char *p = mp_start_noalign(pool, 1);
+  XML_NODE_FOR_EACH(son, node)
+    if (son->type == XML_NODE_CHARS)
+      {
+       p = mp_spread(pool, p, son->len + 1);
+       memcpy(p, son->text, son->len);
+       p += son->len;
+      }
+  *p++ = 0;
+  return mp_end(pool, p);
+}
+
+static char *
+xml_append_dom_chars(char *p, struct mempool *pool, struct xml_node *node)
+{
+  XML_NODE_FOR_EACH(son, node)
+    if (son->type == XML_NODE_CHARS)
+      {
+       p = mp_spread(pool, p, son->len + 1);
+       memcpy(p, son->text, son->len);
+       p += son->len;
+      }
+    else if (son->type == XML_NODE_ELEM)
+      p = xml_append_dom_chars(p, pool, son);
+  return p;
+}
+
+char *
+xml_merge_dom_chars(struct xml_context *ctx UNUSED, struct xml_node *node, struct mempool *pool)
+{
+  ASSERT(node->type == XML_NODE_ELEM);
+  char *p = mp_start_noalign(pool, 1);
+  p = xml_append_dom_chars(p, pool, node);
+  *p++ = 0;
+  return mp_end(pool, p);
+}
index 657268df3f07e4a765243ad29eb042dfada0e6b4..3b06f510b41c7b9a896969a3963d9662dfac05ee 100644 (file)
@@ -80,7 +80,7 @@ xml_push_source(struct xml_context *ctx)
   src->next = ctx->src;
   src->saved_depth = ctx->depth;
   ctx->src = src;
-  ctx->flags &= ~(XML_SRC_EOF | XML_SRC_EXPECTED_DECL | XML_SRC_NEW_LINE | XML_SRC_DOCUMENT);
+  ctx->flags &= ~(XML_SRC_EOF | XML_SRC_EXPECTED_DECL | XML_SRC_DOCUMENT);
   ctx->bstop = ctx->bptr = src->buf;
   ctx->depth = 0;
   return src;
@@ -182,9 +182,9 @@ void xml_parse_decl(struct xml_context *ctx);
   struct fastbuf *fb = src->fb;                                                                \
   if (ctx->bptr == ctx->bstop)                                                         \
     ctx->bptr = ctx->bstop = src->buf;                                                 \
-  uns f = ctx->flags, c, t1 = src->refill_cat1, t2 = src->refill_cat2, row = src->row; \
+  uns c, t1 = src->refill_cat1, t2 = src->refill_cat2, row = src->row;         \
   u32 *bend = src->buf + ARRAY_SIZE(src->buf), *bstop = ctx->bstop,                    \
-      *last_0xd = (f & XML_SRC_NEW_LINE) ? bstop : bend;                               \
+      *last_0xd = src->pending_0xd ? bstop : NULL;                                     \
   do                                                                                   \
     {                                                                                  \
       c = func(fb, ##params);                                                          \
@@ -201,7 +201,7 @@ void xml_parse_decl(struct xml_context *ctx);
            last_0xd = bstop + 2;                                                       \
          else if (c != 0x2028 && last_0xd == bstop)                                    \
            {                                                                           \
-             last_0xd = bend;                                                          \
+             last_0xd = NULL;                                                          \
              continue;                                                                 \
            }                                                                           \
          xml_add_char(&bstop, 0xa), row++;                                             \
@@ -218,12 +218,12 @@ void xml_parse_decl(struct xml_context *ctx);
       else                                                                             \
         {                                                                              \
          /* EOF */                                                                     \
-          f |= XML_SRC_EOF;                                                            \
+          ctx->flags |= XML_SRC_EOF;                                                   \
           break;                                                                       \
        }                                                                               \
     }                                                                                  \
   while (bstop < bend);                                                                        \
-  ctx->flags = (last_0xd == bstop) ? f | XML_SRC_NEW_LINE : f & ~XML_SRC_NEW_LINE;     \
+  src->pending_0xd = (last_0xd == bstop);                                              \
   ctx->bstop = bstop;                                                                  \
   src->row = row;
 
index 972a339b86f0500d84b417d6139548ad821039d3..0c685d8f612f9bcb9d65b24d67f5ade388a0a6cd 100644 (file)
@@ -23,6 +23,7 @@ enum {
   WANT_IGNORE_COMMENTS,
   WANT_IGNORE_PIS,
   WANT_REPORT_BLOCKS,
+  WANT_REPORT_IGNORABLE,
   WANT_FILE_ENTITIES,
 };
 
@@ -36,7 +37,8 @@ static struct option longopts[] = {
   { "hide-errors",     0, 0, WANT_HIDE_ERRORS },
   { "ignore-comments", 0, 0, WANT_IGNORE_COMMENTS },
   { "ignore-pis",      0, 0, WANT_IGNORE_PIS },
-  { "reports-blocks",  0, 0, WANT_REPORT_BLOCKS },
+  { "report-blocks",   0, 0, WANT_REPORT_BLOCKS },
+  { "report-ignorable",        0, 0, WANT_REPORT_IGNORABLE },
   { "file-entities",   0, 0, WANT_FILE_ENTITIES },
   { NULL,              0, 0, 0 }
 };
@@ -58,6 +60,7 @@ CF_USAGE
     --ignore-comments   Ignore comments\n\
     --ignore-pis        Ignore processing instructions\n\
     --report-blocks    Report blocks or characters and CDATA sections\n\
+    --report-ignorable  Report ignorable whitespace\n\
     --file-entities     Resolve file external entities (not fully normative)\n\
 \n", stderr);
   exit(1);
@@ -71,6 +74,7 @@ static uns want_hide_errors;
 static uns want_ignore_comments;
 static uns want_ignore_pis;
 static uns want_report_blocks;
+static uns want_report_ignorable;
 static uns want_file_entities;
 
 static struct fastbuf *out;
@@ -206,6 +210,12 @@ h_cdata(struct xml_context *ctx UNUSED, char *text, uns len UNUSED)
   bprintf(out, "SAX:  cdata text='%s'\n", text);
 }
 
+static void
+h_ignorable(struct xml_context *ctx UNUSED, char *text, uns len UNUSED)
+{
+  bprintf(out, "SAX:  ignorable text='%s'\n", text);
+}
+
 static void
 h_dtd_start(struct xml_context *ctx UNUSED)
 {
@@ -257,6 +267,9 @@ main(int argc, char **argv)
        case WANT_REPORT_BLOCKS:
          want_report_blocks++;
          break;
+       case WANT_REPORT_IGNORABLE:
+         want_report_ignorable++;
+         break;
        case WANT_FILE_ENTITIES:
          want_file_entities++;
          break;
@@ -287,6 +300,8 @@ main(int argc, char **argv)
           ctx.h_block = h_block;
           ctx.h_cdata = h_cdata;
        }
+      if (want_report_ignorable)
+        ctx.h_ignorable = h_ignorable;
       ctx.h_dtd_start = h_dtd_start;
       ctx.h_dtd_end = h_dtd_end;
     }
index 74162ffef447106d921bc60b977bbc98ecddf952..aad3d43955c6353de45d4cbd4ef5d2aacc7d299d 100644 (file)
@@ -25,11 +25,11 @@ Out:        PULL: start
 Run:   ../obj/sherlock/xml/xml-test -sptd
 In:    <?xml version="1.0"?>
        <!DOCTYPE root [
-       <!ELEMENT root ANY>
+       <!ELEMENT root (#PCDATA|a)*>
        <!ENTITY % pe1 "<!ENTITY e1 'text'>">
        %pe1;
        <!ENTITY e2 '&lt;&e1;&gt;'>
-       <!ELEMENT a ANY>
+       <!ELEMENT a (#PCDATA)*>
        ]>
        <root>&e1;<a>&e2;</a></root>
 Out:   PULL: start
index 6a327ec1bd56c886e896da0a76360681bb0c4352..350fce9afd560444fdd601cca2e041afbcec88ed 100644 (file)
@@ -80,17 +80,19 @@ enum xml_flags {
   /* Other parameters */
   XML_VALIDATING =                     0x00000100,     /* Validate everything (not fully implemented!) */
   XML_PARSE_DTD =                      0x00000200,     /* Enable parsing of DTD */
+  XML_NO_CHARS =                       0x00000400,     /* The current element must not contain character data (filled automaticaly if using DTD) */
+  XML_ALLOC_DEFAULT_ATTRS =            0x00000800,     /* Allocate default attribute values so they can be found by XML_ATTR_FOR_EACH */
 
   /* Internals, do not change! */
   XML_EMPTY_ELEM_TAG =                 0x00010000,     /* The current element match EmptyElemTag */
   XML_VERSION_1_1 =                    0x00020000,     /* XML version is 1.1, otherwise 1.0 */
   XML_HAS_EXTERNAL_SUBSET =            0x00040000,     /* The document contains a reference to external DTD subset */
   XML_HAS_INTERNAL_SUBSET =            0x00080000,     /* The document contains an internal subset */
+  XML_HAS_DTD =        XML_HAS_EXTERNAL_SUBSET | XML_HAS_INTERNAL_SUBSET,
   XML_SRC_EOF =                                0x00100000,     /* EOF reached */
   XML_SRC_EXPECTED_DECL =              0x00200000,     /* Just before optional or required XMLDecl/TextDecl */
-  XML_SRC_NEW_LINE =                   0x00400000,     /* The last read character is 0xD */
-  XML_SRC_DOCUMENT =                   0x00800000,     /* The document entity */
-  XML_SRC_EXTERNAL =                   0x01000000,     /* An external entity */
+  XML_SRC_DOCUMENT =                   0x00400000,     /* The document entity */
+  XML_SRC_EXTERNAL =                   0x00800000,     /* An external entity */
 };
 
 enum xml_node_type {
@@ -150,6 +152,7 @@ struct xml_source {
   void (*refill)(struct xml_context *ctx);             /* Callback to decode source characters to the buffer */
   unsigned short *refill_in_to_x;                      /* Libcharset input table */
   uns saved_depth;                                     /* Saved ctx->depth */
+  uns pending_0xd;                                     /* The last read character is 0xD */
 };
 
 struct xml_context {
@@ -193,6 +196,7 @@ struct xml_context {
   void (*h_chars)(struct xml_context *ctx);            /* Called after some characters (only with XML_REPORT_CHARS) */
   void (*h_block)(struct xml_context *ctx, char *text, uns len);       /* Called for each continuous block of characters not reported by h_cdata() (only with XML_REPORT_CHARS) */
   void (*h_cdata)(struct xml_context *ctx, char *text, uns len);       /* Called for each CDATA section (only with XML_REPORT_CHARS) */
+  void (*h_ignorable)(struct xml_context *ctx, char *text, uns len);   /* Called for ignorable whitespace (content in tags without #PCDATA) */
   void (*h_dtd_start)(struct xml_context *ctx);                /* Called just after the DTD structure is initialized */
   void (*h_dtd_end)(struct xml_context *ctx);          /* Called after DTD subsets subsets */
   struct xml_dtd_entity *(*h_find_entity)(struct xml_context *ctx, char *name);                /* Called when needed to resolve a general entity */
@@ -230,12 +234,21 @@ uns xml_parse(struct xml_context *ctx);
 /* Parse with the PUSH interface, return XML_STATE_x (zero on EOF or fatal error) */
 uns xml_next(struct xml_context *ctx);
 
+/* Equivalent to xml_next, but with temporarily changed ctx->pull value */
+uns xml_next_state(struct xml_context *ctx, uns pull);
+
+/* May be called on XML_STATE_STAG to skip it's content; can return XML_STATE_ETAG or XML_STATE_EOF on fatal error */
+uns xml_skip_element(struct xml_context *ctx);
+
 /* Returns the current row number in the document entity */
 uns xml_row(struct xml_context *ctx);
 
 /* Finds a given attribute value in a XML_NODE_ELEM node */
 struct xml_attr *xml_attr_find(struct xml_context *ctx, struct xml_node *node, char *name);
 
+/* Similar to xml_attr_find, but it deals also with default values */
+char *xml_attr_value(struct xml_context *ctx, struct xml_node *node, char *name);
+
 /* The default value of h_find_entity(), knows &lt;, &gt;, &amp;, &apos; and &quot; */
 struct xml_dtd_entity *xml_def_find_entity(struct xml_context *ctx, char *name);
 
@@ -245,6 +258,12 @@ void xml_def_resolve_entity(struct xml_context *ctx, struct xml_dtd_entity *ent)
 /* Remove leading/trailing spaces and replaces sequences of spaces to a single space character (non-CDATA attribute normalization) */
 uns xml_normalize_white(struct xml_context *ctx, char *value);
 
+/* Merge character contents of a given element to a single string (not recursive) */
+char *xml_merge_chars(struct xml_context *ctx, struct xml_node *node, struct mempool *pool);
+
+/* Merge character contents of a given subtree to a single string */
+char *xml_merge_dom_chars(struct xml_context *ctx, struct xml_node *node, struct mempool *pool);
+
 /* Public part of error handling */
 void xml_warn(struct xml_context *ctx, const char *format, ...);
 void xml_error(struct xml_context *ctx, const char *format, ...);