inspect: Don't assume number of captures in match functions
authorMatthew Booth <mbooth@redhat.com>
Tue, 18 Oct 2011 12:30:40 +0000 (13:30 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Wed, 19 Oct 2011 15:27:38 +0000 (16:27 +0100)
It is possible for the pcre library to return a variable number of captures for
a single regular expression. e.g.:

  ^/dev/(cciss/c\d+d\d+)(?:p(\d+))?$

This will return either 1 or 2 captures depending on whether the device has a
partition suffix. The current match wrappers don't allow for this, and require
that a predictable number of matches are returned.

This change updates match, match1, match2, and match3 to ignore the specific
number of matches returned. Instead, any returned captures are assigned to the
given arguments, and any remaining arguments are set to NULL.

src/match.c

index 68b2d4b..6038e41 100644 (file)
@@ -39,12 +39,6 @@ guestfs___match (guestfs_h *g, const char *str, const pcre *re)
   r = pcre_exec (re, NULL, str, len, 0, 0, vec, sizeof vec / sizeof vec[0]);
   if (r == PCRE_ERROR_NOMATCH)
     return 0;
-  if (r != 1) {
-    /* Internal error -- should not happen. */
-    warning (g, "%s: %s: pcre_exec returned unexpected error code %d when matching against the string \"%s\"\n",
-             __FILE__, __func__, r, str);
-    return 0;
-  }
 
   return 1;
 }
@@ -62,14 +56,8 @@ guestfs___match1 (guestfs_h *g, const char *str, const pcre *re)
   r = pcre_exec (re, NULL, str, len, 0, 0, vec, sizeof vec / sizeof vec[0]);
   if (r == PCRE_ERROR_NOMATCH)
     return NULL;
-  if (r != 2) {
-    /* Internal error -- should not happen. */
-    warning (g, "%s: %s: internal error: pcre_exec returned unexpected error code %d when matching against the string \"%s\"",
-             __FILE__, __func__, r, str);
-    return NULL;
-  }
 
-  return safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
+  return r == 2 ? safe_strndup (g, &str[vec[2]], vec[3]-vec[2]) : NULL;
 }
 
 /* Match a regular expression which contains exactly two captures. */
@@ -83,15 +71,12 @@ guestfs___match2 (guestfs_h *g, const char *str, const pcre *re,
   r = pcre_exec (re, NULL, str, len, 0, 0, vec, 30);
   if (r == PCRE_ERROR_NOMATCH)
     return 0;
-  if (r != 3) {
-    /* Internal error -- should not happen. */
-    warning (g, "%s: %s: internal error: pcre_exec returned unexpected error code %d when matching against the string \"%s\"",
-             __FILE__, __func__, r, str);
-    return 0;
-  }
 
-  *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
-  *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);
+  *ret1 = NULL;
+  *ret2 = NULL;
+
+  if (r > 1) *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
+  if (r > 2) *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);
 
   return 1;
 }
@@ -107,16 +92,14 @@ guestfs___match3 (guestfs_h *g, const char *str, const pcre *re,
   r = pcre_exec (re, NULL, str, len, 0, 0, vec, 30);
   if (r == PCRE_ERROR_NOMATCH)
     return 0;
-  if (r != 4) {
-    /* Internal error -- should not happen. */
-    warning (g, "%s: %s: internal error: pcre_exec returned unexpected error code %d when matching against the string \"%s\"",
-             __FILE__, __func__, r, str);
-    return 0;
-  }
 
-  *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
-  *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);
-  *ret3 = safe_strndup (g, &str[vec[6]], vec[7]-vec[6]);
+  *ret1 = NULL;
+  *ret2 = NULL;
+  *ret3 = NULL;
+
+  if (r > 1) *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
+  if (r > 2) *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);
+  if (r > 3) *ret3 = safe_strndup (g, &str[vec[6]], vec[7]-vec[6]);
 
   return 1;
 }