msvcrt_valisttos optimization (cmdline3)

Francois Gouget fgouget at free.fr
Sun Sep 2 21:53:51 CDT 2001



   First I checked that all of the _spawn and _exec class of functions
don't build the command line properly. That is, spawn("main","a b","c")
will build "main a b c" as the command line which is obviously
incorrect. This is the case with both VC5 and VC6, on Win95 and Win2000!
(see spawnv in cmdline-test.tar.gz, posted on wine-dev)

   But I had already started looking into the implementation of
msvcrt_argvtos and msvcrt_valisttos and I was surprised that it did not
put the final '\0'... until I realized that calloc is zeroing the whole
array. So this is why calloc was called rather than malloc, which is
pretty strange for something which one usually rather sees as a memory
region rather than an array of chars. But why zero-out the whole thing
just to overwrite all these zeroes 5 nanoseconds later?


Changelog:

 * dlls/msvcrt/process.c
   Rewrite msvcrt_{argvtos,valisttos} to be more efficient
   Warn about the ' ' and '"' handling of the exec and spawn functions
   Make msvcrt_spawn const correct


--
Francois Gouget         fgouget at free.fr        http://fgouget.free.fr/
  Good judgment comes from experience, and experience comes from bad judgment
                               -- Barry LePatner
-------------- next part --------------
Index: dlls/msvcrt/process.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/process.c,v
retrieving revision 1.7
diff -u -r1.7 process.c
--- dlls/msvcrt/process.c	2001/05/22 19:18:51	1.7
+++ dlls/msvcrt/process.c	2001/09/02 21:33:44
@@ -26,7 +26,7 @@
 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
 
 /* INTERNAL: Spawn a child process */
-static int msvcrt_spawn(int flags, const char* exe, char* args, char* env)
+static int msvcrt_spawn(int flags, const char* exe, const char* args, char* env)
 {
   STARTUPINFOA si;
   PROCESS_INFORMATION pi;
@@ -45,7 +45,7 @@
   memset(&si, 0, sizeof(si));
   si.cb = sizeof(si);
 
-  if (!CreateProcessA(exe, args, NULL, NULL, TRUE,
+  if (!CreateProcessA(exe, (char*)args, NULL, NULL, TRUE,
                      flags == _P_DETACH ? DETACHED_PROCESS : 0,
                      env, NULL, &si, &pi))
   {
@@ -75,76 +75,90 @@
   return -1; /* can't reach here */
 }
 
-/* INTERNAL: Convert argv list to a single 'delim'-separated string */
+/* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
+ * extra '\0' to terminate it
+ */
 static char* msvcrt_argvtos(const char* const* arg, char delim)
 {
-  const char* const* search = arg;
-  long size = 0;
-  char *ret;
+  const char* const* a;
+  long size;
+  char* p;
+  char* ret;
 
   if (!arg && !delim)
-    return NULL;
+  {
+      /* Return NULL for an empty environment list */
+      return NULL;
+  }
 
   /* get length */
-  while(*search)
+  a = arg;
+  size = 0;
+  while (*a)
   {
-    size += strlen(*search) + 1;
-    search++;
+    size += strlen(*a) + 1;
+    a++;
   }
 
-  if (!(ret = (char *)MSVCRT_calloc(size + 1, 1)))
+  ret = (char*)MSVCRT_malloc(size + 1);
+  if (!ret)
     return NULL;
 
   /* fill string */
-  search = arg;
-  size = 0;
-  while(*search)
+  a = arg;
+  p = ret;
+  while (*a)
   {
-    int strsize = strlen(*search);
-    memcpy(ret+size,*search,strsize);
-    ret[size+strsize] = delim;
-    size += strsize + 1;
-    search++;
+    int len = strlen(*a);
+    memcpy(ret+size,*a,len);
+    p += len;
+    *p++ = delim;
+    a++;
   }
+  *p='\0';
   return ret;
 }
 
-/* INTERNAL: Convert va_list to a single 'delim'-separated string */
-static char* msvcrt_valisttos(const char* arg0, va_list ap, char delim)
+/* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
+ * extra '\0' to terminate it
+ */
+static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
 {
-  va_list search = ap;
+  va_list alist2 = alist;
   long size;
-  char *arg;
+  const char *arg;
+  char* p;
   char *ret;
-  int strsize;
 
   if (!arg0 && !delim)
-    return NULL;
-
-  /* get length */
-  size = strlen(arg0) + 1;
-  while((arg = va_arg(search, char *)) != NULL)
   {
-    size += strlen(arg) + 1;
+      /* Return NULL for an empty environment list */
+      return NULL;
   }
 
-  if (!(ret = (char *)MSVCRT_calloc(size + 1, 1)))
+  /* get length */
+  arg = arg0;
+  size = 0;
+  do {
+      size += strlen(arg) + 1;
+      arg = va_arg(alist, char*);
+  } while (arg != NULL);
+
+  ret = (char*)MSVCRT_malloc(size + 1);
+  if (!ret)
     return NULL;
 
   /* fill string */
-  search = ap;
-  size = 0;
-  strsize = strlen(arg0);
-  memcpy(ret+size,arg0,strsize);
-  ret[size+strsize] = delim;
-  size += strsize + 1;
-  while((arg = va_arg(search, char *)) != NULL)
-  {
-    strsize = strlen(search);
-    memcpy(ret+size,search,strsize);
-    ret[size+strsize] = delim;
-    size += strsize + 1;
-  }
+  arg = arg0;
+  p = ret;
+  do {
+      int len = strlen(arg);
+      memcpy(p,arg,len);
+      p += len;
+      *p++ = delim;
+      arg = va_arg(alist2, char*);
+  } while (arg != NULL);
+  *p = '\0';
   return ret;
 }
 
@@ -183,6 +197,9 @@
 
 /*********************************************************************
  *		_execl (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _execl(const char* name, const char* arg0, ...)
 {
@@ -202,6 +219,9 @@
 
 /*********************************************************************
  *		_execlp (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _execlp(const char* name, const char* arg0, ...)
 {
@@ -224,6 +244,9 @@
 
 /*********************************************************************
  *		_execv (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _execv(const char* name, char* const* argv)
 {
@@ -232,6 +255,9 @@
 
 /*********************************************************************
  *		_execve (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _execve(const char* name, char* const* argv, const char* const* envv)
 {
@@ -240,6 +266,9 @@
 
 /*********************************************************************
  *		_execvpe (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _execvpe(const char* name, char* const* argv, const char* const* envv)
 {
@@ -252,6 +281,9 @@
 
 /*********************************************************************
  *		_execvp (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _execvp(const char* name, char* const* argv)
 {
@@ -260,6 +292,9 @@
 
 /*********************************************************************
  *		_spawnl (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _spawnl(int flags, const char* name, const char* arg0, ...)
 {
@@ -279,6 +314,9 @@
 
 /*********************************************************************
  *		_spawnlp (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _spawnlp(int flags, const char* name, const char* arg0, ...)
 {
@@ -301,6 +339,9 @@
 
 /*********************************************************************
  *		_spawnve (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _spawnve(int flags, const char* name, const char* const* argv,
                             const char* const* envv)
@@ -326,6 +367,9 @@
 
 /*********************************************************************
  *		_spawnv (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _spawnv(int flags, const char* name, const char* const* argv)
 {
@@ -334,6 +378,9 @@
 
 /*********************************************************************
  *		_spawnvpe (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _spawnvpe(int flags, const char* name, const char* const* argv,
                             const char* const* envv)
@@ -345,6 +392,9 @@
 
 /*********************************************************************
  *		_spawnvp (MSVCRT.@)
+ *
+ * Like on Windows, this function does not handle arguments with spaces 
+ * or double-quotes.
  */
 int _spawnvp(int flags, const char* name, const char* const* argv)
 {
@@ -357,7 +407,7 @@
 int MSVCRT_system(const char* cmd)
 {
   /* FIXME: should probably launch cmd interpreter in COMSPEC */
-  return msvcrt_spawn(_P_WAIT, cmd, NULL, NULL);
+  return msvcrt_spawn(_P_WAIT, NULL, (char*)cmd, NULL);
 }
 
 /*********************************************************************


More information about the wine-patches mailing list