.
[gnulib.git] / lib / regex.c
index 63189b2..202eef6 100644 (file)
@@ -1,23 +1,28 @@
 /* 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, 1994, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   the C library, however.  The master source lives in /gd/gnu/lib.
 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+NOTE: The canonical source of this file is maintained with the 
+GNU C Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
 
-   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.  */
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software Foundation, 
+Inc., 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)
 #include <config.h>
 #endif
 
+#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>
+#endif
+
+/* For platform which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+# include <wctype.h>
+# include <wchar.h>
+#endif
 
 /* This is for other GNU distributions with internationalized messages.  */
 #if HAVE_LIBINTL_H || defined (_LIBC)
@@ -496,6 +512,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;
@@ -523,6 +540,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;
@@ -607,6 +626,7 @@ print_partial_compiled_pattern (start, end)
     unsigned char *end;
 {
   int mcnt, mcnt2;
+  unsigned char *p1;
   unsigned char *p = start;
   unsigned char *pend = end;
 
@@ -748,20 +768,23 @@ print_partial_compiled_pattern (start, end)
 
         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);
+         printf ("/succeed_n to %d, %d times", p1 - start, mcnt2);
           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);
+         printf ("/set_number_at location %d to %d", p1 - start, mcnt2);
           break;
 
         case wordbound:
@@ -839,7 +862,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)
     {
@@ -854,7 +878,7 @@ print_compiled_pattern (bufp)
   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?  */
 }
 
@@ -867,7 +891,7 @@ print_double_string (where, string1, size1, string2, size2)
     int size1;
     int size2;
 {
-  unsigned this_char;
+  int this_char;
 
   if (where == NULL)
     printf ("(null)");
@@ -886,6 +910,13 @@ print_double_string (where, string1, size1, string2, size2)
     }
 }
 
+void
+printchar (c)
+     int c;
+{
+  putc (c, stderr);
+}
+
 #else /* not DEBUG */
 
 #undef assert
@@ -923,6 +954,12 @@ 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;
 }
 \f
@@ -1003,10 +1040,40 @@ static const char *re_error_msgid[] =
 #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.  */
+
+#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;
@@ -1027,6 +1094,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)
@@ -1067,7 +1136,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,                    \
@@ -1117,7 +1186,7 @@ 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_POP(item_addr) (item_addr)->integer = POP_FAILURE_INT ()
 #else
 #define DEBUG_PUSH(item)
 #define DEBUG_POP(item_addr)
@@ -1138,7 +1207,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 */                                                  \
+    s_reg_t this_reg;                                                  \
                                                                        \
     DEBUG_STATEMENT (failure_id++);                                    \
     DEBUG_STATEMENT (nfailure_points_pushed++);                                \
@@ -1194,7 +1266,7 @@ typedef struct
     DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);\
     PUSH_FAILURE_INT (highest_active_reg);                             \
                                                                        \
-    DEBUG_PRINT2 ("  Pushing pattern 0x%x: ", pattern_place);          \
+    DEBUG_PRINT2 ("  Pushing pattern 0x%x:\n", pattern_place);         \
     DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);          \
     PUSH_FAILURE_POINTER (pattern_place);                              \
                                                                        \
@@ -1220,7 +1292,10 @@ typedef struct
 #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                              \
@@ -1248,7 +1323,7 @@ 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;                                                                \
+  s_reg_t this_reg;                                                    \
   const unsigned char *string_temp;                                    \
                                                                        \
   assert (!FAIL_STACK_EMPTY ());                                       \
@@ -1275,14 +1350,14 @@ typedef struct
   DEBUG_PRINT1 ("'\n");                                                        \
                                                                        \
   pat = (unsigned char *) POP_FAILURE_POINTER ();                      \
-  DEBUG_PRINT2 ("  Popping pattern 0x%x: ", pat);                      \
+  DEBUG_PRINT2 ("  Popping pattern 0x%x:\n", pat);                     \
   DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);                      \
                                                                        \
   /* Restore register info.  */                                                \
-  high_reg = (unsigned) POP_FAILURE_INT ();                            \
+  high_reg = (active_reg_t) POP_FAILURE_INT ();                                \
   DEBUG_PRINT2 ("  Popping high active reg: %d\n", high_reg);          \
                                                                        \
-  low_reg = (unsigned) POP_FAILURE_INT ();                             \
+  low_reg = (active_reg_t) POP_FAILURE_INT ();                         \
   DEBUG_PRINT2 ("  Popping  low active reg: %d\n", low_reg);           \
                                                                        \
   if (1)                                                               \
@@ -1327,6 +1402,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;
@@ -1356,7 +1434,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++)     \
            {                                                           \
@@ -1375,11 +1453,25 @@ 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 ((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
@@ -1421,7 +1513,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.  */
@@ -1454,26 +1546,39 @@ 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.  */
+/* 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
@@ -1487,7 +1592,7 @@ static reg_errcode_t compile_range ();
     bufp->allocated <<= 1;                                             \
     if (bufp->allocated > MAX_BUF_SIZE)                                        \
       bufp->allocated = MAX_BUF_SIZE;                                  \
-    bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
+    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.  */         \
@@ -1519,7 +1624,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
 {
@@ -1571,15 +1677,29 @@ typedef struct
        }                                                               \
     }
 
-#define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* 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
+
+# define IS_CHAR_CLASS(string) wctype (string)
+#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
 
@@ -1629,6 +1749,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.
 
@@ -1654,7 +1778,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;
 {
@@ -2053,6 +2177,34 @@ regex_compile (pattern, size, syntax, bufp)
                        the leading `:' and `[' (but set bits for them).  */
                     if (c == ':' && *p == ']')
                       {
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+                        boolean is_lower = STREQ (str, "lower");
+                        boolean is_upper = STREQ (str, "upper");
+                       wctype_t wt;
+                        int ch;
+
+                       wt = wctype (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)
+                         {
+                           if (iswctype (btowc (ch), wt))
+                             SET_LIST_BIT (ch);
+
+                           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");
@@ -2095,8 +2247,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
                       {
@@ -2520,38 +2676,54 @@ regex_compile (pattern, size, syntax, bufp)
 
 
             case 'w':
+             if (re_syntax_options & RE_NO_GNU_OPS)
+               goto normal_char;
               laststart = b;
               BUF_PUSH (wordchar);
               break;
 
 
             case 'W':
+             if (re_syntax_options & RE_NO_GNU_OPS)
+               goto normal_char;
               laststart = b;
               BUF_PUSH (notwordchar);
               break;
 
 
             case '<':
+             if (re_syntax_options & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (wordbeg);
               break;
 
             case '>':
+             if (re_syntax_options & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (wordend);
               break;
 
             case 'b':
+             if (re_syntax_options & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (wordbound);
               break;
 
             case 'B':
+             if (re_syntax_options & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (notwordbound);
               break;
 
             case '`':
+             if (re_syntax_options & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (begbuf);
               break;
 
             case '\'':
+             if (re_syntax_options & RE_NO_GNU_OPS)
+               goto normal_char;
               BUF_PUSH (endbuf);
               break;
 
@@ -2566,7 +2738,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;
@@ -2793,7 +2965,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 == '\\';
@@ -2850,7 +3022,7 @@ compile_range (p_ptr, pend, translate, syntax, b)
   unsigned this_char;
 
   const char *p = *p_ptr;
-  int range_start, range_end;
+  unsigned int range_start, range_end;
 
   if (p == pend)
     return REG_ERANGE;
@@ -2915,13 +3087,12 @@ re_compile_fastmap (bufp)
 
   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
 
@@ -3399,13 +3570,6 @@ re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
   return -1;
 } /* re_search_2 */
 \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)                 \
@@ -3499,11 +3663,26 @@ 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;
 }
 #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
@@ -3529,7 +3708,11 @@ 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;
 }
 
@@ -3586,20 +3769,20 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
   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
@@ -3713,7 +3896,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;
@@ -3765,7 +3948,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);
@@ -3776,7 +3959,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.  */
@@ -3813,7 +4000,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];
@@ -3839,7 +4026,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];
@@ -3904,7 +4091,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;
@@ -3922,7 +4110,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 */
 
@@ -4194,7 +4382,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];
 
@@ -4353,7 +4542,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;
@@ -4376,7 +4569,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
@@ -4504,10 +4701,17 @@ re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop)
                   = *p2 == (unsigned char) endline ? '\n' : p2[2];
 #endif
 
+#if 0
+                if ((re_opcode_t) p1[3] == exactn
+                   && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5]
+                         && (p2[2 + p1[5] / BYTEWIDTH]
+                             & (1 << (p1[5] % BYTEWIDTH)))))
+#else
                 if ((re_opcode_t) p1[3] == exactn
                    && ! ((int) p2[1] * BYTEWIDTH > (int) p1[4]
-                         && (p2[1 + p1[4] / BYTEWIDTH]
+                         && (p2[2 + p1[4] / BYTEWIDTH]
                              & (1 << (p1[4] % BYTEWIDTH)))))
+#endif
                   {
                    p[-3] = (unsigned char) pop_failure_jump;
                     DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
@@ -4573,7 +4777,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;
 
@@ -4582,16 +4786,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;
 
 
@@ -4640,11 +4854,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;
@@ -4660,6 +4882,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.  */
@@ -4674,7 +4901,11 @@ 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;
           }
@@ -5126,11 +5357,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;
@@ -5153,7 +5385,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;
@@ -5180,12 +5412,18 @@ re_compile_pattern (pattern, length, bufp)
 /* 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;
 {
@@ -5227,6 +5465,9 @@ re_comp (s)
 
 
 int
+#ifdef _LIBC
+weak_function
+#endif
 re_exec (s)
     const char *s;
 {
@@ -5234,6 +5475,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.  */
@@ -5281,7 +5523,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;
 
@@ -5428,7 +5670,8 @@ 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)
+                          / sizeof (re_error_msgid[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.
@@ -5478,11 +5721,3 @@ regfree (preg)
 }
 
 #endif /* not emacs  */
-\f
-/*
-Local variables:
-make-backup-files: t
-version-control: t
-trim-versions-without-asking: nil
-End:
-*/