[Cmake-commits] [cmake-commits] king committed SharedForward.h.in 1.9 1.10

cmake-commits at cmake.org cmake-commits at cmake.org
Fri Sep 26 08:24:27 EDT 2008


Update of /cvsroot/CMake/CMake/Source/kwsys
In directory public:/mounts/ram/cvs-serv22571/Source/kwsys

Modified Files:
	SharedForward.h.in 
Log Message:
BUG: Fix SharedForward with spaces on windows

The windows execvp function does not re-escape arguments correctly.
Instead we generate the escape sequences before calling it.


Index: SharedForward.h.in
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/kwsys/SharedForward.h.in,v
retrieving revision 1.9
retrieving revision 1.10
diff -C 2 -d -r1.9 -r1.10
*** SharedForward.h.in	26 Sep 2008 12:24:20 -0000	1.9
--- SharedForward.h.in	26 Sep 2008 12:24:25 -0000	1.10
***************
*** 158,161 ****
--- 158,162 ----
  # include <windows.h>
  # include <process.h>
+ # define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
  #else
  # include <unistd.h>
***************
*** 270,273 ****
--- 271,414 ----
  #endif
  
+ #ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
+ /*--------------------------------------------------------------------------*/
+ typedef struct kwsys_sf_arg_info_s
+ {
+   const char* arg;
+   int size;
+   int quote;
+ } kwsys_sf_arg_info;
+ 
+ /*--------------------------------------------------------------------------*/
+ static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in)
+ {
+   /* Initialize information.  */
+   kwsys_sf_arg_info info;
+ 
+   /* String iterator.  */
+   const char* c;
+ 
+   /* Keep track of how many backslashes have been encountered in a row.  */
+   int windows_backslashes = 0;
+ 
+   /* Start with the length of the original argument, plus one for
+      either a terminating null or a separating space.  */
+   info.arg = in;
+   info.size = (int)strlen(in) + 1;
+   info.quote = 0;
+ 
+   /* Scan the string for characters that require escaping or quoting.  */
+   for(c=in; *c; ++c)
+     {
+     /* Check whether this character needs quotes.  */
+     if(strchr(" \t?'#&<>|^", *c))
+       {
+       info.quote = 1;
+       }
+ 
+     /* On Windows only backslashes and double-quotes need escaping.  */
+     if(*c == '\\')
+       {
+       /* Found a backslash.  It may need to be escaped later.  */
+       ++windows_backslashes;
+       }
+     else if(*c == '"')
+       {
+       /* Found a double-quote.  We need to escape it and all
+          immediately preceding backslashes.  */
+       info.size += windows_backslashes + 1;
+       windows_backslashes = 0;
+       }
+     else
+       {
+       /* Found another character.  This eliminates the possibility
+          that any immediately preceding backslashes will be
+          escaped.  */
+       windows_backslashes = 0;
+       }
+     }
+ 
+   /* Check whether the argument needs surrounding quotes.  */
+   if(info.quote)
+     {
+     /* Surrounding quotes are needed.  Allocate space for them.  */
+     info.size += 2;
+ 
+     /* We must escape all ending backslashes when quoting on windows.  */
+     info.size += windows_backslashes;
+     }
+ 
+   return info;
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+ static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
+ {
+   /* String iterator.  */
+   const char* c;
+ 
+   /* Keep track of how many backslashes have been encountered in a row.  */
+   int windows_backslashes = 0;
+ 
+   /* Whether the argument must be quoted.  */
+   if(info.quote)
+     {
+     /* Add the opening quote for this argument.  */
+     *out++ = '"';
+     }
+ 
+   /* Scan the string for characters that require escaping or quoting.  */
+   for(c=info.arg; *c; ++c)
+     {
+     /* On Windows only backslashes and double-quotes need escaping.  */
+     if(*c == '\\')
+       {
+       /* Found a backslash.  It may need to be escaped later.  */
+       ++windows_backslashes;
+       }
+     else if(*c == '"')
+       {
+       /* Found a double-quote.  Escape all immediately preceding
+          backslashes.  */
+       while(windows_backslashes > 0)
+         {
+         --windows_backslashes;
+         *out++ = '\\';
+         }
+ 
+       /* Add the backslash to escape the double-quote.  */
+       *out++ = '\\';
+       }
+     else
+       {
+       /* We encountered a normal character.  This eliminates any
+          escaping needed for preceding backslashes.  */
+       windows_backslashes = 0;
+       }
+ 
+     /* Store this character.  */
+     *out++ = *c;
+     }
+ 
+   if(info.quote)
+     {
+     /* Add enough backslashes to escape any trailing ones.  */
+     while(windows_backslashes > 0)
+       {
+       --windows_backslashes;
+       *out++ = '\\';
+       }
+ 
+     /* Add the closing quote for this argument.  */
+     *out++ = '"';
+     }
+ 
+   /* Store a terminating null without incrementing.  */
+   *out = 0;
+ 
+   return out;
+ }
+ #endif
+ 
  /*--------------------------------------------------------------------------*/
  /* Function to convert a logical or relative path to a physical full path.  */
***************
*** 342,347 ****
  /*--------------------------------------------------------------------------*/
  /* Functions to execute a child process.  */
! static void kwsys_shared_forward_execvp(const char* cmd, char* const argv[])
  {
  #if defined(_MSC_VER)
    _execvp(cmd, argv);
--- 483,514 ----
  /*--------------------------------------------------------------------------*/
  /* Functions to execute a child process.  */
! static void kwsys_shared_forward_execvp(const char* cmd, char* const* argv)
  {
+ #ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
+   /* Count the number of arguments.  */
+   int argc = 0;
+   {
+   char* const* argvc;
+   for(argvc = argv; *argvc; ++argvc,++argc) {}
+   }
+ 
+   /* Create the escaped arguments.  */
+   {
+   char** nargv = (char**)malloc((argc+1) * sizeof(char*));
+   int i;
+   for(i=0; i < argc; ++i)
+     {
+     kwsys_sf_arg_info info = kwsys_sf_get_arg_info(argv[i]);
+     nargv[i] = (char*)malloc(info.size);
+     kwsys_sf_get_arg(info, nargv[i]);
+     }
+   nargv[argc] = 0;
+ 
+   /* Replace the command line to be used.  */
+   argv = nargv;
+   }
+ #endif
+ 
+   /* Invoke the child process.  */
  #if defined(_MSC_VER)
    _execvp(cmd, argv);



More information about the Cmake-commits mailing list