(savedir): Work even if directory size is
[gnulib.git] / regex.c
diff --git a/regex.c b/regex.c
index 3cf8a13..09f56a1 100644 (file)
--- a/regex.c
+++ b/regex.c
@@ -2,7 +2,7 @@
    0.12.  (Implements POSIX draft P10003.2/D11.2, except for
    internationalization features.)
 
-   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 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
@@ -2168,6 +2168,7 @@ regex_compile (pattern, size, syntax, bufp)
 
            /* 1 means zero (many) matches is allowed.  */
            char zero_times_ok = 0, many_times_ok = 0;
+           char greedy = 1;
 
            /* If there is a sequence of repetition chars, collapse it
               down to just one (the right one).  We can't combine
@@ -2176,8 +2177,14 @@ regex_compile (pattern, size, syntax, bufp)
 
            for (;;)
              {
-               zero_times_ok |= c != '+';
-               many_times_ok |= c != '?';
+               if (!(syntax & RE_ALL_GREEDY)
+                   && c == '?' && (zero_times_ok || many_times_ok))
+                 greedy = 0;
+               else
+                 {
+                   zero_times_ok |= c != '+';
+                   many_times_ok |= c != '?';
+                 }
 
                if (p == pend)
                  break;
@@ -2218,6 +2225,8 @@ regex_compile (pattern, size, syntax, bufp)
 
            /* Now we know whether or not zero matches is allowed
               and also whether or not two or more matches is allowed.  */
+           if (greedy)
+             {
            if (many_times_ok)
              { /* More than one repetition is allowed, so put in at the
                   end a backward relative jump from `b' to before the next
@@ -2276,7 +2285,39 @@ regex_compile (pattern, size, syntax, bufp)
                INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
                b += 3;
              }
-           }
+
+             }
+           else                /* not greedy */
+             { /* I wish the greedy and non-greedy cases could be merged. */
+
+               if (many_times_ok)
+                 {
+                   /* The greedy multiple match looks like a repeat..until:
+                      we only need a conditional jump at the end of the loop */
+                   GET_BUFFER_SPACE (3);
+                   STORE_JUMP (on_failure_jump, b, laststart);
+                   b += 3;
+                   if (zero_times_ok)
+                     {
+                       /* The repeat...until naturally matches one or more.
+                          To also match zero times, we need to first jump to
+                          the end of the loop (its conditional jump). */
+                       GET_BUFFER_SPACE (3);
+                       INSERT_JUMP (jump, laststart, b);
+                       b += 3;
+                     }
+                 }
+               else
+                 {
+                   /* non-greedy a?? */
+                   GET_BUFFER_SPACE (6);
+                   INSERT_JUMP (jump, laststart, b + 3);
+                   b += 3;
+                   INSERT_JUMP (on_failure_jump, laststart, laststart + 6);
+                   b += 3;
+                 }
+             }
+         }
          break;
 
 
@@ -3110,8 +3151,8 @@ regex_compile (pattern, size, syntax, bufp)
 #ifdef emacs
          if (! SINGLE_BYTE_CHAR_P (c))
            {
-             unsigned char work[4], *str;
-             int i = CHAR_STRING (c, work, str);
+             unsigned char str[MAX_MULTIBYTE_LENGTH];
+             int i = CHAR_STRING (c, str);
              int j;
              for (j = 0; j < i; j++)
                {
@@ -3493,8 +3534,9 @@ re_compile_fastmap (bufp)
                 multibyte character in the range table. */
              int c, count;
 
-             /* Make P points the range table. */
-             p += CHARSET_BITMAP_SIZE (&p[-2]);
+             /* Make P points the range table.  `+ 2' is to skip flag
+                 bits for a character class.  */
+             p += CHARSET_BITMAP_SIZE (&p[-2]) + 2;
 
              /* Extract the number of ranges in range table into COUNT.  */
              EXTRACT_NUMBER_AND_INCR (count, p);