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