system-quote: Refactor.
authorBruno Haible <bruno@clisp.org>
Thu, 10 May 2012 11:52:21 +0000 (13:52 +0200)
committerBruno Haible <bruno@clisp.org>
Thu, 10 May 2012 11:52:21 +0000 (13:52 +0200)
* lib/system-quote.h (system_quote_copy): Fix comment.
* lib/system-quote.c (windows_createprocess_quote, windows_cmd_quote):
New functions, extracted from system_quote_copy.
(system_quote_length, system_quote_copy): Use these functions.
Reported by Paul Eggert.

ChangeLog
lib/system-quote.c
lib/system-quote.h

index ba38632..29df987 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2012-05-10  Bruno Haible  <bruno@clisp.org>
+
+       system-quote: Refactor.
+       * lib/system-quote.h (system_quote_copy): Fix comment.
+       * lib/system-quote.c (windows_createprocess_quote, windows_cmd_quote):
+       New functions, extracted from system_quote_copy.
+       (system_quote_length, system_quote_copy): Use these functions.
+       Reported by Paul Eggert.
+
 2012-05-08  Bruno Haible  <bruno@clisp.org>
 
        execute, spawn-pipe: Escape '*' characters in arguments on Windows.
index facbea6..37a9ff4 100644 (file)
@@ -28,6 +28,7 @@
 #include "xalloc.h"
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
 /* The native Windows CreateProcess() function interprets characters like
    ' ', '\t', '\\', '"' (but not '<' and '>') in a special way:
    - Space and tab are interpreted as delimiters. They are not treated as
  */
 # define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037*"
 # define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+
+/* Copies the quoted string to p and returns the number of bytes needed.
+   If p is non-NULL, there must be room for system_quote_length (string)
+   bytes at p.  */
+static size_t
+windows_createprocess_quote (char *p, const char *string)
+{
+  size_t len = strlen (string);
+  bool quote_around =
+    (len == 0 || strpbrk (string, SHELL_SPECIAL_CHARS) != NULL);
+  size_t backslashes = 0;
+  size_t i = 0;
+# define STORE(c) \
+  do                 \
+    {                \
+      if (p != NULL) \
+        p[i] = (c);  \
+      i++;           \
+    }                \
+  while (0)
+
+  if (quote_around)
+    STORE ('"');
+  for (; len > 0; string++, len--)
+    {
+      char c = *string;
+
+      if (c == '"')
+        {
+          size_t j;
+
+          for (j = backslashes + 1; j > 0; j--)
+            STORE ('\\');
+        }
+      STORE (c);
+      if (c == '\\')
+        backslashes++;
+      else
+        backslashes = 0;
+    }
+  if (quote_around)
+    {
+      size_t j;
+
+      for (j = backslashes; j > 0; j--)
+        STORE ('\\');
+      STORE ('"');
+    }
+# undef STORE
+  return i;
+}
+
 /* The native Windows cmd.exe command interpreter also interprets:
    - '\n', '\r' as a command terminator - no way to escape it,
    - '<', '>' as redirections,
  */
 # define CMD_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037!%&'*+,;<=>[]^`{|}~"
 # define CMD_FORBIDDEN_CHARS "\n\r"
+
+/* Copies the quoted string to p and returns the number of bytes needed.
+   If p is non-NULL, there must be room for system_quote_length (string)
+   bytes at p.  */
+static size_t
+windows_cmd_quote (char *p, const char *string)
+{
+  size_t len = strlen (string);
+  bool quote_around =
+    (len == 0 || strpbrk (string, CMD_SPECIAL_CHARS) != NULL);
+  size_t backslashes = 0;
+  size_t i = 0;
+# define STORE(c) \
+  do                 \
+    {                \
+      if (p != NULL) \
+        p[i] = (c);  \
+      i++;           \
+    }                \
+  while (0)
+
+  if (quote_around)
+    STORE ('"');
+  for (; len > 0; string++, len--)
+    {
+      char c = *string;
+
+      if (c == '"')
+        {
+          size_t j;
+
+          for (j = backslashes + 1; j > 0; j--)
+            STORE ('\\');
+        }
+      if (c == '%')
+        {
+          size_t j;
+
+          for (j = backslashes; j > 0; j--)
+            STORE ('\\');
+          STORE ('"');
+        }
+      STORE (c);
+      if (c == '%')
+        STORE ('"');
+      if (c == '\\')
+        backslashes++;
+      else
+        backslashes = 0;
+    }
+  if (quote_around)
+    {
+      size_t j;
+
+      for (j = backslashes; j > 0; j--)
+        STORE ('\\');
+      STORE ('"');
+    }
+  return i;
+}
+
 #endif
 
 size_t
@@ -77,59 +191,11 @@ system_quote_length (enum system_command_interpreter interpreter,
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
     case SCI_WINDOWS_CREATEPROCESS:
-      {
-        size_t len = strlen (string);
-        bool quote_around =
-          (len == 0 || strpbrk (string, SHELL_SPECIAL_CHARS) != NULL);
-        size_t backslashes = 0;
-        size_t length = len;
-
-        if (quote_around)
-          length++;
-        for (; len > 0; string++, len--)
-          {
-            char c = *string;
-
-            if (c == '"')
-              length += backslashes + 1;
-            if (c == '\\')
-              backslashes++;
-            else
-              backslashes = 0;
-          }
-        if (quote_around)
-          length += backslashes + 1;
-        return length;
-      }
+      return windows_createprocess_quote (NULL, string);
 
     case SCI_SYSTEM:
     case SCI_WINDOWS_CMD:
-      {
-        size_t len = strlen (string);
-        bool quote_around =
-          (len == 0 || strpbrk (string, CMD_SPECIAL_CHARS) != NULL);
-        size_t backslashes = 0;
-        size_t length = len;
-
-        if (quote_around)
-          length++;
-        for (; len > 0; string++, len--)
-          {
-            char c = *string;
-
-            if (c == '"')
-              length += backslashes + 1;
-            if (c == '%')
-              length += backslashes + 2;
-            if (c == '\\')
-              backslashes++;
-            else
-              backslashes = 0;
-          }
-        if (quote_around)
-          length += backslashes + 1;
-        return length;
-      }
+      return windows_cmd_quote (NULL, string);
 #endif
 
     default:
@@ -153,91 +219,15 @@ system_quote_copy (char *p,
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
     case SCI_WINDOWS_CREATEPROCESS:
-      {
-        size_t len = strlen (string);
-        bool quote_around =
-          (len == 0 || strpbrk (string, SHELL_SPECIAL_CHARS) != NULL);
-        size_t backslashes = 0;
-
-        if (quote_around)
-          *p++ = '"';
-        for (; len > 0; string++, len--)
-          {
-            char c = *string;
-
-            if (c == '"')
-              {
-                size_t j;
-
-                for (j = backslashes + 1; j > 0; j--)
-                  *p++ = '\\';
-              }
-            *p++ = c;
-            if (c == '\\')
-              backslashes++;
-            else
-              backslashes = 0;
-          }
-        if (quote_around)
-          {
-            size_t j;
-
-            for (j = backslashes; j > 0; j--)
-              *p++ = '\\';
-            *p++ = '"';
-          }
-        *p = '\0';
-        return p;
-      }
+      p += windows_createprocess_quote (p, string);
+      *p = '\0';
+      return p;
 
     case SCI_SYSTEM:
     case SCI_WINDOWS_CMD:
-      {
-        size_t len = strlen (string);
-        bool quote_around =
-          (len == 0 || strpbrk (string, CMD_SPECIAL_CHARS) != NULL);
-        size_t backslashes = 0;
-
-        if (quote_around)
-          *p++ = '"';
-        for (; len > 0; string++, len--)
-          {
-            char c = *string;
-
-            if (c == '"')
-              {
-                size_t j;
-
-                for (j = backslashes + 1; j > 0; j--)
-                  *p++ = '\\';
-              }
-            if (c == '%')
-              {
-                size_t j;
-
-                for (j = backslashes; j > 0; j--)
-                  *p++ = '\\';
-                *p++ = '"';
-              }
-            *p++ = c;
-            if (c == '%')
-              *p++ = '"';
-            if (c == '\\')
-              backslashes++;
-            else
-              backslashes = 0;
-          }
-        if (quote_around)
-          {
-            size_t j;
-
-            for (j = backslashes; j > 0; j--)
-              *p++ = '\\';
-            *p++ = '"';
-          }
-        *p = '\0';
-        return p;
-      }
+      p += windows_cmd_quote (p, string);
+      *p = '\0';
+      return p;
 #endif
 
     default:
index c2c50c5..d5f2978 100644 (file)
@@ -58,7 +58,7 @@ extern size_t
                             const char *string);
 
 /* Copies the quoted string to p and returns the incremented p.
-   There must be room for shell_quote_length (string) + 1 bytes at p.  */
+   There must be room for system_quote_length (string) + 1 bytes at p.  */
 extern char *
        system_quote_copy (char *p,
                           enum system_command_interpreter interpreter,