| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ | |
| #include "kwsysPrivate.h" | |
| #include KWSYS_HEADER(String.h) | |
| #include KWSYS_HEADER(System.h) | |
| /* Work-around CMake dependency scanning limitation. This must | |
| duplicate the above list of headers. */ | |
| #if 0 | |
| # include "String.h.in" | |
| # include "System.h.in" | |
| #endif | |
| #include <stddef.h> /* ptrdiff_t */ | |
| #include <stdlib.h> /* malloc, free */ | |
| #include <string.h> /* memcpy */ | |
| #include <stdio.h> | |
| #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 const* 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(char const* 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; | |
| char const* 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 (kwsysString_isspace(*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(char const* command, int flags) | |
| { | |
| /* Validate the flags. */ | |
| if (flags != 0) { | |
| return 0; | |
| } | |
| /* Forward to our internal implementation. */ | |
| return kwsysSystem__ParseUnixCommand(command, flags); | |
| } |