summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2006-06-15 18:40:42 (GMT)
committerBrad King <brad.king@kitware.com>2006-06-15 18:40:42 (GMT)
commit6438bec4c9355960f47e4b853f27b548a55ec5e0 (patch)
tree9580881b94fa12d7201875fbf5cc30194d3d7d1f /Source
parent6071052835552a7dbdf7bd4f38263c6f206b26dd (diff)
downloadCMake-6438bec4c9355960f47e4b853f27b548a55ec5e0.zip
CMake-6438bec4c9355960f47e4b853f27b548a55ec5e0.tar.gz
CMake-6438bec4c9355960f47e4b853f27b548a55ec5e0.tar.bz2
ENH: Added Option_Verbatim to run whole command lines directly.
Diffstat (limited to 'Source')
-rw-r--r--Source/kwsys/Process.h.in12
-rw-r--r--Source/kwsys/ProcessUNIX.c327
-rw-r--r--Source/kwsys/ProcessWin32.c361
3 files changed, 517 insertions, 183 deletions
diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in
index 96d3225..3d2db7b 100644
--- a/Source/kwsys/Process.h.in
+++ b/Source/kwsys/Process.h.in
@@ -36,6 +36,7 @@
#define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
#define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
#define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
+#define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim)
#define kwsysProcess_GetOption kwsys_ns(Process_GetOption)
#define kwsysProcess_SetOption kwsys_ns(Process_SetOption)
#define kwsysProcess_Option_e kwsys_ns(Process_Option_e)
@@ -154,6 +155,13 @@ kwsysEXPORT void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe,
* kwsysProcess_Option_HideWindow = Whether to hide window on Windows.
* 0 = No (default)
* 1 = Yes
+ *
+ * kwsysProcess_Option_Verbatim = Whether SetCommand and AddCommand
+ * should treat the first argument
+ * as a verbatim command line
+ * and ignore the rest of the arguments.
+ * 0 = No (default)
+ * 1 = Yes
*/
kwsysEXPORT int kwsysProcess_GetOption(kwsysProcess* cp, int optionId);
kwsysEXPORT void kwsysProcess_SetOption(kwsysProcess* cp, int optionId,
@@ -161,7 +169,8 @@ kwsysEXPORT void kwsysProcess_SetOption(kwsysProcess* cp, int optionId,
enum kwsysProcess_Option_e
{
kwsysProcess_Option_HideWindow,
- kwsysProcess_Option_Detach
+ kwsysProcess_Option_Detach,
+ kwsysProcess_Option_Verbatim
};
/**
@@ -343,6 +352,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
# undef kwsysProcess_SetPipeShared
# undef kwsysProcess_Option_Detach
# undef kwsysProcess_Option_HideWindow
+# undef kwsysProcess_Option_Verbatim
# undef kwsysProcess_GetOption
# undef kwsysProcess_SetOption
# undef kwsysProcess_Option_e
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index 49b939e..03ecc26 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -60,6 +60,7 @@ do.
#include <time.h> /* gettimeofday */
#include <signal.h> /* sigaction */
#include <dirent.h> /* DIR, dirent */
+#include <ctype.h> /* isspace */
/* The number of pipes for the child's output. The standard stdout
and stderr pipes are the first two. One more pipe is used to
@@ -122,6 +123,7 @@ static int kwsysProcessesAdd(kwsysProcess* cp);
static void kwsysProcessesRemove(kwsysProcess* cp);
static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
void* ucontext);
+static char** kwsysProcessParseVerbatimCommand(const char* command);
/*--------------------------------------------------------------------------*/
/* Structure containing data used to implement the child's execution. */
@@ -159,6 +161,9 @@ struct kwsysProcess_s
/* Whether the child was created as a detached process. */
int Detached;
+ /* Whether to treat command lines as verbatim. */
+ int Verbatim;
+
/* Time at which the child started. Negative for no timeout. */
kwsysProcessTime StartTime;
@@ -309,7 +314,7 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
char*** newCommands;
/* Make sure we have a command to add. */
- if(!cp || !command)
+ if(!cp || !command || !*command)
{
return 0;
}
@@ -332,39 +337,54 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
}
/* Add the new command. */
- {
- char const* const* c = command;
- int n = 0;
- int i = 0;
- while(*c++);
- n = c - command - 1;
- newCommands[cp->NumberOfCommands] = (char**)malloc((n+1)*sizeof(char*));
- if(!newCommands[cp->NumberOfCommands])
+ if(cp->Verbatim)
{
- /* Out of memory. */
- free(newCommands);
- return 0;
- }
- for(i=0; i < n; ++i)
- {
- newCommands[cp->NumberOfCommands][i] = strdup(command[i]);
- if(!newCommands[cp->NumberOfCommands][i])
+ /* In order to run the given command line verbatim we need to
+ parse it. */
+ newCommands[cp->NumberOfCommands] =
+ kwsysProcessParseVerbatimCommand(*command);
+ if(!newCommands[cp->NumberOfCommands])
{
- break;
+ /* Out of memory. */
+ free(newCommands);
+ return 0;
}
}
- if(i < n)
+ else
{
- /* Out of memory. */
- for(;i > 0; --i)
+ /* Copy each argument string individually. */
+ char const* const* c = command;
+ int n = 0;
+ int i = 0;
+ while(*c++);
+ n = c - command - 1;
+ newCommands[cp->NumberOfCommands] = (char**)malloc((n+1)*sizeof(char*));
+ if(!newCommands[cp->NumberOfCommands])
{
- free(newCommands[cp->NumberOfCommands][i-1]);
+ /* Out of memory. */
+ free(newCommands);
+ return 0;
}
- free(newCommands);
- return 0;
+ for(i=0; i < n; ++i)
+ {
+ newCommands[cp->NumberOfCommands][i] = strdup(command[i]);
+ if(!newCommands[cp->NumberOfCommands][i])
+ {
+ break;
+ }
+ }
+ if(i < n)
+ {
+ /* Out of memory. */
+ for(;i > 0; --i)
+ {
+ free(newCommands[cp->NumberOfCommands][i-1]);
+ }
+ free(newCommands);
+ return 0;
+ }
+ newCommands[cp->NumberOfCommands][n] = 0;
}
- newCommands[cp->NumberOfCommands][n] = 0;
- }
/* Successfully allocated new command array. Free the old array. */
free(cp->Commands);
@@ -492,6 +512,7 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
switch(optionId)
{
case kwsysProcess_Option_Detach: return cp->OptionDetach;
+ case kwsysProcess_Option_Verbatim: return cp->Verbatim;
default: return 0;
}
}
@@ -507,6 +528,7 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
switch(optionId)
{
case kwsysProcess_Option_Detach: cp->OptionDetach = value; break;
+ case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break;
default: break;
}
}
@@ -2256,3 +2278,256 @@ static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
write(cp->SignalPipe, &buf, 1);
}
}
+
+/*--------------------------------------------------------------------------*/
+static int kwsysProcessAppendByte(char* local,
+ char** begin, char** end,
+ int* size, char c)
+{
+ /* Allocate space for the character. */
+ if((*end - *begin) >= *size)
+ {
+ int length = *end - *begin;
+ char* newBuffer = (char*)malloc(*size*2);
+ if(!newBuffer)
+ {
+ return 0;
+ }
+ memcpy(newBuffer, *begin, length*sizeof(char));
+ if(*begin != local)
+ {
+ free(*begin);
+ }
+ *begin = newBuffer;
+ *end = *begin + length;
+ *size *= 2;
+ }
+
+ /* Store the character. */
+ *(*end)++ = c;
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+static int kwsysProcessAppendArgument(char** local,
+ char*** begin, char*** end,
+ int* size,
+ char* arg_local,
+ char** arg_begin, char** arg_end,
+ int* arg_size)
+{
+ /* Append a null-terminator to the argument string. */
+ if(!kwsysProcessAppendByte(arg_local, arg_begin, arg_end, arg_size, '\0'))
+ {
+ return 0;
+ }
+
+ /* Allocate space for the argument pointer. */
+ if((*end - *begin) >= *size)
+ {
+ int length = *end - *begin;
+ char** newPointers = (char**)malloc(*size*2*sizeof(char*));
+ if(!newPointers)
+ {
+ return 0;
+ }
+ memcpy(newPointers, *begin, length*sizeof(char*));
+ if(*begin != local)
+ {
+ free(*begin);
+ }
+ *begin = newPointers;
+ *end = *begin + length;
+ *size *= 2;
+ }
+
+ /* Allocate space for the argument string. */
+ **end = (char*)malloc(*arg_end - *arg_begin);
+ if(!**end)
+ {
+ return 0;
+ }
+
+ /* Store the argument in the command array. */
+ memcpy(**end, *arg_begin, *arg_end - *arg_begin);
+ ++(*end);
+
+ /* Reset the argument to be empty. */
+ *arg_end = *arg_begin;
+
+ return 1;
+}
+
+/*--------------------------------------------------------------------------*/
+#define KWSYSPE_LOCAL_BYTE_COUNT 1024
+#define KWSYSPE_LOCAL_ARGS_COUNT 32
+static char** kwsysProcessParseVerbatimCommand(const char* command)
+{
+ /* Create a buffer for argument pointers during parsing. */
+ char* local_pointers[KWSYSPE_LOCAL_ARGS_COUNT];
+ int pointers_size = KWSYSPE_LOCAL_ARGS_COUNT;
+ char** pointer_begin = local_pointers;
+ char** pointer_end = pointer_begin;
+
+ /* Create a buffer for argument strings during parsing. */
+ char local_buffer[KWSYSPE_LOCAL_BYTE_COUNT];
+ int buffer_size = KWSYSPE_LOCAL_BYTE_COUNT;
+ char* buffer_begin = local_buffer;
+ char* buffer_end = buffer_begin;
+
+ /* Parse the command string. Try to behave like a UNIX shell. */
+ char** newCommand = 0;
+ const char* c = command;
+ int in_argument = 0;
+ int in_escape = 0;
+ int in_single = 0;
+ int in_double = 0;
+ int failed = 0;
+ for(;*c; ++c)
+ {
+ if(in_escape)
+ {
+ /* This character is escaped so do no special handling. */
+ if(!in_argument)
+ {
+ in_argument = 1;
+ }
+ if(!kwsysProcessAppendByte(local_buffer, &buffer_begin,
+ &buffer_end, &buffer_size, *c))
+ {
+ failed = 1;
+ break;
+ }
+ in_escape = 0;
+ }
+ else if(*c == '\\' && !in_single)
+ {
+ /* The next character should be escaped. */
+ in_escape = 1;
+ }
+ else if(*c == '\'' && !in_double)
+ {
+ /* Enter or exit single-quote state. */
+ if(in_single)
+ {
+ in_single = 0;
+ }
+ else
+ {
+ in_single = 1;
+ if(!in_argument)
+ {
+ in_argument = 1;
+ }
+ }
+ }
+ else if(*c == '"' && !in_single)
+ {
+ /* Enter or exit double-quote state. */
+ if(in_double)
+ {
+ in_double = 0;
+ }
+ else
+ {
+ in_double = 1;
+ if(!in_argument)
+ {
+ in_argument = 1;
+ }
+ }
+ }
+ else if(isspace(*c))
+ {
+ if(in_argument)
+ {
+ if(in_single || in_double)
+ {
+ /* This space belongs to a quoted argument. */
+ if(!kwsysProcessAppendByte(local_buffer, &buffer_begin,
+ &buffer_end, &buffer_size, *c))
+ {
+ failed = 1;
+ break;
+ }
+ }
+ else
+ {
+ /* This argument has been terminated by whitespace. */
+ if(!kwsysProcessAppendArgument(local_pointers, &pointer_begin,
+ &pointer_end, &pointers_size,
+ local_buffer, &buffer_begin,
+ &buffer_end, &buffer_size))
+ {
+ failed = 1;
+ break;
+ }
+ in_argument = 0;
+ }
+ }
+ }
+ else
+ {
+ /* This character belong to an argument. */
+ if(!in_argument)
+ {
+ in_argument = 1;
+ }
+ if(!kwsysProcessAppendByte(local_buffer, &buffer_begin,
+ &buffer_end, &buffer_size, *c))
+ {
+ failed = 1;
+ break;
+ }
+ }
+ }
+
+ /* Finish the last argument. */
+ if(in_argument)
+ {
+ if(!kwsysProcessAppendArgument(local_pointers, &pointer_begin,
+ &pointer_end, &pointers_size,
+ local_buffer, &buffer_begin,
+ &buffer_end, &buffer_size))
+ {
+ failed = 1;
+ }
+ }
+
+ /* If we still have memory allocate space for the new command
+ buffer. */
+ if(!failed)
+ {
+ int n = pointer_end - pointer_begin;
+ newCommand = (char**)malloc((n+1)*sizeof(char*));
+ }
+
+ if(newCommand)
+ {
+ /* Copy the arguments into the new command buffer. */
+ int n = pointer_end - pointer_begin;
+ memcpy(newCommand, pointer_begin, sizeof(char*)*n);
+ newCommand[n] = 0;
+ }
+ else
+ {
+ /* Free arguments already allocated. */
+ while(pointer_end != pointer_begin)
+ {
+ free(*(--pointer_end));
+ }
+ }
+
+ /* Free temporary buffers. */
+ if(pointer_begin != local_pointers)
+ {
+ free(pointer_begin);
+ }
+ if(buffer_begin != local_buffer)
+ {
+ free(buffer_begin);
+ }
+
+ /* Return the final command buffer. */
+ return newCommand;
+}
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 26b77f9..406a187 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -107,6 +107,11 @@ static void kwsysProcessCleanupHandle(PHANDLE h);
static void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle);
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
static void kwsysProcessCleanErrorMessage(kwsysProcess* cp);
+static int kwsysProcessComputeCommandLength(kwsysProcess* cp,
+ char const* const* command);
+static void kwsysProcessComputeCommandLine(kwsysProcess* cp,
+ char const* const* command,
+ char* cmd);
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
kwsysProcessTime* timeoutTime);
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
@@ -206,6 +211,9 @@ struct kwsysProcess_s
/* Whether to hide the child process's window. */
int HideWindow;
+ /* Whether to treat command lines as verbatim. */
+ int Verbatim;
+
/* On Win9x platforms, the path to the forwarding executable. */
char* Win9x;
@@ -646,7 +654,7 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
char** newCommands;
/* Make sure we have a command to add. */
- if(!cp || !command)
+ if(!cp || !command || !*command)
{
return 0;
}
@@ -669,77 +677,19 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
}
/* We need to construct a single string representing the command
- and its arguments. We will surround each argument containing
- spaces with double-quotes. Inside a double-quoted argument, we
- need to escape double-quotes and all backslashes before them.
- We also need to escape backslashes at the end of an argument
- because they come before the closing double-quote for the
- argument. */
+ and its arguments. We will surround each argument containing
+ spaces with double-quotes. Inside a double-quoted argument, we
+ need to escape double-quotes and all backslashes before them.
+ We also need to escape backslashes at the end of an argument
+ because they come before the closing double-quote for the
+ argument. */
{
- char* cmd;
- char const* const* arg;
- int length = 0;
/* First determine the length of the final string. */
- for(arg = command; *arg; ++arg)
- {
- /* Keep track of how many backslashes have been encountered in a
- row in this argument. */
- int backslashes = 0;
- int spaces = 0;
- const char* c;
-
- /* Scan the string for spaces. If there are no spaces, we can
- pass the argument verbatim. */
- for(c=*arg; *c; ++c)
- {
- if(*c == ' ' || *c == '\t')
- {
- spaces = 1;
- break;
- }
- }
-
- /* Add the length of the argument, plus 1 for the space
- separating the arguments. */
- length += (int)strlen(*arg) + 1;
-
- if(spaces)
- {
- /* Add 2 for double quotes since spaces are present. */
- length += 2;
-
- /* Scan the string to find characters that need escaping. */
- for(c=*arg; *c; ++c)
- {
- if(*c == '\\')
- {
- /* Found a backslash. It may need to be escaped later. */
- ++backslashes;
- }
- else if(*c == '"')
- {
- /* Found a double-quote. We need to escape it and all
- immediately preceding backslashes. */
- length += backslashes + 1;
- backslashes = 0;
- }
- else
- {
- /* Found another character. This eliminates the possibility
- that any immediately preceding backslashes will be
- escaped. */
- backslashes = 0;
- }
- }
-
- /* We need to escape all ending backslashes. */
- length += backslashes;
- }
- }
+ int length = kwsysProcessComputeCommandLength(cp, command);
/* Allocate enough space for the command. We do not need an extra
- byte for the terminating null because we allocated a space for
- the first argument that we will not use. */
+ byte for the terminating null because we allocated a space for
+ the first argument that we will not use. */
newCommands[cp->NumberOfCommands] = (char*)malloc(length);
if(!newCommands[cp->NumberOfCommands])
{
@@ -749,94 +699,8 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
}
/* Construct the command line in the allocated buffer. */
- cmd = newCommands[cp->NumberOfCommands];
- for(arg = command; *arg; ++arg)
- {
- /* Keep track of how many backslashes have been encountered in a
- row in an argument. */
- int backslashes = 0;
- int spaces = 0;
- const char* c;
-
- /* Scan the string for spaces. If there are no spaces, we can
- pass the argument verbatim. */
- for(c=*arg; *c; ++c)
- {
- if(*c == ' ' || *c == '\t')
- {
- spaces = 1;
- break;
- }
- }
-
- /* Add the separating space if this is not the first argument. */
- if(arg != command)
- {
- *cmd++ = ' ';
- }
-
- if(spaces)
- {
- /* Add the opening double-quote for this argument. */
- *cmd++ = '"';
-
- /* Add the characters of the argument, possibly escaping them. */
- for(c=*arg; *c; ++c)
- {
- if(*c == '\\')
- {
- /* Found a backslash. It may need to be escaped later. */
- ++backslashes;
- *cmd++ = '\\';
- }
- else if(*c == '"')
- {
- /* Add enough backslashes to escape any that preceded the
- double-quote. */
- while(backslashes > 0)
- {
- --backslashes;
- *cmd++ = '\\';
- }
-
- /* Add the backslash to escape the double-quote. */
- *cmd++ = '\\';
-
- /* Add the double-quote itself. */
- *cmd++ = '"';
- }
- else
- {
- /* We encountered a normal character. This eliminates any
- escaping needed for preceding backslashes. Add the
- character. */
- backslashes = 0;
- *cmd++ = *c;
- }
- }
-
- /* Add enough backslashes to escape any trailing ones. */
- while(backslashes > 0)
- {
- --backslashes;
- *cmd++ = '\\';
- }
-
- /* Add the closing double-quote for this argument. */
- *cmd++ = '"';
- }
- else
- {
- /* No spaces. Add the argument verbatim. */
- for(c=*arg; *c; ++c)
- {
- *cmd++ = *c;
- }
- }
- }
-
- /* Add the terminating null character to the command line. */
- *cmd = 0;
+ kwsysProcessComputeCommandLine(cp, command,
+ newCommands[cp->NumberOfCommands]);
}
/* Save the new array of commands. */
@@ -968,6 +832,7 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
{
case kwsysProcess_Option_Detach: return cp->OptionDetach;
case kwsysProcess_Option_HideWindow: return cp->HideWindow;
+ case kwsysProcess_Option_Verbatim: return cp->Verbatim;
default: return 0;
}
}
@@ -984,6 +849,7 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
{
case kwsysProcess_Option_Detach: cp->OptionDetach = value; break;
case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break;
+ case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break;
default: break;
}
}
@@ -2199,6 +2065,189 @@ void kwsysProcessCleanErrorMessage(kwsysProcess* cp)
}
/*--------------------------------------------------------------------------*/
+int kwsysProcessComputeCommandLength(kwsysProcess* cp,
+ char const* const* command)
+{
+ int length = 0;
+ if(cp->Verbatim)
+ {
+ /* Treat the first argument as a verbatim command line. Use its
+ length directly and add space for the null-terminator. */
+ length = strlen(*command)+1;
+ }
+ else
+ {
+ /* Compute the length of the command line when it is converted to
+ a single string. Space for the null-terminator is allocated by
+ the whitespace character allocated for the first argument that
+ will not be used. */
+ char const* const* arg;
+ for(arg = command; *arg; ++arg)
+ {
+ /* Keep track of how many backslashes have been encountered in a
+ row in this argument. */
+ int backslashes = 0;
+ int spaces = 0;
+ const char* c;
+
+ /* Scan the string for spaces. If there are no spaces, we can
+ pass the argument verbatim. */
+ for(c=*arg; *c; ++c)
+ {
+ if(*c == ' ' || *c == '\t')
+ {
+ spaces = 1;
+ break;
+ }
+ }
+
+ /* Add the length of the argument, plus 1 for the space
+ separating the arguments. */
+ length += (int)strlen(*arg) + 1;
+
+ if(spaces)
+ {
+ /* Add 2 for double quotes since spaces are present. */
+ length += 2;
+
+ /* Scan the string to find characters that need escaping. */
+ for(c=*arg; *c; ++c)
+ {
+ if(*c == '\\')
+ {
+ /* Found a backslash. It may need to be escaped later. */
+ ++backslashes;
+ }
+ else if(*c == '"')
+ {
+ /* Found a double-quote. We need to escape it and all
+ immediately preceding backslashes. */
+ length += backslashes + 1;
+ backslashes = 0;
+ }
+ else
+ {
+ /* Found another character. This eliminates the possibility
+ that any immediately preceding backslashes will be
+ escaped. */
+ backslashes = 0;
+ }
+ }
+
+ /* We need to escape all ending backslashes. */
+ length += backslashes;
+ }
+ }
+ }
+
+ return length;
+}
+
+/*--------------------------------------------------------------------------*/
+void kwsysProcessComputeCommandLine(kwsysProcess* cp,
+ char const* const* command,
+ char* cmd)
+{
+ if(cp->Verbatim)
+ {
+ /* Copy the verbatim command line into the buffer. */
+ strcpy(cmd, *command);
+ }
+ else
+ {
+ /* Construct the command line in the allocated buffer. */
+ char const* const* arg;
+ for(arg = command; *arg; ++arg)
+ {
+ /* Keep track of how many backslashes have been encountered in a
+ row in an argument. */
+ int backslashes = 0;
+ int spaces = 0;
+ const char* c;
+
+ /* Scan the string for spaces. If there are no spaces, we can
+ pass the argument verbatim. */
+ for(c=*arg; *c; ++c)
+ {
+ if(*c == ' ' || *c == '\t')
+ {
+ spaces = 1;
+ break;
+ }
+ }
+
+ /* Add the separating space if this is not the first argument. */
+ if(arg != command)
+ {
+ *cmd++ = ' ';
+ }
+
+ if(spaces)
+ {
+ /* Add the opening double-quote for this argument. */
+ *cmd++ = '"';
+
+ /* Add the characters of the argument, possibly escaping them. */
+ for(c=*arg; *c; ++c)
+ {
+ if(*c == '\\')
+ {
+ /* Found a backslash. It may need to be escaped later. */
+ ++backslashes;
+ *cmd++ = '\\';
+ }
+ else if(*c == '"')
+ {
+ /* Add enough backslashes to escape any that preceded the
+ double-quote. */
+ while(backslashes > 0)
+ {
+ --backslashes;
+ *cmd++ = '\\';
+ }
+
+ /* Add the backslash to escape the double-quote. */
+ *cmd++ = '\\';
+
+ /* Add the double-quote itself. */
+ *cmd++ = '"';
+ }
+ else
+ {
+ /* We encountered a normal character. This eliminates any
+ escaping needed for preceding backslashes. Add the
+ character. */
+ backslashes = 0;
+ *cmd++ = *c;
+ }
+ }
+
+ /* Add enough backslashes to escape any trailing ones. */
+ while(backslashes > 0)
+ {
+ --backslashes;
+ *cmd++ = '\\';
+ }
+
+ /* Add the closing double-quote for this argument. */
+ *cmd++ = '"';
+ }
+ else
+ {
+ /* No spaces. Add the argument verbatim. */
+ for(c=*arg; *c; ++c)
+ {
+ *cmd++ = *c;
+ }
+ }
+ }
+
+ /* Add the terminating null character to the command line. */
+ *cmd = 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
/* Get the time at which either the process or user timeout will
expire. Returns 1 if the user timeout is first, and 0 otherwise. */
int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,