cmake/Source/kwsys/System.c

237 lines
6.7 KiB
C
Raw Normal View History

2017-04-14 19:02:05 +02:00
/* 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(System.h)
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
2018-08-09 18:06:22 +02:00
# include "System.h.in"
#endif
2017-04-14 19:02:05 +02:00
#include <ctype.h> /* isspace */
2009-10-04 10:30:41 +03:00
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* malloc, free */
2015-11-17 17:22:37 +01:00
#include <string.h> /* memcpy */
#include <stdio.h>
2009-10-04 10:30:41 +03:00
#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
2020-08-30 11:54:41 +02:00
static int kwsysSystem__AppendByte(const char* local, char** begin, char** end,
2009-10-04 10:30:41 +03:00
int* size, char c)
{
/* Allocate space for the character. */
2017-04-14 19:02:05 +02:00
if ((*end - *begin) >= *size) {
2009-10-04 10:30:41 +03:00
kwsysSystem_ptrdiff_t length = *end - *begin;
2017-04-14 19:02:05 +02:00
char* newBuffer = (char*)malloc((size_t)(*size * 2));
if (!newBuffer) {
2009-10-04 10:30:41 +03:00
return 0;
2017-04-14 19:02:05 +02:00
}
memcpy(newBuffer, *begin, (size_t)(length) * sizeof(char));
if (*begin != local) {
2009-10-04 10:30:41 +03:00
free(*begin);
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
*begin = newBuffer;
*end = *begin + length;
*size *= 2;
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* Store the character. */
*(*end)++ = c;
return 1;
}
2017-04-14 19:02:05 +02:00
static int kwsysSystem__AppendArgument(char** local, char*** begin,
char*** end, int* size, char* arg_local,
2009-10-04 10:30:41 +03:00
char** arg_begin, char** arg_end,
int* arg_size)
{
/* Append a null-terminator to the argument string. */
2017-04-14 19:02:05 +02:00
if (!kwsysSystem__AppendByte(arg_local, arg_begin, arg_end, arg_size,
'\0')) {
2009-10-04 10:30:41 +03:00
return 0;
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* Allocate space for the argument pointer. */
2017-04-14 19:02:05 +02:00
if ((*end - *begin) >= *size) {
2009-10-04 10:30:41 +03:00
kwsysSystem_ptrdiff_t length = *end - *begin;
2017-04-14 19:02:05 +02:00
char** newPointers = (char**)malloc((size_t)(*size) * 2 * sizeof(char*));
if (!newPointers) {
2009-10-04 10:30:41 +03:00
return 0;
2017-04-14 19:02:05 +02:00
}
memcpy(newPointers, *begin, (size_t)(length) * sizeof(char*));
if (*begin != local) {
2009-10-04 10:30:41 +03:00
free(*begin);
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
*begin = newPointers;
*end = *begin + length;
*size *= 2;
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* Allocate space for the argument string. */
**end = (char*)malloc((size_t)(*arg_end - *arg_begin));
2017-04-14 19:02:05 +02:00
if (!**end) {
2009-10-04 10:30:41 +03:00
return 0;
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* Store the argument in the command array. */
2017-04-14 19:02:05 +02:00
memcpy(**end, *arg_begin, (size_t)(*arg_end - *arg_begin));
2009-10-04 10:30:41 +03:00
++(*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;
2017-04-14 19:02:05 +02:00
for (; *c; ++c) {
if (in_escape) {
2009-10-04 10:30:41 +03:00
/* This character is escaped so do no special handling. */
2017-04-14 19:02:05 +02:00
if (!in_argument) {
2009-10-04 10:30:41 +03:00
in_argument = 1;
2017-04-14 19:02:05 +02:00
}
if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end,
&buffer_size, *c)) {
2009-10-04 10:30:41 +03:00
failed = 1;
break;
}
2017-04-14 19:02:05 +02:00
in_escape = 0;
} else if (*c == '\\') {
2009-10-04 10:30:41 +03:00
/* The next character should be escaped. */
in_escape = 1;
2017-04-14 19:02:05 +02:00
} else if (*c == '\'' && !in_double) {
2009-10-04 10:30:41 +03:00
/* Enter or exit single-quote state. */
2017-04-14 19:02:05 +02:00
if (in_single) {
2009-10-04 10:30:41 +03:00
in_single = 0;
2017-04-14 19:02:05 +02:00
} else {
2009-10-04 10:30:41 +03:00
in_single = 1;
2017-04-14 19:02:05 +02:00
if (!in_argument) {
2009-10-04 10:30:41 +03:00
in_argument = 1;
}
}
2017-04-14 19:02:05 +02:00
} else if (*c == '"' && !in_single) {
2009-10-04 10:30:41 +03:00
/* Enter or exit double-quote state. */
2017-04-14 19:02:05 +02:00
if (in_double) {
2009-10-04 10:30:41 +03:00
in_double = 0;
2017-04-14 19:02:05 +02:00
} else {
2009-10-04 10:30:41 +03:00
in_double = 1;
2017-04-14 19:02:05 +02:00
if (!in_argument) {
2009-10-04 10:30:41 +03:00
in_argument = 1;
}
}
2017-04-14 19:02:05 +02:00
} else if (isspace((unsigned char)*c)) {
if (in_argument) {
if (in_single || in_double) {
2009-10-04 10:30:41 +03:00
/* This space belongs to a quoted argument. */
2017-04-14 19:02:05 +02:00
if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin,
&buffer_end, &buffer_size, *c)) {
2009-10-04 10:30:41 +03:00
failed = 1;
break;
}
2017-04-14 19:02:05 +02:00
} else {
2009-10-04 10:30:41 +03:00
/* This argument has been terminated by whitespace. */
2017-04-14 19:02:05 +02:00
if (!kwsysSystem__AppendArgument(
local_pointers, &pointer_begin, &pointer_end, &pointers_size,
local_buffer, &buffer_begin, &buffer_end, &buffer_size)) {
2009-10-04 10:30:41 +03:00
failed = 1;
break;
}
2017-04-14 19:02:05 +02:00
in_argument = 0;
2009-10-04 10:30:41 +03:00
}
}
2017-04-14 19:02:05 +02:00
} else {
2009-10-04 10:30:41 +03:00
/* This character belong to an argument. */
2017-04-14 19:02:05 +02:00
if (!in_argument) {
2009-10-04 10:30:41 +03:00
in_argument = 1;
2017-04-14 19:02:05 +02:00
}
if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end,
&buffer_size, *c)) {
2009-10-04 10:30:41 +03:00
failed = 1;
break;
}
}
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* Finish the last argument. */
2017-04-14 19:02:05 +02:00
if (in_argument) {
if (!kwsysSystem__AppendArgument(
local_pointers, &pointer_begin, &pointer_end, &pointers_size,
local_buffer, &buffer_begin, &buffer_end, &buffer_size)) {
2009-10-04 10:30:41 +03:00
failed = 1;
}
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* If we still have memory allocate space for the new command
buffer. */
2017-04-14 19:02:05 +02:00
if (!failed) {
2009-10-04 10:30:41 +03:00
kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin;
2017-04-14 19:02:05 +02:00
newCommand = (char**)malloc((size_t)(n + 1) * sizeof(char*));
}
2009-10-04 10:30:41 +03:00
2017-04-14 19:02:05 +02:00
if (newCommand) {
2009-10-04 10:30:41 +03:00
/* Copy the arguments into the new command buffer. */
kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin;
2017-04-14 19:02:05 +02:00
memcpy(newCommand, pointer_begin, sizeof(char*) * (size_t)(n));
2009-10-04 10:30:41 +03:00
newCommand[n] = 0;
2017-04-14 19:02:05 +02:00
} else {
2009-10-04 10:30:41 +03:00
/* Free arguments already allocated. */
2017-04-14 19:02:05 +02:00
while (pointer_end != pointer_begin) {
2009-10-04 10:30:41 +03:00
free(*(--pointer_end));
}
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* Free temporary buffers. */
2017-04-14 19:02:05 +02:00
if (pointer_begin != local_pointers) {
2009-10-04 10:30:41 +03:00
free(pointer_begin);
2017-04-14 19:02:05 +02:00
}
if (buffer_begin != local_buffer) {
2009-10-04 10:30:41 +03:00
free(buffer_begin);
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* 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. */
2017-04-14 19:02:05 +02:00
if (flags != 0) {
2009-10-04 10:30:41 +03:00
return 0;
2017-04-14 19:02:05 +02:00
}
2009-10-04 10:30:41 +03:00
/* Forward to our internal implementation. */
return kwsysSystem__ParseUnixCommand(command, flags);
}