changeset 389:1abea4b3d539

update from FSF
author Jim Meyering <jim@meyering.net>
date Thu, 16 Feb 1995 20:25:54 +0000
parents dcce129e8c8e
children db1c109d898d
files lib/regex.c lib/regex.h
diffstat 2 files changed, 146 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/lib/regex.c
+++ b/lib/regex.c
@@ -33,6 +33,14 @@
 /* We need this for `regex.h', and perhaps for the Emacs include files.  */
 #include <sys/types.h>
 
+/* This is for other GNU distributions with internationalized messages.
+   The GNU C Library itself does not yet support such messages.  */
+#if HAVE_LIBINTL_H
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
 /* The `emacs' switch turns on certain matching commands
    that make sense only in Emacs. */
 #ifdef emacs
@@ -41,9 +49,6 @@
 #include "buffer.h"
 #include "syntax.h"
 
-/* Emacs uses `NULL' as a predicate.  */
-#undef NULL
-
 #else  /* not emacs */
 
 #ifdef STDC_HEADERS
@@ -81,6 +86,12 @@
 #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;
@@ -267,6 +278,9 @@
 {
   no_op = 0,
 
+  /* Succeed right away--no more backtracking.  */
+  succeed,
+
         /* Followed by one byte giving n, then by n literal bytes.  */
   exactn,
 
@@ -495,8 +509,6 @@
   if (debug) print_double_string (w, s1, sz1, s2, sz2)
 
 
-extern void printchar ();
-
 /* Print the fastmap in human-readable form.  */
 
 void
@@ -511,7 +523,7 @@
       if (fastmap[i++])
 	{
 	  was_a_range = 0;
-          printchar (i - 1);
+          putchar (i - 1);
           while (i < (1 << BYTEWIDTH)  &&  fastmap[i])
             {
               was_a_range = 1;
@@ -520,7 +532,7 @@
 	  if (was_a_range)
             {
               printf ("-");
-              printchar (i - 1);
+              putchar (i - 1);
             }
         }
     }
@@ -563,7 +575,7 @@
           do
 	    {
               putchar ('/');
-	      printchar (*p++);
+	      putchar (*p++);
             }
           while (--mcnt);
           break;
@@ -610,18 +622,18 @@
 		  /* Have we broken a range?  */
 		  else if (last + 1 != c && in_range)
               {
-		      printchar (last);
+		      putchar (last);
 		      in_range = 0;
 		    }
                 
 		  if (! in_range)
-		    printchar (c);
+		    putchar (c);
 
 		  last = c;
               }
 
 	    if (in_range)
-	      printchar (last);
+	      putchar (last);
 
 	    putchar (']');
 
@@ -806,13 +818,13 @@
       if (FIRST_STRING_P (where))
         {
           for (this_char = where - string1; this_char < size1; this_char++)
-            printchar (string1[this_char]);
+            putchar (string1[this_char]);
 
           where = string2;    
         }
 
       for (this_char = where - string2; this_char < size2; this_char++)
-        printchar (string2[this_char]);
+        putchar (string2[this_char]);
     }
 }
 
@@ -834,7 +846,9 @@
 /* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
    also be assigned to arbitrarily: each pattern buffer stores its own
    syntax, so it can be changed between regex compilations.  */
-reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
+/* This has no initializer because initialized variables in Emacs
+   become read-only after dumping.  */
+reg_syntax_t re_syntax_options;
 
 
 /* Specify the precise syntax of regexps for compilation.  This provides
@@ -855,10 +869,12 @@
 }
 
 /* This table gives an error message for each of the error codes listed
-   in regex.h.  Obviously the order here has to be same as there.  */
-
-static const char *re_error_msg[] =
-  { NULL,					/* REG_NOERROR */
+   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 */
@@ -993,15 +1009,11 @@
     : ((fail_stack).stack[(fail_stack).avail++] = pattern_op,		\
        1))
 
-/* This pushes an item onto the failure stack.  sizeof(ITEM) must be no
-   larger than sizeof (unsigned char *).  Assumes the variable `fail_stack'.
-   Probably should only be called from within `PUSH_FAILURE_POINT'.  */
+/* This pushes an item onto the failure stack.  Must be a four-byte
+   value.  Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
 #define PUSH_FAILURE_ITEM(item)						\
-  do									\
-    {									\
-      fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item;	\
-    }									\
-  while (0)								\
+  fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item
 
 /* The complement operation.  Assumes `fail_stack' is nonempty.  */
 #define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail]
@@ -1168,10 +1180,10 @@
   DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);			\
 									\
   /* Restore register info.  */						\
-  high_reg = (unsigned long) POP_FAILURE_ITEM ();			\
+  high_reg = (unsigned) POP_FAILURE_ITEM ();				\
   DEBUG_PRINT2 ("  Popping high active reg: %d\n", high_reg);		\
 									\
-  low_reg = (unsigned long) POP_FAILURE_ITEM ();			\
+  low_reg = (unsigned) POP_FAILURE_ITEM ();				\
   DEBUG_PRINT2 ("  Popping  low active reg: %d\n", low_reg);		\
 									\
   for (this_reg = high_reg; this_reg >= low_reg; this_reg--)		\
@@ -1188,6 +1200,7 @@
       DEBUG_PRINT2 ("      start: 0x%x\n", regstart[this_reg]);		\
     }									\
 									\
+  set_regs_matched_done = 0;						\
   DEBUG_STATEMENT (nfailure_points_popped++);				\
 } /* POP_FAILURE_POINT */
 
@@ -1228,22 +1241,24 @@
 /* Call this when have matched a real character; it sets `matched' flags
    for the subexpressions which we are currently inside.  Also records
    that those subexprs have matched.  */
-#define SET_REGS_MATCHED()						\
-  do									\
-    {									\
-      unsigned r;							\
-      for (r = lowest_active_reg; r <= highest_active_reg; r++)		\
-        {								\
-          MATCHED_SOMETHING (reg_info[r])				\
-            = EVER_MATCHED_SOMETHING (reg_info[r])			\
-            = 1;							\
-        }								\
-    }									\
-  while (0)
+#define SET_REGS_MATCHED()					\
+  if (!set_regs_matched_done)					\
+    {								\
+      unsigned r;						\
+      set_regs_matched_done = 1;				\
+      for (r = lowest_active_reg; r <= highest_active_reg; r++)	\
+        {							\
+          MATCHED_SOMETHING (reg_info[r])			\
+            = EVER_MATCHED_SOMETHING (reg_info[r])		\
+            = 1;						\
+        }							\
+    }								\
+  else
 
 
 /* Registers are set to a sentinel when they haven't yet matched.  */
-#define REG_UNSET_VALUE ((char *) -1)
+static char reg_unset_dummy;
+#define REG_UNSET_VALUE (&reg_unset_dummy)
 #define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
 
 
@@ -1551,7 +1566,7 @@
       unsigned debug_count;
       
       for (debug_count = 0; debug_count < size; debug_count++)
-        printchar (pattern[debug_count]);
+        putchar (pattern[debug_count]);
       putchar ('\n');
     }
 #endif /* DEBUG */
@@ -2474,6 +2489,11 @@
   if (!COMPILE_STACK_EMPTY) 
     FREE_STACK_RETURN (REG_EPAREN);
 
+  /* If we don't want backtracking, force success
+     the first time we reach the end of the compiled pattern.  */
+  if (syntax & RE_NO_POSIX_BACKTRACKING)
+    BUF_PUSH (succeed);
+
   free (compile_stack.stack);
 
   /* We have succeeded; set the length of the buffer.  */
@@ -2776,26 +2796,30 @@
   bufp->fastmap_accurate = 1;	    /* It will be when we're done.  */
   bufp->can_be_null = 0;
       
-  while (p != pend || !FAIL_STACK_EMPTY ())
+  while (1)
     {
-      if (p == pend)
-        {
-          bufp->can_be_null |= path_can_be_null;
-          
-          /* Reset for next path.  */
-          path_can_be_null = true;
-          
-          p = fail_stack.stack[--fail_stack.avail];
+      if (p == pend || *p == succeed)
+	{
+	  /* We have reached the (effective) end of pattern.  */
+	  if (!FAIL_STACK_EMPTY ())
+	    {
+	      bufp->can_be_null |= path_can_be_null;
+
+	      /* Reset for next path.  */
+	      path_can_be_null = true;
+
+	      p = fail_stack.stack[--fail_stack.avail];
+
+	      continue;
+	    }
+	  else
+	    break;
 	}
 
       /* We should never be about to go beyond the end of the pattern.  */
       assert (p < pend);
       
-#ifdef SWITCH_ENUM_BUG
-      switch ((int) ((re_opcode_t) *p++))
-#else
-      switch ((re_opcode_t) *p++)
-#endif
+      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
 	{
 
         /* I guess the idea here is to simply not bother with a fastmap
@@ -3460,6 +3484,9 @@
      and need to test it, it's not garbage.  */
   const char *match_end = NULL;
 
+  /* This helps SET_REGS_MATCHED avoid doing redundant work.  */
+  int set_regs_matched_done = 0;
+
   /* Used when we pop values we don't care about.  */
 #ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global.  */
   const char **reg_dummy;
@@ -3656,6 +3683,7 @@
                 }
             } /* d != end_match_2 */
 
+	succeed:
           DEBUG_PRINT1 ("Accepting match.\n");
 
           /* If caller wants register contents data back, do it.  */
@@ -3744,11 +3772,7 @@
         }
 
       /* Otherwise match next pattern command.  */
-#ifdef SWITCH_ENUM_BUG
-      switch ((int) ((re_opcode_t) *p++))
-#else
-      switch ((re_opcode_t) *p++)
-#endif
+      switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++))
 	{
         /* Ignore these.  Used to ignore the n of succeed_n's which
            currently have n == 0.  */
@@ -3756,6 +3780,9 @@
           DEBUG_PRINT1 ("EXECUTING no_op.\n");
           break;
 
+	case succeed:
+          DEBUG_PRINT1 ("EXECUTING succeed.\n");
+	  goto succeed;
 
         /* Match the next n pattern characters exactly.  The following
            byte in the pattern defines n, and the n bytes after that
@@ -3863,6 +3890,9 @@
 
           IS_ACTIVE (reg_info[*p]) = 1;
           MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+	  /* Clear this whenever we change the register activity status.  */
+	  set_regs_matched_done = 0;
           
           /* This is the new highest active register.  */
           highest_active_reg = *p;
@@ -3875,6 +3905,7 @@
           /* Move past the register number and inner group count.  */
           p += 2;
 	  just_past_start_mem = p;
+
           break;
 
 
@@ -3900,7 +3931,10 @@
 
           /* This register isn't active anymore.  */
           IS_ACTIVE (reg_info[*p]) = 0;
-          
+
+	  /* Clear this whenever we change the register activity status.  */
+	  set_regs_matched_done = 0;
+
           /* If this was the only register active, nothing is active
              anymore.  */
           if (lowest_active_reg == highest_active_reg)
@@ -3994,7 +4028,7 @@
                           regstart[r] = old_regstart[r];
 
                           /* xx why this test?  */
-                          if (old_regend[r] >= regstart[r])
+                          if ((int) old_regend[r] >= (int) regstart[r])
                             regend[r] = old_regend[r];
                         }     
                     }
@@ -4068,6 +4102,9 @@
                     : bcmp (d, d2, mcnt))
 		  goto fail;
 		d += mcnt, d2 += mcnt;
+
+		/* Do this because we've match some characters.  */
+		SET_REGS_MATCHED ();
 	      }
 	  }
 	  break;
@@ -4365,7 +4402,7 @@
                actual values.  Otherwise, we will restore only one
                register from the stack, since lowest will == highest in
                `pop_failure_point'.  */
-            unsigned long dummy_low_reg, dummy_high_reg;
+            unsigned dummy_low_reg, dummy_high_reg;
             unsigned char *pdummy;
             const char *sdummy;
 
@@ -4934,7 +4971,9 @@
   
   ret = regex_compile (pattern, length, re_syntax_options, bufp);
 
-  return re_error_msg[(int) ret];
+  if (!ret)
+    return NULL;
+  return gettext (re_error_msgid[(int) ret]);
 }     
 
 /* Entry points compatible with 4.2 BSD regex library.  We don't define
@@ -4954,7 +4993,7 @@
   if (!s)
     {
       if (!re_comp_buf.buffer)
-	return "No previous regular expression";
+	return gettext ("No previous regular expression");
       return 0;
     }
 
@@ -4962,12 +5001,12 @@
     {
       re_comp_buf.buffer = (unsigned char *) malloc (200);
       if (re_comp_buf.buffer == NULL)
-        return "Memory exhausted";
+        return gettext (re_error_msgid[(int) REG_ESPACE]);
       re_comp_buf.allocated = 200;
 
       re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
       if (re_comp_buf.fastmap == NULL)
-	return "Memory exhausted";
+	return gettext (re_error_msgid[(int) REG_ESPACE]);
     }
 
   /* Since `re_exec' always passes NULL for the `regs' argument, we
@@ -4978,8 +5017,11 @@
 
   ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
   
-  /* Yes, we're discarding `const' here.  */
-  return (char *) re_error_msg[(int) ret];
+  if (!ret)
+    return NULL;
+
+  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
+  return (char *) gettext (re_error_msgid[(int) ret]);
 }
 
 
@@ -5183,19 +5225,14 @@
   size_t msg_size;
 
   if (errcode < 0
-      || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0])))
+      || errcode >= (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.
        Dump core so we can fix it.  */
     abort ();
 
-  msg = re_error_msg[errcode];
-
-  /* POSIX doesn't require that we do anything in this case, but why
-     not be nice.  */
-  if (! msg)
-    msg = "Success";
+  msg = gettext (re_error_msgid[errcode]);
 
   msg_size = strlen (msg) + 1; /* Includes the null.  */
   
--- a/lib/regex.h
+++ b/lib/regex.h
@@ -1,7 +1,7 @@
 /* Definitions for data structures and routines for the regular
-   expression library, version 0.11.
+   expression library, version 0.12.
 
-   Copyright (C) 1985, 89, 90, 91, 92 Free Software Foundation, Inc.
+   Copyright (C) 1985, 89, 90, 91, 92, 1993 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -20,7 +20,15 @@
 #ifndef __REGEXP_LIBRARY_H__
 #define __REGEXP_LIBRARY_H__
 
-/* POSIX says that <sys/types.h> must be included before <regex.h>.  */
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+   <regex.h>.  */
+
+#ifdef VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+   should be there.  */
+#include <stddef.h>
+#endif
+
 
 /* The following bits are used to determine the regexp syntax we
    recognize.  The set/not-set meanings are chosen so that Emacs syntax
@@ -122,6 +130,10 @@
    If not set, then an unmatched ) is invalid.  */
 #define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
 
+/* If this bit is set, succeed as soon as we match the whole pattern,
+   without further backtracking.  */
+#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
+
 /* This global variable defines the particular regexp syntax to use (for
    some interfaces).  When a regexp is compiled, the syntax used is
    stored in the pattern buffer, so changing this does not affect
@@ -137,7 +149,7 @@
 #define RE_SYNTAX_AWK							\
   (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL			\
    | RE_NO_BK_PARENS            | RE_NO_BK_REFS				\
-   | RE_NO_BK_VAR               | RE_NO_EMPTY_RANGES			\
+   | RE_NO_BK_VBAR               | RE_NO_EMPTY_RANGES			\
    | RE_UNMATCHED_RIGHT_PAREN_ORD)
 
 #define RE_SYNTAX_POSIX_AWK 						\
@@ -157,6 +169,9 @@
 #define RE_SYNTAX_POSIX_EGREP						\
   (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
 
+/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */
+#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+
 #define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
 
 /* Syntax bits common to both basic and extended POSIX regex syntax.  */
@@ -311,12 +326,12 @@
 #define REGS_FIXED 2
   unsigned regs_allocated : 2;
 
-        /* Set to zero when regex_compile compiles a pattern; set to one
-           by re_compile_fastmap when it updates the fastmap, if any.  */
+        /* Set to zero when `regex_compile' compiles a pattern; set to one
+           by `re_compile_fastmap' if it updates the fastmap.  */
   unsigned fastmap_accurate : 1;
 
-        /* If set, regexec reports only success or failure and does not
-           return anything in pmatch.  */
+        /* If set, `re_match_2' does not return information about
+           subexpressions.  */
   unsigned no_sub : 1;
 
         /* If set, a beginning-of-line anchor doesn't match at the
@@ -333,11 +348,6 @@
 };
 
 typedef struct re_pattern_buffer regex_t;
-
-
-/* search.c (search_buffer) in Emacs needs this one opcode value.  It is
-   defined both in `regex.c' and here.  */
-#define RE_EXACTN_VALUE 1
 
 /* Type for byte offsets within the string.  POSIX mandates this.  */
 typedef int regoff_t;
@@ -376,19 +386,17 @@
    prototype (if we are ANSI), and once without (if we aren't) -- we
    use the following macro to declare argument types.  This
    unfortunately clutters up the declarations a bit, but I think it's
-   worth it.
-   
-   We also have to undo `const' if we are not ANSI and if it hasn't
-   previously being taken care of.  */
+   worth it.  */
 
 #if __STDC__
+
 #define _RE_ARGS(args) args
-#else
+
+#else /* not __STDC__ */
+
 #define _RE_ARGS(args) ()
-#ifndef const
-#define const
-#endif
-#endif
+
+#endif /* not __STDC__ */
 
 /* Sets the current default syntax to SYNTAX, and return the old syntax.
    You can also simply assign to the `re_syntax_options' variable.  */
@@ -456,9 +464,11 @@
   _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
              unsigned num_regs, regoff_t *starts, regoff_t *ends));
 
+#ifdef _REGEX_RE_COMP
 /* 4.2 bsd compatibility.  */
 extern char *re_comp _RE_ARGS ((const char *));
 extern int re_exec _RE_ARGS ((const char *));
+#endif
 
 /* POSIX compatibility.  */
 extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));