/*============================================================================ KWSys - Kitware System Library Copyright 2000-2009 Kitware, Inc., Insight Software Consortium Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #include "kwsysPrivate.h" #include KWSYS_HEADER(System.h) /* Work-around CMake dependency scanning limitation. This must duplicate the above list of headers. */ #if 0 # include "System.h.in" #endif #include /* ptrdiff_t */ #include /* malloc, free */ #include /* memcpy */ #include /* isspace */ #include #if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T typedef ptrdiff_t kwsysSystem_ptrdiff_t; #else typedef int kwsysSystem_ptrdiff_t; #endif /*--------------------------------------------------------------------------*/ static int kwsysSystem__AppendByte(char* local, char** begin, char** end, int* size, char c) { /* Allocate space for the character. */ if((*end - *begin) >= *size) { kwsysSystem_ptrdiff_t length = *end - *begin; char* newBuffer = (char*)malloc((size_t)(*size*2)); if(!newBuffer) { return 0; } memcpy(newBuffer, *begin, (size_t)(length)*sizeof(char)); if(*begin != local) { free(*begin); } *begin = newBuffer; *end = *begin + length; *size *= 2; } /* Store the character. */ *(*end)++ = c; return 1; } /*--------------------------------------------------------------------------*/ static int kwsysSystem__AppendArgument(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(!kwsysSystem__AppendByte(arg_local, arg_begin, arg_end, arg_size, '\0')) { return 0; } /* Allocate space for the argument pointer. */ if((*end - *begin) >= *size) { kwsysSystem_ptrdiff_t length = *end - *begin; char** newPointers = (char**)malloc((size_t)(*size)*2*sizeof(char*)); if(!newPointers) { return 0; } memcpy(newPointers, *begin, (size_t)(length)*sizeof(char*)); if(*begin != local) { free(*begin); } *begin = newPointers; *end = *begin + length; *size *= 2; } /* Allocate space for the argument string. */ **end = (char*)malloc((size_t)(*arg_end - *arg_begin)); if(!**end) { return 0; } /* Store the argument in the command array. */ memcpy(**end, *arg_begin,(size_t)(*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** kwsysSystem__ParseUnixCommand(const char* command, int flags) { /* 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(!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end, &buffer_size, *c)) { failed = 1; break; } in_escape = 0; } else if(*c == '\\') { /* 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((unsigned char) *c)) { if(in_argument) { if(in_single || in_double) { /* This space belongs to a quoted argument. */ if(!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end, &buffer_size, *c)) { failed = 1; break; } } else { /* This argument has been terminated by whitespace. */ if(!kwsysSystem__AppendArgument(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(!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end, &buffer_size, *c)) { failed = 1; break; } } } /* Finish the last argument. */ if(in_argument) { if(!kwsysSystem__AppendArgument(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) { kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin; newCommand = (char**)malloc((size_t)(n+1)*sizeof(char*)); } if(newCommand) { /* Copy the arguments into the new command buffer. */ kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin; memcpy(newCommand, pointer_begin, sizeof(char*)*(size_t)(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); } /* The flags argument is currently unused. */ (void)flags; /* Return the final command buffer. */ return newCommand; } /*--------------------------------------------------------------------------*/ char** kwsysSystem_Parse_CommandForUnix(const char* command, int flags) { /* Validate the flags. */ if(flags != 0) { return 0; } /* Forward to our internal implementation. */ return kwsysSystem__ParseUnixCommand(command, flags); }