]> code.delx.au - gnu-emacs/blobdiff - src/regex.c
Merge from emacs--devo--0
[gnu-emacs] / src / regex.c
index 24574c5e5e866c3b990be22cffa81fb57f3f209b..a0d6b945cf1afdfd2c698bbafe74a2f439366841 100644 (file)
@@ -3,11 +3,12 @@
    internationalization features.)
 
    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
+                 2002, 2003, 2004, 2005, 2006, 2007
+                 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)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -311,7 +312,7 @@ enum syntaxcode { Swhitespace = 0, Sword = 1, Ssymbol = 2 };
 # define RE_STRING_CHAR(p, s, multibyte) STRING_CHAR ((p), (s))
 # define CHAR_STRING(c, s) (*(s) = (c), 1)
 # define STRING_CHAR_AND_LENGTH(p, s, actual_len) ((actual_len) = 1, *(p))
-# define RE_STRING_CHAR_AND_LENGTH(p, s, multibyte) STRING_CHAR_AND_LENGTH ((p), (s))
+# define RE_STRING_CHAR_AND_LENGTH(p, s, len, multibyte) STRING_CHAR_AND_LENGTH ((p), (s), (len))
 # define RE_CHAR_TO_MULTIBYTE(c) (c)
 # define RE_CHAR_TO_UNIBYTE(c) (c)
 # define GET_CHAR_BEFORE_2(c, p, str1, end1, str2, end2) \
@@ -1397,18 +1398,12 @@ static const char *re_error_msgid[] =
 /* Normally, this is fine.  */
 #define MATCH_MAY_ALLOCATE
 
-/* 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
-#endif
-
 /* The match routines may not allocate if (1) they would do it with malloc
    and (2) it's not safe for them to use malloc.
    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
+#if defined REGEX_MALLOC && defined emacs
 # undef MATCH_MAY_ALLOCATE
 #endif
 
@@ -2183,7 +2178,7 @@ re_wctype (str)
   else return 0;
 }
 
-/* True iff CH is in the char class CC.  */
+/* True if CH is in the char class CC.  */
 boolean
 re_iswctype (ch, cc)
      int ch;
@@ -2620,11 +2615,6 @@ regex_compile (pattern, size, syntax, bufp)
      last -- ends with a forward jump of this sort.  */
   unsigned char *fixup_alt_jump = 0;
 
-  /* Counts open-groups as they are encountered.  Remembered for the
-     matching close-group on the compile stack, so the same register
-     number is put in the stop_memory as the start_memory.  */
-  regnum_t regnum = 0;
-
   /* Work area for range table of charset.  */
   struct range_table_work_area range_table_work;
 
@@ -3276,28 +3266,54 @@ regex_compile (pattern, size, syntax, bufp)
            handle_open:
              {
                int shy = 0;
+               regnum_t regnum = 0;
                if (p+1 < pend)
                  {
                    /* Look for a special (?...) construct */
                    if ((syntax & RE_SHY_GROUPS) && *p == '?')
                      {
                        PATFETCH (c); /* Gobble up the '?'.  */
-                       PATFETCH (c);
-                       switch (c)
+                       while (!shy)
                          {
-                         case ':': shy = 1; break;
-                         default:
-                           /* Only (?:...) is supported right now. */
-                           FREE_STACK_RETURN (REG_BADPAT);
+                           PATFETCH (c);
+                           switch (c)
+                             {
+                             case ':': shy = 1; break;
+                             case '0':
+                               /* An explicitly specified regnum must start
+                                  with non-0. */
+                               if (regnum == 0)
+                                 FREE_STACK_RETURN (REG_BADPAT);
+                             case '1': case '2': case '3': case '4':
+                             case '5': case '6': case '7': case '8': case '9':
+                               regnum = 10*regnum + (c - '0'); break;
+                             default:
+                               /* Only (?:...) is supported right now. */
+                               FREE_STACK_RETURN (REG_BADPAT);
+                             }
                          }
                      }
                  }
 
                if (!shy)
-                 {
-                   bufp->re_nsub++;
-                   regnum++;
+                 regnum = ++bufp->re_nsub;
+               else if (regnum)
+                 { /* It's actually not shy, but explicitly numbered.  */
+                   shy = 0;
+                   if (regnum > bufp->re_nsub)
+                     bufp->re_nsub = regnum;
+                   else if (regnum > bufp->re_nsub
+                            /* Ideally, we'd want to check that the specified
+                               group can't have matched (i.e. all subgroups
+                               using the same regnum are in other branches of
+                               OR patterns), but we don't currently keep track
+                               of enough info to do that easily.  */
+                            || group_in_compile_stack (compile_stack, regnum))
+                     FREE_STACK_RETURN (REG_BADPAT);
                  }
+               else
+                 /* It's really shy.  */
+                 regnum = - bufp->re_nsub;
 
                if (COMPILE_STACK_FULL)
                  {
@@ -3316,12 +3332,11 @@ regex_compile (pattern, size, syntax, bufp)
                COMPILE_STACK_TOP.fixup_alt_jump
                  = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
                COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
-               COMPILE_STACK_TOP.regnum = shy ? -regnum : regnum;
+               COMPILE_STACK_TOP.regnum = regnum;
 
-               /* Do not push a
-                  start_memory for groups beyond the last one we can
-                  represent in the compiled pattern.  */
-               if (regnum <= MAX_REGNUM && !shy)
+               /* Do not push a start_memory for groups beyond the last one
+                  we can represent in the compiled pattern.  */
+               if (regnum <= MAX_REGNUM && regnum > 0)
                  BUF_PUSH_2 (start_memory, regnum);
 
                compile_stack.avail++;
@@ -3366,7 +3381,7 @@ regex_compile (pattern, size, syntax, bufp)
                /* We don't just want to restore into `regnum', because
                   later groups should continue to be numbered higher,
                   as in `(ab)c(de)' -- the second group is #2.  */
-               regnum_t this_group_regnum;
+               regnum_t regnum;
 
                compile_stack.avail--;
                begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
@@ -3375,7 +3390,7 @@ regex_compile (pattern, size, syntax, bufp)
                    ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
                    : 0;
                laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
-               this_group_regnum = COMPILE_STACK_TOP.regnum;
+               regnum = COMPILE_STACK_TOP.regnum;
                /* If we've reached MAX_REGNUM groups, then this open
                   won't actually generate any code, so we'll have to
                   clear pending_exact explicitly.  */
@@ -3383,8 +3398,8 @@ regex_compile (pattern, size, syntax, bufp)
 
                /* We're at the end of the group, so now we know how many
                   groups were inside this one.  */
-               if (this_group_regnum <= MAX_REGNUM && this_group_regnum > 0)
-                 BUF_PUSH_2 (stop_memory, this_group_regnum);
+               if (regnum <= MAX_REGNUM && regnum > 0)
+                 BUF_PUSH_2 (stop_memory, regnum);
              }
              break;
 
@@ -3710,8 +3725,9 @@ regex_compile (pattern, size, syntax, bufp)
 
                reg = c - '0';
 
-               /* Can't back reference to a subexpression before its end.  */
-               if (reg > regnum || group_in_compile_stack (compile_stack, reg))
+               if (reg > bufp->re_nsub || reg < 1
+                   /* Can't back reference to a subexp before its end.  */
+                   || group_in_compile_stack (compile_stack, reg))
                  FREE_STACK_RETURN (REG_ESUBREG);
 
                laststart = b;
@@ -4103,17 +4119,21 @@ analyse_first (p, pend, fastmap, multibyte)
            if (!!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) ^ not)
              fastmap[j] = 1;
 
-         if ((not && multibyte)
-             /* Any leading code can possibly start a character
+#ifdef emacs
+         if (/* Any leading code can possibly start a character
                 which doesn't match the specified set of characters.  */
-             || (CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
-                 && CHARSET_RANGE_TABLE_BITS (&p[-2]) != 0))
-           /* If we can match a character class, we can match
-              any multibyte characters.  */
+             not
+             || 
+             /* If we can match a character class, we can match any
+                multibyte characters.  */
+             (CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
+              && CHARSET_RANGE_TABLE_BITS (&p[-2]) != 0))
+
            {
              if (match_any_multibyte_characters == false)
                {
-                 for (j = 0x80; j < (1 << BYTEWIDTH); j++)
+                 for (j = MIN_MULTIBYTE_LEADING_CODE;
+                      j <= MAX_MULTIBYTE_LEADING_CODE; j++)
                    fastmap[j] = 1;
                  match_any_multibyte_characters = true;
                }
@@ -4145,6 +4165,7 @@ analyse_first (p, pend, fastmap, multibyte)
                    fastmap[j] = 1;
                }
            }
+#endif
          break;
 
        case syntaxspec:
@@ -4167,20 +4188,18 @@ analyse_first (p, pend, fastmap, multibyte)
          if (!fastmap) break;
          not = (re_opcode_t)p[-1] == notcategoryspec;
          k = *p++;
-         for (j = (multibyte ? 127 : (1 << BYTEWIDTH)); j >= 0; j--)
+         for (j = (1 << BYTEWIDTH); j >= 0; j--)
            if ((CHAR_HAS_CATEGORY (j, k)) ^ not)
              fastmap[j] = 1;
 
-         if (multibyte)
+         /* Any leading code can possibly start a character which
+            has or doesn't has the specified category.  */
+         if (match_any_multibyte_characters == false)
            {
-             /* Any character set can possibly contain a character
-                whose category is K (or not).  */
-             if (match_any_multibyte_characters == false)
-               {
-                 for (j = 0x80; j < (1 << BYTEWIDTH); j++)
-                   fastmap[j] = 1;
-                 match_any_multibyte_characters = true;
-               }
+             for (j = MIN_MULTIBYTE_LEADING_CODE;
+                  j <= MAX_MULTIBYTE_LEADING_CODE; j++)
+               fastmap[j] = 1;
+             match_any_multibyte_characters = true;
            }
          break;
 
@@ -4610,11 +4629,6 @@ re_search_2 (bufp, str1, size1, str2, size2, startpos, range, regs, stop)
 
       val = re_match_2_internal (bufp, string1, size1, string2, size2,
                                 startpos, regs, stop);
-#ifndef REGEX_MALLOC
-# ifdef C_ALLOCA
-      alloca (0);
-# endif
-#endif
 
       if (val >= 0)
        return startpos;
@@ -5051,9 +5065,6 @@ re_match (bufp, string, size, pos, regs)
 {
   int result = re_match_2_internal (bufp, NULL, 0, (re_char*) string, size,
                                    pos, regs, size);
-# if defined C_ALLOCA && !defined REGEX_MALLOC
-  alloca (0);
-# endif
   return result;
 }
 WEAK_ALIAS (__re_match, re_match)
@@ -5099,9 +5110,6 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
   result = re_match_2_internal (bufp, (re_char*) string1, size1,
                                (re_char*) string2, size2,
                                pos, regs, stop);
-#if defined C_ALLOCA && !defined REGEX_MALLOC
-  alloca (0);
-#endif
   return result;
 }
 WEAK_ALIAS (__re_match_2, re_match_2)