Rename ISASCII to IN_CTYPE_DOMAIN.
[gnulib.git] / lib / regex.c
index 951d0c0..d4c2739 100644 (file)
 /* Extended regular expression matching and search library,
    version 0.12.
-   (Implements POSIX draft P10003.2/D11.2, except for
+   (Implements POSIX draft P1003.2/D11.2, except for some of the
    internationalization features.)
+   Copyright (C) 1993-1999, 2000 Free Software Foundation, Inc.
 
-   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
+   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 General Public License for more details.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 /* AIX requires this to be the first thing in the file. */
-#if defined (_AIX) && !defined (REGEX_MALLOC)
+#if defined _AIX && !defined REGEX_MALLOC
   #pragma alloca
 #endif
 
+#undef _GNU_SOURCE
 #define _GNU_SOURCE
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
 #endif
 
+#ifndef PARAMS
+# if defined __GNUC__ || (defined __STDC__ && __STDC__)
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif  /* GCC.  */
+#endif  /* Not PARAMS.  */
+
+#if defined STDC_HEADERS && !defined emacs
+# include <stddef.h>
+#else
 /* We need this for `regex.h', and perhaps for the Emacs include files.  */
-#include <sys/types.h>
+# include <sys/types.h>
+#endif
+
+#define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
+
+/* For platform which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+# include <wchar.h>
+# include <wctype.h>
+#endif
+
+#ifdef _LIBC
+/* We have to keep the namespace clean.  */
+# define regfree(preg) __regfree (preg)
+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
+# define regerror(errcode, preg, errbuf, errbuf_size) \
+       __regerror(errcode, preg, errbuf, errbuf_size)
+# define re_set_registers(bu, re, nu, st, en) \
+       __re_set_registers (bu, re, nu, st, en)
+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
+       __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+# define re_match(bufp, string, size, pos, regs) \
+       __re_match (bufp, string, size, pos, regs)
+# define re_search(bufp, string, size, startpos, range, regs) \
+       __re_search (bufp, string, size, startpos, range, regs)
+# define re_compile_pattern(pattern, length, bufp) \
+       __re_compile_pattern (pattern, length, bufp)
+# define re_set_syntax(syntax) __re_set_syntax (syntax)
+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
+       __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
+
+# define btowc __btowc
+
+/* We are also using some library internals.  */
+# include <locale/localeinfo.h>
+# include <locale/elem-hash.h>
+# include <langinfo.h>
+#endif
 
 /* This is for other GNU distributions with internationalized messages.  */
-#if HAVE_LIBINTL_H || defined (_LIBC)
+#if HAVE_LIBINTL_H || defined _LIBC
 # include <libintl.h>
 #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
+
 /* The `emacs' switch turns on certain matching commands
    that make sense only in Emacs. */
 #ifdef emacs
 
-#include "lisp.h"
-#include "buffer.h"
-#include "syntax.h"
+# include "lisp.h"
+# include "buffer.h"
+# include "syntax.h"
 
 #else  /* not emacs */
 
 /* If we are not linking with Emacs proper,
    we can't use the relocating allocator
    even if config.h says that we can.  */
-#undef REL_ALLOC
+# undef REL_ALLOC
 
-#if defined (STDC_HEADERS) || defined (_LIBC)
-#include <stdlib.h>
-#else
+# if defined STDC_HEADERS || defined _LIBC
+#  include <stdlib.h>
+# else
 char *malloc ();
 char *realloc ();
-#endif
+# endif
 
 /* When used in Emacs's lib-src, we need to get bzero and bcopy somehow.
    If nothing else has been done, use the method below.  */
-#ifdef INHIBIT_STRING_HEADER
-#if !(defined (HAVE_BZERO) && defined (HAVE_BCOPY))
-#if !defined (bzero) && !defined (bcopy)
-#undef INHIBIT_STRING_HEADER
-#endif
-#endif
-#endif
+# ifdef INHIBIT_STRING_HEADER
+#  if !(defined HAVE_BZERO && defined HAVE_BCOPY)
+#   if !defined bzero && !defined bcopy
+#    undef INHIBIT_STRING_HEADER
+#   endif
+#  endif
+# endif
 
 /* This is the normal way of making sure we have a bcopy and a bzero.
    This is used in most programs--a few other programs avoid this
    by defining INHIBIT_STRING_HEADER.  */
-#ifndef INHIBIT_STRING_HEADER
-#if defined (HAVE_STRING_H) || defined (STDC_HEADERS) || defined (_LIBC)
-#include <string.h>
-#ifndef bcmp
-#define bcmp(s1, s2, n)        memcmp ((s1), (s2), (n))
-#endif
-#ifndef bcopy
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#endif
-#ifndef bzero
-#define bzero(s, n)    memset ((s), 0, (n))
-#endif
-#else
-#include <strings.h>
-#endif
-#endif
+# ifndef INHIBIT_STRING_HEADER
+#  if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC
+#   include <string.h>
+#   ifndef bzero
+#    ifndef _LIBC
+#     define bzero(s, n)       (memset (s, '\0', n), (s))
+#    else
+#     define bzero(s, n)       __bzero (s, n)
+#    endif
+#   endif
+#  else
+#   include <strings.h>
+#   ifndef memcmp
+#    define memcmp(s1, s2, n)  bcmp (s1, s2, n)
+#   endif
+#   ifndef memcpy
+#    define memcpy(d, s, n)    (bcopy (s, d, n), (d))
+#   endif
+#  endif
+# endif
 
 /* Define the syntax stuff for \<, \>, etc.  */
 
 /* This must be nonzero for the wordchar and notwordchar pattern
    commands in re_match_2.  */
-#ifndef Sword
-#define Sword 1
-#endif
-
-#ifdef SWITCH_ENUM_BUG
-#define SWITCH_ENUM_CAST(x) ((int)(x))
-#else
-#define SWITCH_ENUM_CAST(x) (x)
-#endif
-
-#ifdef SYNTAX_TABLE
-
-extern char *re_syntax_table;
-
-#else /* not SYNTAX_TABLE */
-
-/* How many characters in the character set.  */
-#define CHAR_SET_SIZE 256
-
-static char re_syntax_table[CHAR_SET_SIZE];
+# ifndef Sword
+#  define Sword 1
+# endif
 
-static void
-init_syntax_once ()
-{
-   register int c;
-   static int done = 0;
+# ifdef SWITCH_ENUM_BUG
+#  define SWITCH_ENUM_CAST(x) ((int)(x))
+# else
+#  define SWITCH_ENUM_CAST(x) (x)
+# endif
 
-   if (done)
-     return;
-
-   bzero (re_syntax_table, sizeof re_syntax_table);
-
-   for (c = 'a'; c <= 'z'; c++)
-     re_syntax_table[c] = Sword;
-
-   for (c = 'A'; c <= 'Z'; c++)
-     re_syntax_table[c] = Sword;
-
-   for (c = '0'; c <= '9'; c++)
-     re_syntax_table[c] = Sword;
-
-   re_syntax_table['_'] = Sword;
-
-   done = 1;
-}
-
-#endif /* not SYNTAX_TABLE */
+#endif /* not emacs */
 
-#define SYNTAX(c) re_syntax_table[c]
+#if defined _LIBC || HAVE_LIMITS_H
+# include <limits.h>
+#endif
 
-#endif /* not emacs */
+#ifndef MB_LEN_MAX
+# define MB_LEN_MAX 1
+#endif
 \f
 /* Get the interface, including the syntax bits.  */
-#include "regex.h"
+#include <regex.h>
 
 /* isalpha etc. are used for the character classes.  */
 #include <ctype.h>
@@ -163,38 +194,46 @@ init_syntax_once ()
    STDC_HEADERS is defined, then autoconf has verified that the ctype
    macros don't need to be guarded with references to isascii. ...
    Defining isascii to 1 should let any compiler worth its salt
-   eliminate the && through constant folding."  */
+   eliminate the && through constant folding."
+   Solaris defines some of these symbols so we must undefine them first.  */
 
-#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
-#define ISASCII(c) 1
+#if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+# define IN_CTYPE_DOMAIN(c) 1
 #else
-#define ISASCII(c) isascii(c)
+# define IN_CTYPE_DOMAIN(c) isascii(c)
 #endif
 
 #ifdef isblank
-#define ISBLANK(c) (ISASCII (c) && isblank (c))
+# define ISBLANK(c) (IN_CTYPE_DOMAIN (c) && isblank (c))
 #else
-#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
 #endif
 #ifdef isgraph
-#define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isgraph (c))
 #else
-#define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+# define ISGRAPH(c) (IN_CTYPE_DOMAIN (c) && isprint (c) && !isspace (c))
 #endif
 
-#define ISPRINT(c) (ISASCII (c) && isprint (c))
-#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
-#define ISALNUM(c) (ISASCII (c) && isalnum (c))
-#define ISALPHA(c) (ISASCII (c) && isalpha (c))
-#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
-#define ISLOWER(c) (ISASCII (c) && islower (c))
-#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
-#define ISSPACE(c) (ISASCII (c) && isspace (c))
-#define ISUPPER(c) (ISASCII (c) && isupper (c))
-#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+#undef ISPRINT
+#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
+#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
+#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c))
+#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
+#define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c))
+#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
+#define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (c))
+#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
+#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
+#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c))
+
+#ifdef _tolower
+# define TOLOWER(c) _tolower(c)
+#else
+# define TOLOWER(c) tolower(c)
+#endif
 
 #ifndef NULL
-#define NULL (void *)0
+# define NULL (void *)0
 #endif
 
 /* We remove any previous definition of `SIGN_EXTEND_CHAR',
@@ -203,12 +242,49 @@ init_syntax_once ()
    (Per Bothner suggested the basic approach.)  */
 #undef SIGN_EXTEND_CHAR
 #if __STDC__
-#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+# define SIGN_EXTEND_CHAR(c) ((signed char) (c))
 #else  /* not __STDC__ */
 /* As in Harbison and Steele.  */
-#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
 #endif
 \f
+#ifndef emacs
+/* How many characters in the character set.  */
+# define CHAR_SET_SIZE 256
+
+# ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+# else /* not SYNTAX_TABLE */
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void
+init_syntax_once ()
+{
+   register int c;
+   static int done = 0;
+
+   if (done)
+     return;
+   bzero (re_syntax_table, sizeof re_syntax_table);
+
+   for (c = 0; c < CHAR_SET_SIZE; ++c)
+     if (ISALNUM (c))
+       re_syntax_table[c] = Sword;
+
+   re_syntax_table['_'] = Sword;
+
+   done = 1;
+}
+
+# endif /* not SYNTAX_TABLE */
+
+# define SYNTAX(c) re_syntax_table[(unsigned char) (c)]
+
+#endif /* emacs */
+\f
 /* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
    use `alloca' instead of `malloc'.  This is because using malloc in
    re_search* or re_match* could cause memory leaks when C-g is used in
@@ -221,76 +297,67 @@ init_syntax_once ()
 
 #ifdef REGEX_MALLOC
 
-#define REGEX_ALLOCATE malloc
-#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
-#define REGEX_FREE free
+# define REGEX_ALLOCATE malloc
+# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+# define REGEX_FREE free
 
 #else /* not REGEX_MALLOC  */
 
 /* Emacs already defines alloca, sometimes.  */
-#ifndef alloca
+# ifndef alloca
 
 /* Make alloca work the best possible way.  */
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else /* not __GNUC__ */
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#else /* not __GNUC__ or HAVE_ALLOCA_H */
-#ifndef _AIX /* Already did AIX, up at the top.  */
-#if defined (__STDC__) && __STDC__
-void *alloca ();
-#else
-char *alloca ();
-#endif
-#endif /* not _AIX */
-#endif /* not HAVE_ALLOCA_H */
-#endif /* not __GNUC__ */
+#  ifdef __GNUC__
+#   define alloca __builtin_alloca
+#  else /* not __GNUC__ */
+#   if HAVE_ALLOCA_H
+#    include <alloca.h>
+#   endif /* HAVE_ALLOCA_H */
+#  endif /* not __GNUC__ */
 
-#endif /* not alloca */
+# endif /* not alloca */
 
-#define REGEX_ALLOCATE alloca
+# define REGEX_ALLOCATE alloca
 
 /* Assumes a `char *destination' variable.  */
-#define REGEX_REALLOCATE(source, osize, nsize)                         \
+# define REGEX_REALLOCATE(source, osize, nsize)                                \
   (destination = (char *) alloca (nsize),                              \
-   bcopy (source, destination, osize),                                 \
-   destination)
+   memcpy (destination, source, osize))
 
 /* No need to do anything to free, after alloca.  */
-#define REGEX_FREE(arg) ((void)0) /* Do nothing!  But inhibit gcc warning.  */
+# define REGEX_FREE(arg) ((void)0) /* Do nothing!  But inhibit gcc warning.  */
 
 #endif /* not REGEX_MALLOC */
 
 /* Define how to allocate the failure stack.  */
 
-#if defined (REL_ALLOC) && defined (REGEX_MALLOC)
+#if defined REL_ALLOC && defined REGEX_MALLOC
 
-#define REGEX_ALLOCATE_STACK(size)                             \
+# define REGEX_ALLOCATE_STACK(size)                            \
   r_alloc (&failure_stack_ptr, (size))
-#define REGEX_REALLOCATE_STACK(source, osize, nsize)           \
+# define REGEX_REALLOCATE_STACK(source, osize, nsize)          \
   r_re_alloc (&failure_stack_ptr, (nsize))
-#define REGEX_FREE_STACK(ptr)                                  \
+# define REGEX_FREE_STACK(ptr)                                 \
   r_alloc_free (&failure_stack_ptr)
 
 #else /* not using relocating allocator */
 
-#ifdef REGEX_MALLOC
+# ifdef REGEX_MALLOC
 
-#define REGEX_ALLOCATE_STACK malloc
-#define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
-#define REGEX_FREE_STACK free
+#  define REGEX_ALLOCATE_STACK malloc
+#  define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize)
+#  define REGEX_FREE_STACK free
 
-#else /* not REGEX_MALLOC */
+# else /* not REGEX_MALLOC */
 
-#define REGEX_ALLOCATE_STACK alloca
+#  define REGEX_ALLOCATE_STACK alloca
 
-#define REGEX_REALLOCATE_STACK(source, osize, nsize)                   \
+#  define REGEX_REALLOCATE_STACK(source, osize, nsize)                 \
    REGEX_REALLOCATE (source, osize, nsize)
 /* No need to explicitly free anything.  */
-#define REGEX_FREE_STACK(arg)
+#  define REGEX_FREE_STACK(arg)
 
-#endif /* not REGEX_MALLOC */
+# endif /* not REGEX_MALLOC */
 #endif /* not using relocating allocator */
 
 
@@ -320,7 +387,12 @@ typedef char boolean;
 #define false 0
 #define true 1
 
-static int re_match_2_internal ();
+static int re_match_2_internal PARAMS ((struct re_pattern_buffer *bufp,
+                                       const char *string1, int size1,
+                                       const char *string2, int size2,
+                                       int pos,
+                                       struct re_registers *regs,
+                                       int stop));
 \f
 /* These are the command codes that appear in compiled regular
    expressions.  Some opcodes are followed by argument bytes.  A
@@ -491,6 +563,7 @@ typedef enum
   } while (0)
 
 #ifdef DEBUG
+static void extract_number _RE_ARGS ((int *dest, unsigned char *source));
 static void
 extract_number (dest, source)
     int *dest;
@@ -501,10 +574,10 @@ extract_number (dest, source)
   *dest += temp << 8;
 }
 
-#ifndef EXTRACT_MACROS /* To debug the macros.  */
-#undef EXTRACT_NUMBER
-#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
-#endif /* not EXTRACT_MACROS */
+# ifndef EXTRACT_MACROS /* To debug the macros.  */
+#  undef EXTRACT_NUMBER
+#  define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
+# endif /* not EXTRACT_MACROS */
 
 #endif /* DEBUG */
 
@@ -518,6 +591,8 @@ extract_number (dest, source)
   } while (0)
 
 #ifdef DEBUG
+static void extract_number_and_incr _RE_ARGS ((int *destination,
+                                              unsigned char **source));
 static void
 extract_number_and_incr (destination, source)
     int *destination;
@@ -527,11 +602,11 @@ extract_number_and_incr (destination, source)
   *source += 2;
 }
 
-#ifndef EXTRACT_MACROS
-#undef EXTRACT_NUMBER_AND_INCR
-#define EXTRACT_NUMBER_AND_INCR(dest, src) \
+# ifndef EXTRACT_MACROS
+#  undef EXTRACT_NUMBER_AND_INCR
+#  define EXTRACT_NUMBER_AND_INCR(dest, src) \
   extract_number_and_incr (&dest, &src)
-#endif /* not EXTRACT_MACROS */
+# endif /* not EXTRACT_MACROS */
 
 #endif /* DEBUG */
 \f
@@ -544,21 +619,21 @@ extract_number_and_incr (destination, source)
 #ifdef DEBUG
 
 /* We use standard I/O for debugging.  */
-#include <stdio.h>
+# include <stdio.h>
 
 /* It is useful to test things that ``must'' be true when debugging.  */
-#include <assert.h>
+# include <assert.h>
 
-static int debug = 0;
+static int debug;
 
-#define DEBUG_STATEMENT(e) e
-#define DEBUG_PRINT1(x) if (debug) printf (x)
-#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
-#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)                          \
+# define DEBUG_STATEMENT(e) e
+# define DEBUG_PRINT1(x) if (debug) printf (x)
+# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
+# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
+# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)                                 \
   if (debug) print_partial_compiled_pattern (s, e)
-#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)                 \
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)                        \
   if (debug) print_double_string (w, s1, sz1, s2, sz2)
 
 
@@ -602,6 +677,7 @@ print_partial_compiled_pattern (start, end)
     unsigned char *end;
 {
   int mcnt, mcnt2;
+  unsigned char *p1;
   unsigned char *p = start;
   unsigned char *pend = end;
 
@@ -614,7 +690,11 @@ print_partial_compiled_pattern (start, end)
   /* Loop over pattern commands.  */
   while (p < pend)
     {
-      printf ("%d:\t", p - start);
+#ifdef _LIBC
+      printf ("%t:\t", p - start);
+#else
+      printf ("%ld:\t", (long int) (p - start));
+#endif
 
       switch ((re_opcode_t) *p++)
        {
@@ -704,17 +784,30 @@ print_partial_compiled_pattern (start, end)
 
        case on_failure_jump:
           extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_jump to %d", p + mcnt - start);
+#ifdef _LIBC
+         printf ("/on_failure_jump to %t", p + mcnt - start);
+#else
+         printf ("/on_failure_jump to %ld", (long int) (p + mcnt - start));
+#endif
           break;
 
        case on_failure_keep_string_jump:
           extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_keep_string_jump to %d", p + mcnt - start);
+#ifdef _LIBC
+         printf ("/on_failure_keep_string_jump to %t", p + mcnt - start);
+#else
+         printf ("/on_failure_keep_string_jump to %ld",
+                 (long int) (p + mcnt - start));
+#endif
           break;
 
        case dummy_failure_jump:
           extract_number_and_incr (&mcnt, &p);
-         printf ("/dummy_failure_jump to %d", p + mcnt - start);
+#ifdef _LIBC
+         printf ("/dummy_failure_jump to %t", p + mcnt - start);
+#else
+         printf ("/dummy_failure_jump to %ld", (long int) (p + mcnt - start));
+#endif
           break;
 
        case push_dummy_failure:
@@ -723,40 +816,69 @@ print_partial_compiled_pattern (start, end)
 
         case maybe_pop_jump:
           extract_number_and_incr (&mcnt, &p);
-         printf ("/maybe_pop_jump to %d", p + mcnt - start);
+#ifdef _LIBC
+         printf ("/maybe_pop_jump to %t", p + mcnt - start);
+#else
+         printf ("/maybe_pop_jump to %ld", (long int) (p + mcnt - start));
+#endif
          break;
 
         case pop_failure_jump:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/pop_failure_jump to %d", p + mcnt - start);
+#ifdef _LIBC
+         printf ("/pop_failure_jump to %t", p + mcnt - start);
+#else
+         printf ("/pop_failure_jump to %ld", (long int) (p + mcnt - start));
+#endif
          break;
 
         case jump_past_alt:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/jump_past_alt to %d", p + mcnt - start);
+#ifdef _LIBC
+         printf ("/jump_past_alt to %t", p + mcnt - start);
+#else
+         printf ("/jump_past_alt to %ld", (long int) (p + mcnt - start));
+#endif
          break;
 
         case jump:
          extract_number_and_incr (&mcnt, &p);
-         printf ("/jump to %d", p + mcnt - start);
+#ifdef _LIBC
+         printf ("/jump to %t", p + mcnt - start);
+#else
+         printf ("/jump to %ld", (long int) (p + mcnt - start));
+#endif
          break;
 
         case succeed_n:
           extract_number_and_incr (&mcnt, &p);
+         p1 = p + mcnt;
           extract_number_and_incr (&mcnt2, &p);
-         printf ("/succeed_n to %d, %d times", p + mcnt - start, mcnt2);
+#ifdef _LIBC
+         printf ("/succeed_n to %t, %d times", p1 - start, mcnt2);
+#else
+         printf ("/succeed_n to %ld, %d times",
+                 (long int) (p1 - start), mcnt2);
+#endif
           break;
 
         case jump_n:
           extract_number_and_incr (&mcnt, &p);
+         p1 = p + mcnt;
           extract_number_and_incr (&mcnt2, &p);
-         printf ("/jump_n to %d, %d times", p + mcnt - start, mcnt2);
+         printf ("/jump_n to %d, %d times", p1 - start, mcnt2);
           break;
 
         case set_number_at:
           extract_number_and_incr (&mcnt, &p);
+         p1 = p + mcnt;
           extract_number_and_incr (&mcnt2, &p);
-         printf ("/set_number_at location %d to %d", p + mcnt - start, mcnt2);
+#ifdef _LIBC
+         printf ("/set_number_at location %t to %d", p1 - start, mcnt2);
+#else
+         printf ("/set_number_at location %ld to %d",
+                 (long int) (p1 - start), mcnt2);
+#endif
           break;
 
         case wordbound:
@@ -774,7 +896,7 @@ print_partial_compiled_pattern (start, end)
        case wordend:
          printf ("/wordend");
 
-#ifdef emacs
+# ifdef emacs
        case before_dot:
          printf ("/before_dot");
           break;
@@ -798,7 +920,7 @@ print_partial_compiled_pattern (start, end)
          mcnt = *p++;
          printf ("/%d", mcnt);
          break;
-#endif /* emacs */
+# endif /* emacs */
 
        case wordchar:
          printf ("/wordchar");
@@ -823,7 +945,11 @@ print_partial_compiled_pattern (start, end)
       putchar ('\n');
     }
 
-  printf ("%d:\tend of pattern.\n", p - start);
+#ifdef _LIBC
+  printf ("%t:\tend of pattern.\n", p - start);
+#else
+  printf ("%ld:\tend of pattern.\n", (long int) (p - start));
+#endif
 }
 
 
@@ -834,7 +960,8 @@ print_compiled_pattern (bufp)
   unsigned char *buffer = bufp->buffer;
 
   print_partial_compiled_pattern (buffer, buffer + bufp->used);
-  printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
+  printf ("%ld bytes used/%ld bytes allocated.\n",
+         bufp->used, bufp->allocated);
 
   if (bufp->fastmap_accurate && bufp->fastmap)
     {
@@ -842,14 +969,18 @@ print_compiled_pattern (bufp)
       print_fastmap (bufp->fastmap);
     }
 
-  printf ("re_nsub: %d\t", bufp->re_nsub);
+#ifdef _LIBC
+  printf ("re_nsub: %Zd\t", bufp->re_nsub);
+#else
+  printf ("re_nsub: %ld\t", (long int) bufp->re_nsub);
+#endif
   printf ("regs_alloc: %d\t", bufp->regs_allocated);
   printf ("can_be_null: %d\t", bufp->can_be_null);
   printf ("newline_anchor: %d\n", bufp->newline_anchor);
   printf ("no_sub: %d\t", bufp->no_sub);
   printf ("not_bol: %d\t", bufp->not_bol);
   printf ("not_eol: %d\t", bufp->not_eol);
-  printf ("syntax: %d\n", bufp->syntax);
+  printf ("syntax: %lx\n", bufp->syntax);
   /* Perhaps we should print the translate table?  */
 }
 
@@ -862,7 +993,7 @@ print_double_string (where, string1, size1, string2, size2)
     int size1;
     int size2;
 {
-  unsigned this_char;
+  int this_char;
 
   if (where == NULL)
     printf ("(null)");
@@ -881,18 +1012,25 @@ print_double_string (where, string1, size1, string2, size2)
     }
 }
 
+void
+printchar (c)
+     int c;
+{
+  putc (c, stderr);
+}
+
 #else /* not DEBUG */
 
-#undef assert
-#define assert(e)
+# undef assert
+# define assert(e)
 
-#define DEBUG_STATEMENT(e)
-#define DEBUG_PRINT1(x)
-#define DEBUG_PRINT2(x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4)
-#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
-#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+# define DEBUG_STATEMENT(e)
+# define DEBUG_PRINT1(x)
+# define DEBUG_PRINT2(x1, x2)
+# define DEBUG_PRINT3(x1, x2, x3)
+# define DEBUG_PRINT4(x1, x2, x3, x4)
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
 
 #endif /* not DEBUG */
 \f
@@ -918,32 +1056,96 @@ re_set_syntax (syntax)
   reg_syntax_t ret = re_syntax_options;
 
   re_syntax_options = syntax;
+#ifdef DEBUG
+  if (syntax & RE_DEBUG)
+    debug = 1;
+  else if (debug) /* was on but now is not */
+    debug = 0;
+#endif /* DEBUG */
   return ret;
 }
+#ifdef _LIBC
+weak_alias (__re_set_syntax, re_set_syntax)
+#endif
 \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?  */
 
-static const char *re_error_msgid[] =
-  { "Success",                                 /* REG_NOERROR */
-    "No match",                                        /* REG_NOMATCH */
-    "Invalid regular expression",              /* REG_BADPAT */
-    "Invalid collation character",             /* REG_ECOLLATE */
-    "Invalid character class name",            /* REG_ECTYPE */
-    "Trailing backslash",                      /* REG_EESCAPE */
-    "Invalid back reference",                  /* REG_ESUBREG */
-    "Unmatched [ or [^",                       /* REG_EBRACK */
-    "Unmatched ( or \\(",                      /* REG_EPAREN */
-    "Unmatched \\{",                           /* REG_EBRACE */
-    "Invalid content of \\{\\}",               /* REG_BADBR */
-    "Invalid range end",                       /* REG_ERANGE */
-    "Memory exhausted",                                /* REG_ESPACE */
-    "Invalid preceding regular expression",    /* REG_BADRPT */
-    "Premature end of regular expression",     /* REG_EEND */
-    "Regular expression too big",              /* REG_ESIZE */
-    "Unmatched ) or \\)",                      /* REG_ERPAREN */
+static const char re_error_msgid[] =
+  {
+#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 */
+  };
+
+static const size_t re_error_msgid_idx[] =
+  {
+    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
 /* Avoiding alloca during matching, to placate r_alloc.  */
@@ -971,7 +1173,7 @@ static const char *re_error_msgid[] =
 /* When using GNU C, we are not REALLY using the C alloca, no matter
    what config.h may say.  So don't take precautions for it.  */
 #ifdef __GNUC__
-#undef C_ALLOCA
+# undef C_ALLOCA
 #endif
 
 /* The match routines may not allocate if (1) they would do it with malloc
@@ -979,8 +1181,8 @@ static const char *re_error_msgid[] =
    Note that if REL_ALLOC is defined, matching would not use malloc for the
    failure stack, but we would still use it for the register vectors;
    so REL_ALLOC should not affect this.  */
-#if (defined (C_ALLOCA) || defined (REGEX_MALLOC)) && defined (emacs)
-#undef MATCH_MAY_ALLOCATE
+#if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs
+# undef MATCH_MAY_ALLOCATE
 #endif
 
 \f
@@ -993,18 +1195,48 @@ static const char *re_error_msgid[] =
    when matching.  If this number is exceeded, we allocate more
    space, so it is not a hard limit.  */
 #ifndef INIT_FAILURE_ALLOC
-#define INIT_FAILURE_ALLOC 5
+# define INIT_FAILURE_ALLOC 5
 #endif
 
 /* Roughly the maximum number of failure points on the stack.  Would be
-   exactly that if always used MAX_FAILURE_SPACE each time we failed.
+   exactly that if always used MAX_FAILURE_ITEMS items each time we failed.
    This is a variable only so users of regex can assign to it; we never
    change it ourselves.  */
-#if defined (MATCH_MAY_ALLOCATE)
-int re_max_failures = 200000;
-#else
+
+#ifdef INT_IS_16BIT
+
+# if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+   whose default stack limit is 2mb.  */
+long int re_max_failures = 4000;
+# else
+long int re_max_failures = 2000;
+# endif
+
+union fail_stack_elt
+{
+  unsigned char *pointer;
+  long int integer;
+};
+
+typedef union fail_stack_elt fail_stack_elt_t;
+
+typedef struct
+{
+  fail_stack_elt_t *stack;
+  unsigned long int size;
+  unsigned long int avail;             /* Offset of next open position.  */
+} fail_stack_type;
+
+#else /* not INT_IS_16BIT */
+
+# if defined MATCH_MAY_ALLOCATE
+/* 4400 was enough to cause a crash on Alpha OSF/1,
+   whose default stack limit is 2mb.  */
+int re_max_failures = 20000;
+# else
 int re_max_failures = 2000;
-#endif
+# endif
 
 union fail_stack_elt
 {
@@ -1021,6 +1253,8 @@ typedef struct
   unsigned avail;                      /* Offset of next open position.  */
 } fail_stack_type;
 
+#endif /* INT_IS_16BIT */
+
 #define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
 #define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
 #define FAIL_STACK_FULL()      (fail_stack.avail == fail_stack.size)
@@ -1030,10 +1264,10 @@ typedef struct
    Do `return -2' if the alloc fails.  */
 
 #ifdef MATCH_MAY_ALLOCATE
-#define INIT_FAIL_STACK()                                              \
+# define INIT_FAIL_STACK()                                             \
   do {                                                                 \
     fail_stack.stack = (fail_stack_elt_t *)                            \
-      REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t));   \
+      REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
                                                                        \
     if (fail_stack.stack == NULL)                                      \
       return -2;                                                       \
@@ -1042,14 +1276,14 @@ typedef struct
     fail_stack.avail = 0;                                              \
   } while (0)
 
-#define RESET_FAIL_STACK()  REGEX_FREE_STACK (fail_stack.stack)
+# define RESET_FAIL_STACK()  REGEX_FREE_STACK (fail_stack.stack)
 #else
-#define INIT_FAIL_STACK()                                              \
+# define INIT_FAIL_STACK()                                             \
   do {                                                                 \
     fail_stack.avail = 0;                                              \
   } while (0)
 
-#define RESET_FAIL_STACK()
+# define RESET_FAIL_STACK()
 #endif
 
 
@@ -1061,7 +1295,7 @@ typedef struct
    REGEX_REALLOCATE_STACK requires `destination' be declared.   */
 
 #define DOUBLE_FAIL_STACK(fail_stack)                                  \
-  ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS             \
+  ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS)        \
    ? 0                                                                 \
    : ((fail_stack).stack = (fail_stack_elt_t *)                                \
         REGEX_REALLOCATE_STACK ((fail_stack).stack,                    \
@@ -1110,11 +1344,11 @@ typedef struct
 
 /* Used to omit pushing failure point id's when we're not debugging.  */
 #ifdef DEBUG
-#define DEBUG_PUSH PUSH_FAILURE_INT
-#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
+# define DEBUG_PUSH PUSH_FAILURE_INT
+# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT ()
 #else
-#define DEBUG_PUSH(item)
-#define DEBUG_POP(item_addr)
+# define DEBUG_PUSH(item)
+# define DEBUG_POP(item_addr)
 #endif
 
 
@@ -1122,8 +1356,8 @@ typedef struct
    if we ever fail back to it.
 
    Requires variables fail_stack, regstart, regend, reg_info, and
-   num_regs be declared.  DOUBLE_FAIL_STACK requires `destination' be
-   declared.
+   num_regs_pushed be declared.  DOUBLE_FAIL_STACK requires `destination'
+   be declared.
 
    Does `return FAILURE_CODE' if runs out of memory.  */
 
@@ -1132,7 +1366,10 @@ typedef struct
     char *destination;                                                 \
     /* Must be int, so when we don't save any registers, the arithmetic        \
        of 0 + -1 isn't done as unsigned.  */                           \
-    int this_reg;                                                      \
+    /* Can't be int, since there is not a shred of a guarantee that int        \
+       is wide enough to hold a value of something to which pointer can        \
+       be assigned */                                                  \
+    active_reg_t this_reg;                                             \
                                                                        \
     DEBUG_STATEMENT (failure_id++);                                    \
     DEBUG_STATEMENT (nfailure_points_pushed++);                                \
@@ -1140,7 +1377,7 @@ typedef struct
     DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
     DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
                                                                        \
-    DEBUG_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);          \
+    DEBUG_PRINT2 ("  slots needed: %ld\n", NUM_FAILURE_ITEMS);         \
     DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);      \
                                                                        \
     /* Ensure we have enough space allocated for what we will push.  */        \
@@ -1157,20 +1394,21 @@ typedef struct
     /* Push the info, starting with the registers.  */                 \
     DEBUG_PRINT1 ("\n");                                               \
                                                                        \
-    if (!(RE_NO_POSIX_BACKTRACKING & bufp->syntax))                    \
+    if (1)                                                             \
       for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
           this_reg++)                                                  \
        {                                                               \
-         DEBUG_PRINT2 ("  Pushing reg: %d\n", this_reg);               \
+         DEBUG_PRINT2 ("  Pushing reg: %lu\n", this_reg);              \
          DEBUG_STATEMENT (num_regs_pushed++);                          \
                                                                        \
-         DEBUG_PRINT2 ("    start: 0x%x\n", regstart[this_reg]);       \
+         DEBUG_PRINT2 ("    start: %p\n", regstart[this_reg]);         \
          PUSH_FAILURE_POINTER (regstart[this_reg]);                    \
                                                                        \
-         DEBUG_PRINT2 ("    end: 0x%x\n", regend[this_reg]);           \
+         DEBUG_PRINT2 ("    end: %p\n", regend[this_reg]);             \
          PUSH_FAILURE_POINTER (regend[this_reg]);                      \
                                                                        \
-         DEBUG_PRINT2 ("    info: 0x%x\n      ", reg_info[this_reg]);  \
+         DEBUG_PRINT2 ("    info: %p\n      ",                         \
+                       reg_info[this_reg].word.pointer);               \
          DEBUG_PRINT2 (" match_null=%d",                               \
                        REG_MATCH_NULL_STRING_P (reg_info[this_reg]));  \
          DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));  \
@@ -1182,17 +1420,17 @@ typedef struct
          PUSH_FAILURE_ELT (reg_info[this_reg].word);                   \
        }                                                               \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg);\
+    DEBUG_PRINT2 ("  Pushing  low active reg: %ld\n", lowest_active_reg);\
     PUSH_FAILURE_INT (lowest_active_reg);                              \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);\
+    DEBUG_PRINT2 ("  Pushing high active reg: %ld\n", highest_active_reg);\
     PUSH_FAILURE_INT (highest_active_reg);                             \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing pattern 0x%x: ", pattern_place);          \
+    DEBUG_PRINT2 ("  Pushing pattern %p:\n", pattern_place);           \
     DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);          \
     PUSH_FAILURE_POINTER (pattern_place);                              \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing string 0x%x: `", string_place);           \
+    DEBUG_PRINT2 ("  Pushing string %p: `", string_place);             \
     DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
                                 size2);                                \
     DEBUG_PRINT1 ("'\n");                                              \
@@ -1208,17 +1446,20 @@ typedef struct
 
 /* Individual items aside from the registers.  */
 #ifdef DEBUG
-#define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
+# define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
 #else
-#define NUM_NONREG_ITEMS 4
+# define NUM_NONREG_ITEMS 4
 #endif
 
 /* We push at most this many items on the stack.  */
-#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+/* We used to use (num_regs - 1), which is the number of registers
+   this regexp will save; but that was changed to 5
+   to avoid stack overflow for a regexp with lots of parens.  */
+#define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
 
 /* We actually push this many items.  */
 #define NUM_FAILURE_ITEMS                              \
-  (((RE_NO_POSIX_BACKTRACKING & bufp->syntax           \
+  (((0                                                 \
      ? 0 : highest_active_reg - lowest_active_reg + 1) \
     * NUM_REG_ITEMS)                                   \
    + NUM_NONREG_ITEMS)
@@ -1241,8 +1482,8 @@ typedef struct
 
 #define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
 {                                                                      \
-  DEBUG_STATEMENT (fail_stack_elt_t failure_id;)                       \
-  int this_reg;                                                                \
+  DEBUG_STATEMENT (unsigned failure_id;)                               \
+  active_reg_t this_reg;                                               \
   const unsigned char *string_temp;                                    \
                                                                        \
   assert (!FAIL_STACK_EMPTY ());                                       \
@@ -1264,34 +1505,35 @@ typedef struct
   if (string_temp != NULL)                                             \
     str = (const char *) string_temp;                                  \
                                                                        \
-  DEBUG_PRINT2 ("  Popping string 0x%x: `", str);                      \
+  DEBUG_PRINT2 ("  Popping string %p: `", str);                                \
   DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);     \
   DEBUG_PRINT1 ("'\n");                                                        \
                                                                        \
   pat = (unsigned char *) POP_FAILURE_POINTER ();                      \
-  DEBUG_PRINT2 ("  Popping pattern 0x%x: ", pat);                      \
+  DEBUG_PRINT2 ("  Popping pattern %p:\n", pat);                       \
   DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);                      \
                                                                        \
   /* Restore register info.  */                                                \
-  high_reg = (unsigned) POP_FAILURE_INT ();                            \
-  DEBUG_PRINT2 ("  Popping high active reg: %d\n", high_reg);          \
+  high_reg = (active_reg_t) POP_FAILURE_INT ();                                \
+  DEBUG_PRINT2 ("  Popping high active reg: %ld\n", high_reg);         \
                                                                        \
-  low_reg = (unsigned) POP_FAILURE_INT ();                             \
-  DEBUG_PRINT2 ("  Popping  low active reg: %d\n", low_reg);           \
+  low_reg = (active_reg_t) POP_FAILURE_INT ();                         \
+  DEBUG_PRINT2 ("  Popping  low active reg: %ld\n", low_reg);          \
                                                                        \
-  if (!(RE_NO_POSIX_BACKTRACKING & bufp->syntax))                      \
+  if (1)                                                               \
     for (this_reg = high_reg; this_reg >= low_reg; this_reg--)         \
       {                                                                        \
-       DEBUG_PRINT2 ("    Popping reg: %d\n", this_reg);               \
+       DEBUG_PRINT2 ("    Popping reg: %ld\n", this_reg);              \
                                                                        \
        reg_info[this_reg].word = POP_FAILURE_ELT ();                   \
-       DEBUG_PRINT2 ("      info: 0x%x\n", reg_info[this_reg]);        \
+       DEBUG_PRINT2 ("      info: %p\n",                               \
+                     reg_info[this_reg].word.pointer);                 \
                                                                        \
        regend[this_reg] = (const char *) POP_FAILURE_POINTER ();       \
-       DEBUG_PRINT2 ("      end: 0x%x\n", regend[this_reg]);           \
+       DEBUG_PRINT2 ("      end: %p\n", regend[this_reg]);             \
                                                                        \
        regstart[this_reg] = (const char *) POP_FAILURE_POINTER ();     \
-       DEBUG_PRINT2 ("      start: 0x%x\n", regstart[this_reg]);       \
+       DEBUG_PRINT2 ("      start: %p\n", regstart[this_reg]);         \
       }                                                                        \
   else                                                                 \
     {                                                                  \
@@ -1321,6 +1563,9 @@ typedef struct
    the type of `word', i.e., is something that fits into one item on the
    failure stack.  */
 
+
+/* Declarations and macros for re_match_2.  */
+
 typedef union
 {
   fail_stack_elt_t word;
@@ -1350,7 +1595,7 @@ typedef union
     {                                                                  \
       if (!set_regs_matched_done)                                      \
        {                                                               \
-         unsigned r;                                                   \
+         active_reg_t r;                                               \
          set_regs_matched_done = 1;                                    \
          for (r = lowest_active_reg; r <= highest_active_reg; r++)     \
            {                                                           \
@@ -1369,18 +1614,33 @@ static char reg_unset_dummy;
 \f
 /* Subroutine declarations and macros for regex_compile.  */
 
-static void store_op1 (), store_op2 ();
-static void insert_op1 (), insert_op2 ();
-static boolean at_begline_loc_p (), at_endline_loc_p ();
-static boolean group_in_compile_stack ();
-static reg_errcode_t compile_range ();
+static reg_errcode_t regex_compile _RE_ARGS ((const char *pattern, size_t size,
+                                             reg_syntax_t syntax,
+                                             struct re_pattern_buffer *bufp));
+static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg));
+static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+                                int arg1, int arg2));
+static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+                                 int arg, unsigned char *end));
+static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc,
+                                 int arg1, int arg2, unsigned char *end));
+static boolean at_begline_loc_p _RE_ARGS ((const char *pattern, const char *p,
+                                          reg_syntax_t syntax));
+static boolean at_endline_loc_p _RE_ARGS ((const char *p, const char *pend,
+                                          reg_syntax_t syntax));
+static reg_errcode_t compile_range _RE_ARGS ((unsigned int range_start,
+                                             const char **p_ptr,
+                                             const char *pend,
+                                             char *translate,
+                                             reg_syntax_t syntax,
+                                             unsigned char *b));
 
 /* Fetch the next character in the uncompiled pattern---translating it
    if necessary.  Also cast from a signed character in the constant
    string passed to us by the user to an unsigned char that we can use
    as an array index (in, e.g., `translate').  */
 #ifndef PATFETCH
-#define PATFETCH(c)                                                    \
+# define PATFETCH(c)                                                   \
   do {if (p == pend) return REG_EEND;                                  \
     c = (unsigned char) *p++;                                          \
     if (translate) c = (unsigned char) translate[c];                   \
@@ -1403,7 +1663,7 @@ static reg_errcode_t compile_range ();
    `char *', to avoid warnings when a string constant is passed.  But
    when we use a character as a subscript we must make it unsigned.  */
 #ifndef TRANSLATE
-#define TRANSLATE(d) \
+# define TRANSLATE(d) \
   (translate ? (char) translate[(unsigned char) (d)] : (d))
 #endif
 
@@ -1415,7 +1675,7 @@ static reg_errcode_t compile_range ();
 
 /* Make sure we have at least N more bytes of space in buffer.  */
 #define GET_BUFFER_SPACE(n)                                            \
-    while (b - bufp->buffer + (n) > bufp->allocated)                   \
+    while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \
       EXTEND_BUFFER ()
 
 /* Make sure we have one more byte of buffer space and then add C to it.  */
@@ -1448,54 +1708,89 @@ static reg_errcode_t compile_range ();
 /* Store a jump with opcode OP at LOC to location TO.  We store a
    relative address offset by the three bytes the jump itself occupies.  */
 #define STORE_JUMP(op, loc, to) \
-  store_op1 (op, loc, (to) - (loc) - 3)
+  store_op1 (op, loc, (int) ((to) - (loc) - 3))
 
 /* Likewise, for a two-argument jump.  */
 #define STORE_JUMP2(op, loc, to, arg) \
-  store_op2 (op, loc, (to) - (loc) - 3, arg)
+  store_op2 (op, loc, (int) ((to) - (loc) - 3), arg)
 
 /* Like `STORE_JUMP', but for inserting.  Assume `b' is the buffer end.  */
 #define INSERT_JUMP(op, loc, to) \
-  insert_op1 (op, loc, (to) - (loc) - 3, b)
+  insert_op1 (op, loc, (int) ((to) - (loc) - 3), b)
 
 /* Like `STORE_JUMP2', but for inserting.  Assume `b' is the buffer end.  */
 #define INSERT_JUMP2(op, loc, to, arg) \
-  insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
+  insert_op2 (op, loc, (int) ((to) - (loc) - 3), arg, b)
 
 
 /* This is not an arbitrary limit: the arguments which represent offsets
    into the pattern are two bytes long.  So if 2^16 bytes turns out to
    be too small, many things would have to change.  */
-#define MAX_BUF_SIZE (1L << 16)
-
+/* Any other compiler which, like MSC, has allocation limit below 2^16
+   bytes will have to use approach similar to what was done below for
+   MSC and drop MAX_BUF_SIZE a bit.  Otherwise you may end up
+   reallocating to 0 bytes.  Such thing is not going to work too well.
+   You have been warned!!  */
+#if defined _MSC_VER  && !defined WIN32
+/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes.
+   The REALLOC define eliminates a flurry of conversion warnings,
+   but is not required. */
+# define MAX_BUF_SIZE  65500L
+# define REALLOC(p,s) realloc ((p), (size_t) (s))
+#else
+# define MAX_BUF_SIZE (1L << 16)
+# define REALLOC(p,s) realloc ((p), (s))
+#endif
 
 /* Extend the buffer by twice its current size via realloc and
    reset the pointers that pointed into the old block to point to the
    correct places in the new one.  If extending the buffer results in it
    being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
+#if __BOUNDED_POINTERS__
+# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated)
+# define MOVE_BUFFER_POINTER(P) \
+  (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr)
+# define ELSE_EXTEND_BUFFER_HIGH_BOUND         \
+  else                                         \
+    {                                          \
+      SET_HIGH_BOUND (b);                      \
+      SET_HIGH_BOUND (begalt);                 \
+      if (fixup_alt_jump)                      \
+       SET_HIGH_BOUND (fixup_alt_jump);        \
+      if (laststart)                           \
+       SET_HIGH_BOUND (laststart);             \
+      if (pending_exact)                       \
+       SET_HIGH_BOUND (pending_exact);         \
+    }
+#else
+# define MOVE_BUFFER_POINTER(P) (P) += incr
+# define ELSE_EXTEND_BUFFER_HIGH_BOUND
+#endif
 #define EXTEND_BUFFER()                                                        \
-  do {                                                                         \
+  do {                                                                 \
     unsigned char *old_buffer = bufp->buffer;                          \
-    if (bufp->allocated == MAX_BUF_SIZE)                               \
+    if (bufp->allocated == MAX_BUF_SIZE)                               \
       return REG_ESIZE;                                                        \
     bufp->allocated <<= 1;                                             \
     if (bufp->allocated > MAX_BUF_SIZE)                                        \
-      bufp->allocated = MAX_BUF_SIZE;                                  \
-    bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
+      bufp->allocated = MAX_BUF_SIZE;                                  \
+    bufp->buffer = (unsigned char *) REALLOC (bufp->buffer, bufp->allocated);\
     if (bufp->buffer == NULL)                                          \
       return REG_ESPACE;                                               \
     /* If the buffer moved, move all the pointers into it.  */         \
     if (old_buffer != bufp->buffer)                                    \
       {                                                                        \
-        b = (b - old_buffer) + bufp->buffer;                           \
-        begalt = (begalt - old_buffer) + bufp->buffer;                 \
-        if (fixup_alt_jump)                                            \
-          fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
-        if (laststart)                                                 \
-          laststart = (laststart - old_buffer) + bufp->buffer;         \
-        if (pending_exact)                                             \
-          pending_exact = (pending_exact - old_buffer) + bufp->buffer; \
+       int incr = bufp->buffer - old_buffer;                           \
+       MOVE_BUFFER_POINTER (b);                                        \
+       MOVE_BUFFER_POINTER (begalt);                                   \
+       if (fixup_alt_jump)                                             \
+         MOVE_BUFFER_POINTER (fixup_alt_jump);                         \
+       if (laststart)                                                  \
+         MOVE_BUFFER_POINTER (laststart);                              \
+       if (pending_exact)                                              \
+         MOVE_BUFFER_POINTER (pending_exact);                          \
       }                                                                        \
+    ELSE_EXTEND_BUFFER_HIGH_BOUND                                      \
   } while (0)
 
 
@@ -1513,7 +1808,8 @@ typedef unsigned regnum_t;
 
 /* Since offsets can go either forwards or backwards, this type needs to
    be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.  */
-typedef int pattern_offset_t;
+/* int may be not enough when sizeof(int) == 2.  */
+typedef long pattern_offset_t;
 
 typedef struct
 {
@@ -1553,7 +1849,7 @@ typedef struct
   { if (p != pend)                                                     \
      {                                                                 \
        PATFETCH (c);                                                   \
-       while (ISDIGIT (c))                                             \
+       while ('0' <= c && c <= '9')                                    \
          {                                                             \
            if (num < 0)                                                        \
               num = 0;                                                 \
@@ -1565,15 +1861,33 @@ typedef struct
        }                                                               \
     }
 
-#define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+/* The GNU C library provides support for user-defined character classes
+   and the functions from ISO C amendement 1.  */
+# ifdef CHARCLASS_NAME_MAX
+#  define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+# else
+/* This shouldn't happen but some implementation might still have this
+   problem.  Use a reasonable default value.  */
+#  define CHAR_CLASS_MAX_LENGTH 256
+# endif
+
+# ifdef _LIBC
+#  define IS_CHAR_CLASS(string) __wctype (string)
+# else
+#  define IS_CHAR_CLASS(string) wctype (string)
+# endif
+#else
+# define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
 
-#define IS_CHAR_CLASS(string)                                          \
+# define IS_CHAR_CLASS(string)                                         \
    (STREQ (string, "alpha") || STREQ (string, "upper")                 \
     || STREQ (string, "lower") || STREQ (string, "digit")              \
     || STREQ (string, "alnum") || STREQ (string, "xdigit")             \
     || STREQ (string, "space") || STREQ (string, "print")              \
     || STREQ (string, "punct") || STREQ (string, "graph")              \
     || STREQ (string, "cntrl") || STREQ (string, "blank"))
+#endif
 \f
 #ifndef MATCH_MAY_ALLOCATE
 
@@ -1623,6 +1937,10 @@ regex_grow_registers (num_regs)
 
 #endif /* not MATCH_MAY_ALLOCATE */
 \f
+static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type
+                                                compile_stack,
+                                                regnum_t regnum));
+
 /* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
    Returns one of error codes defined in `regex.h', or zero for success.
 
@@ -1648,7 +1966,7 @@ regex_grow_registers (num_regs)
 static reg_errcode_t
 regex_compile (pattern, size, syntax, bufp)
      const char *pattern;
-     int size;
+     size_t size;
      reg_syntax_t syntax;
      struct re_pattern_buffer *bufp;
 {
@@ -1734,7 +2052,7 @@ regex_compile (pattern, size, syntax, bufp)
   /* Always count groups, whether or not bufp->no_sub is set.  */
   bufp->re_nsub = 0;
 
-#if !defined (emacs) && !defined (SYNTAX_TABLE)
+#if !defined emacs && !defined SYNTAX_TABLE
   /* Initialize the syntax table.  */
    init_syntax_once ();
 #endif
@@ -1937,6 +2255,7 @@ regex_compile (pattern, size, syntax, bufp)
         case '[':
           {
             boolean had_char_class = false;
+           unsigned int range_start = 0xffffffff;
 
             if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
 
@@ -1980,6 +2299,7 @@ regex_compile (pattern, size, syntax, bufp)
 
                     PATFETCH (c1);
                     SET_LIST_BIT (c1);
+                   range_start = c1;
                     continue;
                   }
 
@@ -2004,8 +2324,10 @@ regex_compile (pattern, size, syntax, bufp)
                     && *p != ']')
                   {
                     reg_errcode_t ret
-                      = compile_range (&p, pend, translate, syntax, b);
+                      = compile_range (range_start, &p, pend, translate,
+                                      syntax, b);
                     if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+                   range_start = 0xffffffff;
                   }
 
                 else if (p[0] == '-' && p[1] != ']')
@@ -2015,8 +2337,9 @@ regex_compile (pattern, size, syntax, bufp)
                    /* Move past the `-'.  */
                     PATFETCH (c1);
 
-                    ret = compile_range (&p, pend, translate, syntax, b);
+                    ret = compile_range (c, &p, pend, translate, syntax, b);
                     if (ret != REG_NOERROR) FREE_STACK_RETURN (ret);
+                   range_start = 0xffffffff;
                   }
 
                 /* See if we're at the beginning of a possible character
@@ -2035,18 +2358,54 @@ regex_compile (pattern, size, syntax, bufp)
                     for (;;)
                       {
                         PATFETCH (c);
-                        if (c == ':' || c == ']' || p == pend
-                            || c1 == CHAR_CLASS_MAX_LENGTH)
+                        if ((c == ':' && *p == ']') || p == pend)
                           break;
-                        str[c1++] = c;
+                       if (c1 < CHAR_CLASS_MAX_LENGTH)
+                         str[c1++] = c;
+                       else
+                         /* This is in any case an invalid class name.  */
+                         str[0] = '\0';
                       }
                     str[c1] = '\0';
 
-                    /* If isn't a word bracketed by `[:' and:`]':
+                    /* If isn't a word bracketed by `[:' and `:]':
                        undo the ending character, the letters, and leave
                        the leading `:' and `[' (but set bits for them).  */
                     if (c == ':' && *p == ']')
                       {
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+                        boolean is_lower = STREQ (str, "lower");
+                        boolean is_upper = STREQ (str, "upper");
+                       wctype_t wt;
+                        int ch;
+
+                       wt = IS_CHAR_CLASS (str);
+                       if (wt == 0)
+                         FREE_STACK_RETURN (REG_ECTYPE);
+
+                        /* Throw away the ] at the end of the character
+                           class.  */
+                        PATFETCH (c);
+
+                        if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                        for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
+                         {
+# ifdef _LIBC
+                           if (__iswctype (__btowc (ch), wt))
+                             SET_LIST_BIT (ch);
+# else
+                           if (iswctype (btowc (ch), wt))
+                             SET_LIST_BIT (ch);
+# endif
+
+                           if (translate && (is_upper || is_lower)
+                               && (ISUPPER (ch) || ISLOWER (ch)))
+                             SET_LIST_BIT (ch);
+                         }
+
+                        had_char_class = true;
+#else
                         int ch;
                         boolean is_alnum = STREQ (str, "alnum");
                         boolean is_alpha = STREQ (str, "alpha");
@@ -2089,8 +2448,12 @@ regex_compile (pattern, size, syntax, bufp)
                                 || (is_upper  && ISUPPER (ch))
                                 || (is_xdigit && ISXDIGIT (ch)))
                              SET_LIST_BIT (ch);
+                           if (   translate && (is_upper || is_lower)
+                               && (ISUPPER (ch) || ISLOWER (ch)))
+                             SET_LIST_BIT (ch);
                           }
                         had_char_class = true;
+#endif /* libc || wctype.h */
                       }
                     else
                       {
@@ -2099,13 +2462,289 @@ regex_compile (pattern, size, syntax, bufp)
                           PATUNFETCH;
                         SET_LIST_BIT ('[');
                         SET_LIST_BIT (':');
+                       range_start = ':';
                         had_char_class = false;
                       }
                   }
+                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=')
+                 {
+                   unsigned char str[MB_LEN_MAX + 1];
+#ifdef _LIBC
+                   uint32_t nrules =
+                     _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+#endif
+
+                   PATFETCH (c);
+                   c1 = 0;
+
+                   /* If pattern is `[[='.  */
+                   if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                   for (;;)
+                     {
+                       PATFETCH (c);
+                       if ((c == '=' && *p == ']') || p == pend)
+                         break;
+                       if (c1 < MB_LEN_MAX)
+                         str[c1++] = c;
+                       else
+                         /* This is in any case an invalid class name.  */
+                         str[0] = '\0';
+                      }
+                   str[c1] = '\0';
+
+                   if (c == '=' && *p == ']' && str[0] != '\0')
+                     {
+                       /* If we have no collation data we use the default
+                          collation in which each character is in a class
+                          by itself.  It also means that ASCII is the
+                          character set and therefore we cannot have character
+                          with more than one byte in the multibyte
+                          representation.  */
+#ifdef _LIBC
+                       if (nrules == 0)
+#endif
+                         {
+                           if (c1 != 1)
+                             FREE_STACK_RETURN (REG_ECOLLATE);
+
+                           /* Throw away the ] at the end of the equivalence
+                              class.  */
+                           PATFETCH (c);
+
+                           /* Set the bit for the character.  */
+                           SET_LIST_BIT (str[0]);
+                         }
+#ifdef _LIBC
+                       else
+                         {
+                           /* Try to match the byte sequence in `str' against
+                              those known to the collate implementation.
+                              First find out whether the bytes in `str' are
+                              actually from exactly one character.  */
+                           const int32_t *table;
+                           const unsigned char *weights;
+                           const unsigned char *extra;
+                           const int32_t *indirect;
+                           int32_t idx;
+                           const unsigned char *cp = str;
+                           int ch;
+
+                           /* This #include defines a local function!  */
+# include <locale/weight.h>
+
+                           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 || cp < str + c1)
+                             /* This is no valid character.  */
+                             FREE_STACK_RETURN (REG_ECOLLATE);
+
+                           /* Throw away the ] at the end of the equivalence
+                              class.  */
+                           PATFETCH (c);
+
+                           /* Now we have to go throught the whole table
+                              and find all characters which have the same
+                              first level weight.
+
+                              XXX Note that this is not entirely correct.
+                              we would have to match multibyte sequences
+                              but this is not possible with the current
+                              implementation.  */
+                           for (ch = 1; ch < 256; ++ch)
+                             /* XXX This test would have to be changed if we
+                                would allow matching multibyte sequences.  */
+                             if (table[ch] > 0)
+                               {
+                                 int32_t idx2 = table[ch];
+                                 size_t len = weights[idx2];
+
+                                 /* Test whether the lenghts match.  */
+                                 if (weights[idx] == len)
+                                   {
+                                     /* They do.  New compare the bytes of
+                                        the weight.  */
+                                     size_t cnt = 0;
+
+                                     while (cnt < len
+                                            && (weights[idx + 1 + cnt]
+                                                == weights[idx2 + 1 + cnt]))
+                                       ++len;
+
+                                     if (cnt == len)
+                                       /* They match.  Mark the character as
+                                          acceptable.  */
+                                       SET_LIST_BIT (ch);
+                                   }
+                               }
+                         }
+#endif
+                       had_char_class = true;
+                     }
+                    else
+                      {
+                        c1++;
+                        while (c1--)
+                          PATUNFETCH;
+                        SET_LIST_BIT ('[');
+                        SET_LIST_BIT ('=');
+                       range_start = '=';
+                        had_char_class = false;
+                      }
+                 }
+                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.')
+                 {
+                   unsigned char str[128];     /* Should be large enough.  */
+#ifdef _LIBC
+                   uint32_t nrules =
+                     _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+#endif
+
+                   PATFETCH (c);
+                   c1 = 0;
+
+                   /* If pattern is `[[='.  */
+                   if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+                   for (;;)
+                     {
+                       PATFETCH (c);
+                       if ((c == '.' && *p == ']') || p == pend)
+                         break;
+                       if (c1 < sizeof (str))
+                         str[c1++] = c;
+                       else
+                         /* This is in any case an invalid class name.  */
+                         str[0] = '\0';
+                      }
+                   str[c1] = '\0';
+
+                   if (c == '.' && *p == ']' && str[0] != '\0')
+                     {
+                       /* If we have no collation data we use the default
+                          collation in which each character is the name
+                          for its own class which contains only the one
+                          character.  It also means that ASCII is the
+                          character set and therefore we cannot have character
+                          with more than one byte in the multibyte
+                          representation.  */
+#ifdef _LIBC
+                       if (nrules == 0)
+#endif
+                         {
+                           if (c1 != 1)
+                             FREE_STACK_RETURN (REG_ECOLLATE);
+
+                           /* Throw away the ] at the end of the equivalence
+                              class.  */
+                           PATFETCH (c);
+
+                           /* Set the bit for the character.  */
+                           SET_LIST_BIT (str[0]);
+                           range_start = ((const unsigned char *) str)[0];
+                         }
+#ifdef _LIBC
+                       else
+                         {
+                           /* Try to match the byte sequence in `str' against
+                              those known to the collate implementation.
+                              First find out whether the bytes in `str' are
+                              actually from exactly one character.  */
+                           int32_t table_size;
+                           const int32_t *symb_table;
+                           const unsigned char *extra;
+                           int32_t idx;
+                           int32_t elem;
+                           int32_t second;
+                           int32_t hash;
+
+                           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);
+
+                           /* Locate the character in the hashing table.  */
+                           hash = elem_hash (str, c1);
+
+                           idx = 0;
+                           elem = hash % table_size;
+                           second = hash % (table_size - 2);
+                           while (symb_table[2 * elem] != 0)
+                             {
+                               /* First compare the hashing value.  */
+                               if (symb_table[2 * elem] == hash
+                                   && c1 == extra[symb_table[2 * elem + 1]]
+                                   && memcmp (str,
+                                              &extra[symb_table[2 * elem + 1]
+                                                    + 1],
+                                              c1) == 0)
+                                 {
+                                   /* Yep, this is the entry.  */
+                                   idx = symb_table[2 * elem + 1];
+                                   idx += 1 + extra[idx];
+                                   break;
+                                 }
+
+                               /* Next entry.  */
+                               elem += second;
+                             }
+
+                           if (symb_table[2 * elem] == 0)
+                             /* This is no valid character.  */
+                             FREE_STACK_RETURN (REG_ECOLLATE);
+
+                           /* Throw away the ] at the end of the equivalence
+                              class.  */
+                           PATFETCH (c);
+
+                           /* Now add the multibyte character(s) we found
+                              to the acceptabed list.
+
+                              XXX Note that this is not entirely correct.
+                              we would have to match multibyte sequences
+                              but this is not possible with the current
+                              implementation.  Also, we have to match
+                              collating symbols, which expand to more than
+                              one file, as a whole and not allow the
+                              individual bytes.  */
+                           c1 = extra[idx++];
+                           if (c1 == 1)
+                             range_start = extra[idx];
+                           while (c1-- > 0)
+                             SET_LIST_BIT (extra[idx++]);
+                         }
+#endif
+                       had_char_class = false;
+                     }
+                    else
+                      {
+                        c1++;
+                        while (c1--)
+                          PATUNFETCH;
+                        SET_LIST_BIT ('[');
+                        SET_LIST_BIT ('.');
+                       range_start = '.';
+                        had_char_class = false;
+                      }
+                 }
                 else
                   {
                     had_char_class = false;
                     SET_LIST_BIT (c);
+                   range_start = c;
                   }
               }
 
@@ -2216,10 +2855,12 @@ regex_compile (pattern, size, syntax, bufp)
               if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
 
               if (COMPILE_STACK_EMPTY)
-                if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
-                  goto normal_backslash;
-                else
-                  FREE_STACK_RETURN (REG_ERPAREN);
+               {
+                 if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+                   goto normal_backslash;
+                 else
+                   FREE_STACK_RETURN (REG_ERPAREN);
+               }
 
             handle_close:
               if (fixup_alt_jump)
@@ -2236,10 +2877,12 @@ regex_compile (pattern, size, syntax, bufp)
 
               /* See similar code for backslashed left paren above.  */
               if (COMPILE_STACK_EMPTY)
-                if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
-                  goto normal_char;
-                else
-                  FREE_STACK_RETURN (REG_ERPAREN);
+               {
+                 if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+                   goto normal_char;
+                 else
+                   FREE_STACK_RETURN (REG_ERPAREN);
+               }
 
               /* Since we just checked for an empty stack above, this
                  ``can't happen''.  */
@@ -2328,8 +2971,7 @@ regex_compile (pattern, size, syntax, bufp)
               if (!(syntax & RE_INTERVALS)
                      /* If we're at `\{' and it's not the open-interval
                         operator.  */
-                  || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
-                  || (p - 2 == pattern  &&  p == pend))
+                 || (syntax & RE_NO_BK_BRACES))
                 goto normal_backslash;
 
             handle_interval:
@@ -2343,7 +2985,7 @@ regex_compile (pattern, size, syntax, bufp)
 
                 if (p == pend)
                   {
-                    if (syntax & RE_NO_BK_BRACES)
+                    if (!(syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
                       goto unfetch_interval;
                     else
                       FREE_STACK_RETURN (REG_EBRACE);
@@ -2354,7 +2996,12 @@ regex_compile (pattern, size, syntax, bufp)
                 if (c == ',')
                   {
                     GET_UNSIGNED_NUMBER (upper_bound);
-                    if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+                   if ((!(syntax & RE_NO_BK_BRACES) && c != '\\')
+                       || ((syntax & RE_NO_BK_BRACES) && c != '}'))
+                     FREE_STACK_RETURN (REG_BADBR);
+
+                   if (upper_bound < 0)
+                     upper_bound = RE_DUP_MAX;
                   }
                 else
                   /* Interval such as `{1}' => match exactly once. */
@@ -2363,7 +3010,7 @@ regex_compile (pattern, size, syntax, bufp)
                 if (lower_bound < 0 || upper_bound > RE_DUP_MAX
                     || lower_bound > upper_bound)
                   {
-                    if (syntax & RE_NO_BK_BRACES)
+                    if (!(syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
                       goto unfetch_interval;
                     else
                       FREE_STACK_RETURN (REG_BADBR);
@@ -2378,7 +3025,7 @@ regex_compile (pattern, size, syntax, bufp)
 
                 if (c != '}')
                   {
-                    if (syntax & RE_NO_BK_BRACES)
+                    if (!(syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
                       goto unfetch_interval;
                     else
                       FREE_STACK_RETURN (REG_BADBR);
@@ -2514,38 +3161,54 @@ regex_compile (pattern, size, syntax, bufp)
 
 
             case 'w':
+             if (syntax & RE_NO_GNU_OPS)
+               goto normal_char;
               laststart = b;
               BUF_PUSH (wordchar);
               break;
 
 
             case 'W':
+             if (syntax & RE_NO_GNU_OPS)
+               goto normal_char;
               laststart = b;
               BUF_PUSH (notwordchar);
               break;
 
 
             case '<':
+             if (syntax & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (wordbeg);
               break;
 
             case '>':
+             if (syntax & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (wordend);
               break;
 
             case 'b':
+             if (syntax & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (wordbound);
               break;
 
             case 'B':
+             if (syntax & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (notwordbound);
               break;
 
             case '`':
+             if (syntax & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (begbuf);
               break;
 
             case '\'':
+             if (syntax & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (endbuf);
               break;
 
@@ -2560,7 +3223,7 @@ regex_compile (pattern, size, syntax, bufp)
                 FREE_STACK_RETURN (REG_ESUBREG);
 
               /* Can't back reference to a subexpression if inside of it.  */
-              if (group_in_compile_stack (compile_stack, c1))
+              if (group_in_compile_stack (compile_stack, (regnum_t) c1))
                 goto normal_char;
 
               laststart = b;
@@ -2663,7 +3326,7 @@ regex_compile (pattern, size, syntax, bufp)
       {
        fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS);
 
-#ifdef emacs
+# ifdef emacs
        if (! fail_stack.stack)
          fail_stack.stack
            = (fail_stack_elt_t *) xmalloc (fail_stack.size
@@ -2673,7 +3336,7 @@ regex_compile (pattern, size, syntax, bufp)
            = (fail_stack_elt_t *) xrealloc (fail_stack.stack,
                                             (fail_stack.size
                                              * sizeof (fail_stack_elt_t)));
-#else /* not emacs */
+# else /* not emacs */
        if (! fail_stack.stack)
          fail_stack.stack
            = (fail_stack_elt_t *) malloc (fail_stack.size
@@ -2683,7 +3346,7 @@ regex_compile (pattern, size, syntax, bufp)
            = (fail_stack_elt_t *) realloc (fail_stack.stack,
                                            (fail_stack.size
                                             * sizeof (fail_stack_elt_t)));
-#endif /* not emacs */
+# endif /* not emacs */
       }
 
     regex_grow_registers (num_regs);
@@ -2787,7 +3450,7 @@ at_begline_loc_p (pattern, p, syntax)
 static boolean
 at_endline_loc_p (p, pend, syntax)
     const char *p, *pend;
-    int syntax;
+    reg_syntax_t syntax;
 {
   const char *next = p;
   boolean next_backslash = *next == '\\';
@@ -2835,49 +3498,53 @@ group_in_compile_stack (compile_stack, regnum)
    `regex_compile' itself.  */
 
 static reg_errcode_t
-compile_range (p_ptr, pend, translate, syntax, b)
-    const char **p_ptr, *pend;
-    RE_TRANSLATE_TYPE translate;
-    reg_syntax_t syntax;
-    unsigned char *b;
+compile_range (range_start_char, p_ptr, pend, translate, syntax, b)
+     unsigned int range_start_char;
+     const char **p_ptr, *pend;
+     RE_TRANSLATE_TYPE translate;
+     reg_syntax_t syntax;
+     unsigned char *b;
 {
   unsigned this_char;
 
   const char *p = *p_ptr;
-  int range_start, range_end;
+  reg_errcode_t ret;
+  char range_start[2];
+  char range_end[2];
+  char ch[2];
 
   if (p == pend)
     return REG_ERANGE;
 
-  /* Even though the pattern is a signed `char *', we need to fetch
-     with unsigned char *'s; if the high bit of the pattern character
-     is set, the range endpoints will be negative if we fetch using a
-     signed char *.
-
-     We also want to fetch the endpoints without translating them; the
+  /* Fetch the endpoints without translating them; the
      appropriate translation is done in the bit-setting loop below.  */
-  /* The SVR4 compiler on the 3B2 had trouble with unsigned const char *.  */
-  range_start = ((const unsigned char *) p)[-2];
-  range_end   = ((const unsigned char *) p)[0];
+  range_start[0] = range_start_char;
+  range_start[1] = '\0';
+  range_end[0] = p[0];
+  range_end[1] = '\0';
 
   /* Have to increment the pointer into the pattern string, so the
      caller isn't still at the ending character.  */
   (*p_ptr)++;
 
-  /* If the start is after the end, the range is empty.  */
-  if (range_start > range_end)
-    return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+  /* Report an error if the range is empty and the syntax prohibits this.  */
+  ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
 
   /* Here we see why `this_char' has to be larger than an `unsigned
-     char' -- the range is inclusive, so if `range_end' == 0xff
-     (assuming 8-bit characters), we would otherwise go into an infinite
-     loop, since all characters <= 0xff.  */
-  for (this_char = range_start; this_char <= range_end; this_char++)
+     char' -- we would otherwise go into an infinite loop, since all
+     characters <= 0xff.  */
+  ch[1] = '\0';
+  for (this_char = 0; this_char <= (unsigned char) -1; ++this_char)
     {
-      SET_LIST_BIT (TRANSLATE (this_char));
+      ch[0] = this_char;
+      if (strcoll (range_start, ch) <= 0 && strcoll (ch, range_end) <= 0)
+       {
+         SET_LIST_BIT (TRANSLATE (this_char));
+         ret = REG_NOERROR;
+       }
     }
 
-  return REG_NOERROR;
+  return ret;
 }
 \f
 /* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
@@ -2904,18 +3571,15 @@ re_compile_fastmap (bufp)
 #ifndef REGEX_MALLOC
   char *destination;
 #endif
-  /* We don't push any register information onto the failure stack.  */
-  unsigned num_regs = 0;
 
   register char *fastmap = bufp->fastmap;
   unsigned char *pattern = bufp->buffer;
-  unsigned long size = bufp->used;
   unsigned char *p = pattern;
-  register unsigned char *pend = pattern + size;
+  register unsigned char *pend = pattern + bufp->used;
 
+#ifdef REL_ALLOC
   /* This holds the pointer to the failure stack, when
      it is allocated relocatably.  */
-#ifdef REL_ALLOC
   fail_stack_elt_t *failure_stack_ptr;
 #endif
 
@@ -3185,6 +3849,9 @@ re_compile_fastmap (bufp)
   RESET_FAIL_STACK ();
   return 0;
 } /* re_compile_fastmap */
+#ifdef _LIBC
+weak_alias (__re_compile_fastmap, re_compile_fastmap)
+#endif
 \f
 /* Set REGS to hold NUM_REGS registers, storing them in STARTS and
    ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
@@ -3220,6 +3887,9 @@ re_set_registers (bufp, regs, num_regs, starts, ends)
       regs->start = regs->end = (regoff_t *) 0;
     }
 }
+#ifdef _LIBC
+weak_alias (__re_set_registers, re_set_registers)
+#endif
 \f
 /* Searching routines.  */
 
@@ -3236,6 +3906,9 @@ re_search (bufp, string, size, startpos, range, regs)
   return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
                      regs, size);
 }
+#ifdef _LIBC
+weak_alias (__re_search, re_search)
+#endif
 
 
 /* Using the compiled pattern in BUFP->buffer, first tries to match the
@@ -3289,7 +3962,11 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
 
   /* If the search isn't to be a backwards one, don't waste time in a
      search for a pattern that must be anchored.  */
-  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
+  if (bufp->used > 0 && range > 0
+      && ((re_opcode_t) bufp->buffer[0] == begbuf
+         /* `begline' is like `begbuf' if it cannot match at newlines.  */
+         || ((re_opcode_t) bufp->buffer[0] == begline
+             && !bufp->newline_anchor)))
     {
       if (startpos > 0)
        return -1;
@@ -3365,9 +4042,9 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
       val = re_match_2_internal (bufp, string1, size1, string2, size2,
                                 startpos, regs, stop);
 #ifndef REGEX_MALLOC
-#ifdef C_ALLOCA
+# ifdef C_ALLOCA
       alloca (0);
-#endif
+# endif
 #endif
 
       if (val >= 0)
@@ -3392,14 +4069,10 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
     }
   return -1;
 } /* re_search_2 */
+#ifdef _LIBC
+weak_alias (__re_search_2, re_search_2)
+#endif
 \f
-/* Declarations and macros for re_match_2.  */
-
-static int bcmp_translate ();
-static boolean alt_match_null_string_p (),
-               common_op_match_null_string_p (),
-               group_match_null_string_p ();
-
 /* This converts PTR, a pointer into one of the search strings `string1'
    and `string2' into an offset from the beginning of that string.  */
 #define POINTER_TO_OFFSET(ptr)                 \
@@ -3440,17 +4113,19 @@ static boolean alt_match_null_string_p (),
            : (d) == string2 - 1 ? *(end1 - 1) : *(d))                  \
    == Sword)
 
+/* Disabled due to a compiler bug -- see comment at case wordbound */
+#if 0
 /* Test if the character before D and the one at D differ with respect
    to being word-constituent.  */
 #define AT_WORD_BOUNDARY(d)                                            \
   (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)                            \
    || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
-
+#endif
 
 /* Free everything we malloc.  */
 #ifdef MATCH_MAY_ALLOCATE
-#define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
-#define FREE_VARIABLES()                                               \
+# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL
+# define FREE_VARIABLES()                                              \
   do {                                                                 \
     REGEX_FREE_STACK (fail_stack.stack);                               \
     FREE_VAR (regstart);                                               \
@@ -3464,7 +4139,7 @@ static boolean alt_match_null_string_p (),
     FREE_VAR (reg_info_dummy);                                         \
   } while (0)
 #else
-#define FREE_VARIABLES() ((void)0) /* Do nothing!  But inhibit gcc warning.  */
+# define FREE_VARIABLES() ((void)0) /* Do nothing!  But inhibit gcc warning. */
 #endif /* not MATCH_MAY_ALLOCATE */
 
 /* These values must meet several constraints.  They must not be valid
@@ -3491,11 +4166,29 @@ re_match (bufp, string, size, pos, regs)
 {
   int result = re_match_2_internal (bufp, NULL, 0, string, size,
                                    pos, regs, size);
+# ifndef REGEX_MALLOC
+#  ifdef C_ALLOCA
   alloca (0);
+#  endif
+# endif
   return result;
 }
+# ifdef _LIBC
+weak_alias (__re_match, re_match)
+# endif
 #endif /* not emacs */
 
+static boolean group_match_null_string_p _RE_ARGS ((unsigned char **p,
+                                                   unsigned char *end,
+                                               register_info_type *reg_info));
+static boolean alt_match_null_string_p _RE_ARGS ((unsigned char *p,
+                                                 unsigned char *end,
+                                               register_info_type *reg_info));
+static boolean common_op_match_null_string_p _RE_ARGS ((unsigned char **p,
+                                                       unsigned char *end,
+                                               register_info_type *reg_info));
+static int bcmp_translate _RE_ARGS ((const char *s1, const char *s2,
+                                    int len, char *translate));
 
 /* re_match_2 matches the compiled pattern in BUFP against the
    the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
@@ -3521,9 +4214,16 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
 {
   int result = re_match_2_internal (bufp, string1, size1, string2, size2,
                                    pos, regs, stop);
+#ifndef REGEX_MALLOC
+# ifdef C_ALLOCA
   alloca (0);
+# endif
+#endif
   return result;
 }
+#ifdef _LIBC
+weak_alias (__re_match_2, re_match_2)
+#endif
 
 /* This is a separate function so that we can force an alloca cleanup
    afterwards.  */
@@ -3574,24 +4274,24 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
   fail_stack_type fail_stack;
 #endif
 #ifdef DEBUG
-  static unsigned failure_id = 0;
+  static unsigned failure_id;
   unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
 #endif
 
+#ifdef REL_ALLOC
   /* This holds the pointer to the failure stack, when
      it is allocated relocatably.  */
-#ifdef REL_ALLOC
   fail_stack_elt_t *failure_stack_ptr;
 #endif
 
   /* We fill all the registers internally, independent of what we
      return, for use in backreferences.  The number here includes
      an element for register zero.  */
-  unsigned num_regs = bufp->re_nsub + 1;
+  size_t num_regs = bufp->re_nsub + 1;
 
   /* The currently active registers.  */
-  unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
-  unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+  active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+  active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG;
 
   /* Information on the contents of registers. These are pointers into
      the input strings; they record just what was matched (on this
@@ -3705,7 +4405,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
   /* Initialize subexpression text positions to -1 to mark ones that no
      start_memory/stop_memory has been seen for. Also initialize the
      register information struct.  */
-  for (mcnt = 1; mcnt < num_regs; mcnt++)
+  for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
     {
       regstart[mcnt] = regend[mcnt]
         = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
@@ -3757,7 +4457,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
       dend = end_match_2;
     }
 
-  DEBUG_PRINT1 ("The compiled pattern is: ");
+  DEBUG_PRINT1 ("The compiled pattern is:\n");
   DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
   DEBUG_PRINT1 ("The string to match is: `");
   DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
@@ -3768,7 +4468,11 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
      fails at this starting point in the input data.  */
   for (;;)
     {
+#ifdef _LIBC
+      DEBUG_PRINT2 ("\n%p: ", p);
+#else
       DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
 
       if (p == pend)
        { /* End of pattern means we might have succeeded.  */
@@ -3805,7 +4509,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
 
                       DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
 
-                      for (mcnt = 1; mcnt < num_regs; mcnt++)
+                      for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
                         {
                           best_regstart[mcnt] = regstart[mcnt];
                           best_regend[mcnt] = regend[mcnt];
@@ -3831,7 +4535,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                   dend = ((d >= string1 && d <= end1)
                           ? end_match_1 : end_match_2);
 
-                 for (mcnt = 1; mcnt < num_regs; mcnt++)
+                 for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++)
                    {
                      regstart[mcnt] = best_regstart[mcnt];
                      regend[mcnt] = best_regend[mcnt];
@@ -3896,7 +4600,8 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
 
               /* Go through the first `min (num_regs, regs->num_regs)'
                  registers, since that is all we initialized.  */
-             for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++)
+             for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs);
+                  mcnt++)
                {
                   if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
                     regs->start[mcnt] = regs->end[mcnt] = -1;
@@ -3914,7 +4619,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                  we (re)allocated the registers, this is the case,
                  because we always allocate enough to have at least one
                  -1 at the end.  */
-              for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
+              for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++)
                 regs->start[mcnt] = regs->end[mcnt] = -1;
            } /* regs && !bufp->no_sub */
 
@@ -4186,7 +4891,8 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                       EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
 
                      /* Restore this and inner groups' (if any) registers.  */
-                      for (r = *p; r < *p + *(p + 1); r++)
+                      for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1);
+                          r++)
                         {
                           regstart[r] = old_regstart[r];
 
@@ -4262,7 +4968,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                    past them.  */
                if (translate
                     ? bcmp_translate (d, d2, mcnt, translate)
-                    : bcmp (d, d2, mcnt))
+                    : memcmp (d, d2, mcnt))
                  goto fail;
                d += mcnt, d2 += mcnt;
 
@@ -4345,7 +5051,11 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
           DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
 
           EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+          DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt);
+#else
           DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+#endif
 
           PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
           break;
@@ -4368,7 +5078,11 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
           DEBUG_PRINT1 ("EXECUTING on_failure_jump");
 
           EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+          DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt);
+#else
           DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+#endif
 
           /* If this on_failure_jump comes right before a group (i.e.,
              the original * applied to a group), save the information
@@ -4491,19 +5205,15 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
              }
             else if ((re_opcode_t) *p2 == charset)
              {
-#ifdef DEBUG
-               register unsigned char c
-                  = *p2 == (unsigned char) endline ? '\n' : p2[2];
-#endif
-
+               /* We win if the first character of the loop is not part
+                   of the charset.  */
                 if ((re_opcode_t) p1[3] == exactn
-                   && ! ((int) p2[1] * BYTEWIDTH > (int) p1[4]
-                         && (p2[1 + p1[4] / BYTEWIDTH]
-                             & (1 << (p1[4] % BYTEWIDTH)))))
-                  {
-                   p[-3] = (unsigned char) pop_failure_jump;
-                    DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
-                                  c, p1[5]);
+                   && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
+                         && (p2[2 + p1[5] / BYTEWIDTH]
+                             & (1 << (p1[5] % BYTEWIDTH)))))
+                 {
+                   p[-3] = (unsigned char) pop_failure_jump;
+                   DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
                   }
 
                else if ((re_opcode_t) p1[3] == charset_not)
@@ -4565,7 +5275,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                actual values.  Otherwise, we will restore only one
                register from the stack, since lowest will == highest in
                `pop_failure_point'.  */
-            unsigned dummy_low_reg, dummy_high_reg;
+            active_reg_t dummy_low_reg, dummy_high_reg;
             unsigned char *pdummy;
             const char *sdummy;
 
@@ -4574,16 +5284,26 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                                dummy_low_reg, dummy_high_reg,
                                reg_dummy, reg_dummy, reg_info_dummy);
           }
-          /* Note fall through.  */
+         /* Note fall through.  */
 
+       unconditional_jump:
+#ifdef _LIBC
+         DEBUG_PRINT2 ("\n%p: ", p);
+#else
+         DEBUG_PRINT2 ("\n0x%x: ", p);
+#endif
+          /* Note fall through.  */
 
         /* Unconditionally jump (without popping any failure points).  */
         case jump:
-       unconditional_jump:
          EXTRACT_NUMBER_AND_INCR (mcnt, p);    /* Get the amount to jump.  */
           DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
          p += mcnt;                            /* Do the jump.  */
+#ifdef _LIBC
+          DEBUG_PRINT2 ("(to %p).\n", p);
+#else
           DEBUG_PRINT2 ("(to 0x%x).\n", p);
+#endif
          break;
 
 
@@ -4603,7 +5323,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
           DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
           /* It doesn't matter what we push for the string here.  What
              the code at `fail' tests is the value for the pattern.  */
-          PUSH_FAILURE_POINT (0, 0, -2);
+          PUSH_FAILURE_POINT (NULL, NULL, -2);
           goto unconditional_jump;
 
 
@@ -4616,7 +5336,7 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
           DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
           /* See comments just above at `dummy_failure_jump' about the
              two zeroes.  */
-          PUSH_FAILURE_POINT (0, 0, -2);
+          PUSH_FAILURE_POINT (NULL, NULL, -2);
           break;
 
         /* Have to succeed matching what follows at least n times.
@@ -4632,11 +5352,19 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                mcnt--;
               p += 2;
                STORE_NUMBER_AND_INCR (p, mcnt);
-               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p, mcnt);
+#ifdef _LIBC
+               DEBUG_PRINT3 ("  Setting %p to %d.\n", p - 2, mcnt);
+#else
+               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p - 2, mcnt);
+#endif
             }
          else if (mcnt == 0)
             {
+#ifdef _LIBC
+              DEBUG_PRINT2 ("  Setting two bytes from %p to no_op.\n", p+2);
+#else
               DEBUG_PRINT2 ("  Setting two bytes from 0x%x to no_op.\n", p+2);
+#endif
              p[2] = (unsigned char) no_op;
               p[3] = (unsigned char) no_op;
               goto on_failure;
@@ -4652,6 +5380,11 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
             {
                mcnt--;
                STORE_NUMBER (p + 2, mcnt);
+#ifdef _LIBC
+               DEBUG_PRINT3 ("  Setting %p to %d.\n", p + 2, mcnt);
+#else
+               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p + 2, mcnt);
+#endif
               goto unconditional_jump;
             }
           /* If don't have to jump any more, skip over the rest of command.  */
@@ -4666,22 +5399,63 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
             EXTRACT_NUMBER_AND_INCR (mcnt, p);
             p1 = p + mcnt;
             EXTRACT_NUMBER_AND_INCR (mcnt, p);
+#ifdef _LIBC
+            DEBUG_PRINT3 ("  Setting %p to %d.\n", p1, mcnt);
+#else
             DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p1, mcnt);
+#endif
            STORE_NUMBER (p1, mcnt);
             break;
           }
 
-        case wordbound:
-          DEBUG_PRINT1 ("EXECUTING wordbound.\n");
-          if (AT_WORD_BOUNDARY (d))
+#if 0
+       /* The DEC Alpha C compiler 3.x generates incorrect code for the
+          test  WORDCHAR_P (d - 1) != WORDCHAR_P (d)  in the expansion of
+          AT_WORD_BOUNDARY, so this code is disabled.  Expanding the
+          macro and introducing temporary variables works around the bug.  */
+
+       case wordbound:
+         DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+         if (AT_WORD_BOUNDARY (d))
            break;
-          goto fail;
+         goto fail;
 
        case notwordbound:
-          DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+         DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
          if (AT_WORD_BOUNDARY (d))
            goto fail;
-          break;
+         break;
+#else
+       case wordbound:
+       {
+         boolean prevchar, thischar;
+
+         DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+         if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+           break;
+
+         prevchar = WORDCHAR_P (d - 1);
+         thischar = WORDCHAR_P (d);
+         if (prevchar != thischar)
+           break;
+         goto fail;
+       }
+
+      case notwordbound:
+       {
+         boolean prevchar, thischar;
+
+         DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+         if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d))
+           goto fail;
+
+         prevchar = WORDCHAR_P (d - 1);
+         thischar = WORDCHAR_P (d);
+         if (prevchar != thischar)
+           goto fail;
+         break;
+       }
+#endif
 
        case wordbeg:
           DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
@@ -5081,11 +5855,12 @@ common_op_match_null_string_p (p, end, reg_info)
 
 static int
 bcmp_translate (s1, s2, len, translate)
-     unsigned char *s1, *s2;
+     const char *s1, *s2;
      register int len;
      RE_TRANSLATE_TYPE translate;
 {
-  register unsigned char *p1 = s1, *p2 = s2;
+  register const unsigned char *p1 = (const unsigned char *) s1;
+  register const unsigned char *p2 = (const unsigned char *) s2;
   while (len)
     {
       if (translate[*p1++] != translate[*p2++]) return 1;
@@ -5108,7 +5883,7 @@ bcmp_translate (s1, s2, len, translate)
 const char *
 re_compile_pattern (pattern, length, bufp)
      const char *pattern;
-     int length;
+     size_t length;
      struct re_pattern_buffer *bufp;
 {
   reg_errcode_t ret;
@@ -5129,18 +5904,27 @@ re_compile_pattern (pattern, length, bufp)
 
   if (!ret)
     return NULL;
-  return gettext (re_error_msgid[(int) ret]);
+  return gettext (re_error_msgid + re_error_msgid_idx[(int) ret]);
 }
+#ifdef _LIBC
+weak_alias (__re_compile_pattern, re_compile_pattern)
+#endif
 \f
 /* Entry points compatible with 4.2 BSD regex library.  We don't define
    them unless specifically requested.  */
 
-#ifdef _REGEX_RE_COMP
+#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 below without link errors.  */
+weak_function
+#endif
 re_comp (s)
     const char *s;
 {
@@ -5157,12 +5941,14 @@ re_comp (s)
     {
       re_comp_buf.buffer = (unsigned char *) malloc (200);
       if (re_comp_buf.buffer == NULL)
-        return gettext (re_error_msgid[(int) REG_ESPACE]);
+        return (char *) gettext (re_error_msgid
+                                + re_error_msgid_idx[(int) REG_ESPACE]);
       re_comp_buf.allocated = 200;
 
       re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
       if (re_comp_buf.fastmap == NULL)
-       return gettext (re_error_msgid[(int) REG_ESPACE]);
+       return (char *) gettext (re_error_msgid
+                                + re_error_msgid_idx[(int) REG_ESPACE]);
     }
 
   /* Since `re_exec' always passes NULL for the `regs' argument, we
@@ -5177,11 +5963,14 @@ re_comp (s)
     return NULL;
 
   /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
-  return (char *) gettext (re_error_msgid[(int) ret]);
+  return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) ret]);
 }
 
 
 int
+#ifdef _LIBC
+weak_function
+#endif
 re_exec (s)
     const char *s;
 {
@@ -5189,6 +5978,7 @@ re_exec (s)
   return
     0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
 }
+
 #endif /* _REGEX_RE_COMP */
 \f
 /* POSIX.2 functions.  Don't define these for Emacs.  */
@@ -5206,7 +5996,8 @@ re_exec (s)
        REG_EXTENDED bit in CFLAGS is set; otherwise, to
        RE_SYNTAX_POSIX_BASIC;
      `newline_anchor' to REG_NEWLINE being set in CFLAGS;
-     `fastmap' and `fastmap_accurate' to zero;
+     `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.
@@ -5236,7 +6027,7 @@ regcomp (preg, pattern, cflags)
     int cflags;
 {
   reg_errcode_t ret;
-  unsigned syntax
+  reg_syntax_t syntax
     = (cflags & REG_EXTENDED) ?
       RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
 
@@ -5245,11 +6036,8 @@ regcomp (preg, pattern, cflags)
   preg->allocated = 0;
   preg->used = 0;
 
-  /* Don't bother to use a fastmap when searching.  This simplifies the
-     REG_NEWLINE case: if we used a fastmap, we'd have to put all the
-     characters after newlines into the fastmap.  This way, we just try
-     every character.  */
-  preg->fastmap = 0;
+  /* Try to allocate space for the fastmap.  */
+  preg->fastmap = (char *) malloc (1 << BYTEWIDTH);
 
   if (cflags & REG_ICASE)
     {
@@ -5263,7 +6051,7 @@ regcomp (preg, pattern, cflags)
 
       /* Map uppercase characters to corresponding lowercase ones.  */
       for (i = 0; i < CHAR_SET_SIZE; i++)
-        preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
+        preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i;
     }
   else
     preg->translate = NULL;
@@ -5289,8 +6077,24 @@ regcomp (preg, pattern, cflags)
      unmatched close-group: both are REG_EPAREN.  */
   if (ret == REG_ERPAREN) ret = REG_EPAREN;
 
+  if (ret == REG_NOERROR && preg->fastmap)
+    {
+      /* Compute the fastmap now, since regexec cannot modify the pattern
+        buffer.  */
+      if (re_compile_fastmap (preg) == -2)
+       {
+         /* Some error occurred while computing the fastmap, just forget
+            about it.  */
+         free (preg->fastmap);
+         preg->fastmap = NULL;
+       }
+    }
+
   return (int) ret;
 }
+#ifdef _LIBC
+weak_alias (__regcomp, regcomp)
+#endif
 
 
 /* regexec searches for a given pattern, specified by PREG, in the
@@ -5334,10 +6138,10 @@ regexec (preg, string, nmatch, pmatch, eflags)
   if (want_reg_info)
     {
       regs.num_regs = nmatch;
-      regs.start = TALLOC (nmatch, regoff_t);
-      regs.end = TALLOC (nmatch, regoff_t);
-      if (regs.start == NULL || regs.end == NULL)
+      regs.start = TALLOC (nmatch * 2, regoff_t);
+      if (regs.start == NULL)
         return (int) REG_NOMATCH;
+      regs.end = regs.start + nmatch;
     }
 
   /* Perform the searching operation.  */
@@ -5361,12 +6165,14 @@ regexec (preg, string, nmatch, pmatch, eflags)
 
       /* If we needed the temporary register info, free the space now.  */
       free (regs.start);
-      free (regs.end);
     }
 
   /* We want zero return to mean success, unlike `re_search'.  */
   return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
 }
+#ifdef _LIBC
+weak_alias (__regexec, regexec)
+#endif
 
 
 /* Returns a message corresponding to an error code, ERRCODE, returned
@@ -5383,14 +6189,15 @@ regerror (errcode, preg, errbuf, errbuf_size)
   size_t msg_size;
 
   if (errcode < 0
-      || errcode >= (sizeof (re_error_msgid) / sizeof (re_error_msgid[0])))
+      || errcode >= (int) (sizeof (re_error_msgid_idx)
+                          / sizeof (re_error_msgid_idx[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[errcode]);
+  msg = gettext (re_error_msgid + re_error_msgid_idx[errcode]);
 
   msg_size = strlen (msg) + 1; /* Includes the null.  */
 
@@ -5398,15 +6205,22 @@ regerror (errcode, preg, errbuf, errbuf_size)
     {
       if (msg_size > errbuf_size)
         {
-          strncpy (errbuf, msg, errbuf_size - 1);
+#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
-        strcpy (errbuf, msg);
+        memcpy (errbuf, msg, msg_size);
     }
 
   return msg_size;
 }
+#ifdef _LIBC
+weak_alias (__regerror, regerror)
+#endif
 
 
 /* Free dynamically allocated space used by PREG.  */
@@ -5431,13 +6245,8 @@ regfree (preg)
     free (preg->translate);
   preg->translate = NULL;
 }
+#ifdef _LIBC
+weak_alias (__regfree, regfree)
+#endif
 
 #endif /* not emacs  */
-\f
-/*
-Local variables:
-make-backup-files: t
-version-control: t
-trim-versions-without-asking: nil
-End:
-*/