System.c 6.66 KB
Newer Older
Kitware Robot's avatar
Kitware Robot committed
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
Kitware Robot's avatar
Kitware Robot committed
3 4 5 6 7 8
#include "kwsysPrivate.h"
#include KWSYS_HEADER(System.h)

/* Work-around CMake dependency scanning limitation.  This must
   duplicate the above list of headers.  */
#if 0
Kitware Robot's avatar
Kitware Robot committed
9
#  include "System.h.in"
Kitware Robot's avatar
Kitware Robot committed
10 11
#endif

Kitware Robot's avatar
Kitware Robot committed
12
#include <ctype.h>  /* isspace */
Kitware Robot's avatar
Kitware Robot committed
13 14
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* malloc, free */
Kitware Robot's avatar
Kitware Robot committed
15
#include <string.h> /* memcpy */
Kitware Robot's avatar
Kitware Robot committed
16 17 18 19 20 21 22 23 24

#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

Kitware Robot's avatar
Kitware Robot committed
25
static int kwsysSystem__AppendByte(char* local, char** begin, char** end,
Kitware Robot's avatar
Kitware Robot committed
26 27 28
                                   int* size, char c)
{
  /* Allocate space for the character.  */
Kitware Robot's avatar
Kitware Robot committed
29
  if ((*end - *begin) >= *size) {
Kitware Robot's avatar
Kitware Robot committed
30
    kwsysSystem_ptrdiff_t length = *end - *begin;
Kitware Robot's avatar
Kitware Robot committed
31 32
    char* newBuffer = (char*)malloc((size_t)(*size * 2));
    if (!newBuffer) {
Kitware Robot's avatar
Kitware Robot committed
33
      return 0;
Kitware Robot's avatar
Kitware Robot committed
34 35 36
    }
    memcpy(newBuffer, *begin, (size_t)(length) * sizeof(char));
    if (*begin != local) {
Kitware Robot's avatar
Kitware Robot committed
37
      free(*begin);
Kitware Robot's avatar
Kitware Robot committed
38
    }
Kitware Robot's avatar
Kitware Robot committed
39 40 41
    *begin = newBuffer;
    *end = *begin + length;
    *size *= 2;
Kitware Robot's avatar
Kitware Robot committed
42
  }
Kitware Robot's avatar
Kitware Robot committed
43 44 45 46 47 48

  /* Store the character.  */
  *(*end)++ = c;
  return 1;
}

Kitware Robot's avatar
Kitware Robot committed
49 50
static int kwsysSystem__AppendArgument(char** local, char*** begin,
                                       char*** end, int* size, char* arg_local,
Kitware Robot's avatar
Kitware Robot committed
51 52 53 54
                                       char** arg_begin, char** arg_end,
                                       int* arg_size)
{
  /* Append a null-terminator to the argument string.  */
Kitware Robot's avatar
Kitware Robot committed
55 56
  if (!kwsysSystem__AppendByte(arg_local, arg_begin, arg_end, arg_size,
                               '\0')) {
Kitware Robot's avatar
Kitware Robot committed
57
    return 0;
Kitware Robot's avatar
Kitware Robot committed
58
  }
Kitware Robot's avatar
Kitware Robot committed
59 60

  /* Allocate space for the argument pointer.  */
Kitware Robot's avatar
Kitware Robot committed
61
  if ((*end - *begin) >= *size) {
Kitware Robot's avatar
Kitware Robot committed
62
    kwsysSystem_ptrdiff_t length = *end - *begin;
Kitware Robot's avatar
Kitware Robot committed
63 64
    char** newPointers = (char**)malloc((size_t)(*size) * 2 * sizeof(char*));
    if (!newPointers) {
Kitware Robot's avatar
Kitware Robot committed
65
      return 0;
Kitware Robot's avatar
Kitware Robot committed
66 67 68
    }
    memcpy(newPointers, *begin, (size_t)(length) * sizeof(char*));
    if (*begin != local) {
Kitware Robot's avatar
Kitware Robot committed
69
      free(*begin);
Kitware Robot's avatar
Kitware Robot committed
70
    }
Kitware Robot's avatar
Kitware Robot committed
71 72 73
    *begin = newPointers;
    *end = *begin + length;
    *size *= 2;
Kitware Robot's avatar
Kitware Robot committed
74
  }
Kitware Robot's avatar
Kitware Robot committed
75 76 77

  /* Allocate space for the argument string.  */
  **end = (char*)malloc((size_t)(*arg_end - *arg_begin));
Kitware Robot's avatar
Kitware Robot committed
78
  if (!**end) {
Kitware Robot's avatar
Kitware Robot committed
79
    return 0;
Kitware Robot's avatar
Kitware Robot committed
80
  }
Kitware Robot's avatar
Kitware Robot committed
81 82

  /* Store the argument in the command array.  */
Kitware Robot's avatar
Kitware Robot committed
83
  memcpy(**end, *arg_begin, (size_t)(*arg_end - *arg_begin));
Kitware Robot's avatar
Kitware Robot committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
  ++(*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;
Kitware Robot's avatar
Kitware Robot committed
116 117
  for (; *c; ++c) {
    if (in_escape) {
Kitware Robot's avatar
Kitware Robot committed
118
      /* This character is escaped so do no special handling.  */
Kitware Robot's avatar
Kitware Robot committed
119
      if (!in_argument) {
Kitware Robot's avatar
Kitware Robot committed
120
        in_argument = 1;
Kitware Robot's avatar
Kitware Robot committed
121 122 123
      }
      if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end,
                                   &buffer_size, *c)) {
Kitware Robot's avatar
Kitware Robot committed
124 125 126
        failed = 1;
        break;
      }
Kitware Robot's avatar
Kitware Robot committed
127 128
      in_escape = 0;
    } else if (*c == '\\') {
Kitware Robot's avatar
Kitware Robot committed
129 130
      /* The next character should be escaped.  */
      in_escape = 1;
Kitware Robot's avatar
Kitware Robot committed
131
    } else if (*c == '\'' && !in_double) {
Kitware Robot's avatar
Kitware Robot committed
132
      /* Enter or exit single-quote state.  */
Kitware Robot's avatar
Kitware Robot committed
133
      if (in_single) {
Kitware Robot's avatar
Kitware Robot committed
134
        in_single = 0;
Kitware Robot's avatar
Kitware Robot committed
135
      } else {
Kitware Robot's avatar
Kitware Robot committed
136
        in_single = 1;
Kitware Robot's avatar
Kitware Robot committed
137
        if (!in_argument) {
Kitware Robot's avatar
Kitware Robot committed
138 139 140
          in_argument = 1;
        }
      }
Kitware Robot's avatar
Kitware Robot committed
141
    } else if (*c == '"' && !in_single) {
Kitware Robot's avatar
Kitware Robot committed
142
      /* Enter or exit double-quote state.  */
Kitware Robot's avatar
Kitware Robot committed
143
      if (in_double) {
Kitware Robot's avatar
Kitware Robot committed
144
        in_double = 0;
Kitware Robot's avatar
Kitware Robot committed
145
      } else {
Kitware Robot's avatar
Kitware Robot committed
146
        in_double = 1;
Kitware Robot's avatar
Kitware Robot committed
147
        if (!in_argument) {
Kitware Robot's avatar
Kitware Robot committed
148 149 150
          in_argument = 1;
        }
      }
Kitware Robot's avatar
Kitware Robot committed
151 152 153
    } else if (isspace((unsigned char)*c)) {
      if (in_argument) {
        if (in_single || in_double) {
Kitware Robot's avatar
Kitware Robot committed
154
          /* This space belongs to a quoted argument.  */
Kitware Robot's avatar
Kitware Robot committed
155 156
          if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin,
                                       &buffer_end, &buffer_size, *c)) {
Kitware Robot's avatar
Kitware Robot committed
157 158 159
            failed = 1;
            break;
          }
Kitware Robot's avatar
Kitware Robot committed
160
        } else {
Kitware Robot's avatar
Kitware Robot committed
161
          /* This argument has been terminated by whitespace.  */
Kitware Robot's avatar
Kitware Robot committed
162 163 164
          if (!kwsysSystem__AppendArgument(
                local_pointers, &pointer_begin, &pointer_end, &pointers_size,
                local_buffer, &buffer_begin, &buffer_end, &buffer_size)) {
Kitware Robot's avatar
Kitware Robot committed
165 166 167
            failed = 1;
            break;
          }
Kitware Robot's avatar
Kitware Robot committed
168
          in_argument = 0;
Kitware Robot's avatar
Kitware Robot committed
169 170
        }
      }
Kitware Robot's avatar
Kitware Robot committed
171
    } else {
Kitware Robot's avatar
Kitware Robot committed
172
      /* This character belong to an argument.  */
Kitware Robot's avatar
Kitware Robot committed
173
      if (!in_argument) {
Kitware Robot's avatar
Kitware Robot committed
174
        in_argument = 1;
Kitware Robot's avatar
Kitware Robot committed
175 176 177
      }
      if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end,
                                   &buffer_size, *c)) {
Kitware Robot's avatar
Kitware Robot committed
178 179 180 181
        failed = 1;
        break;
      }
    }
Kitware Robot's avatar
Kitware Robot committed
182
  }
Kitware Robot's avatar
Kitware Robot committed
183 184

  /* Finish the last argument.  */
Kitware Robot's avatar
Kitware Robot committed
185 186 187 188
  if (in_argument) {
    if (!kwsysSystem__AppendArgument(
          local_pointers, &pointer_begin, &pointer_end, &pointers_size,
          local_buffer, &buffer_begin, &buffer_end, &buffer_size)) {
Kitware Robot's avatar
Kitware Robot committed
189 190
      failed = 1;
    }
Kitware Robot's avatar
Kitware Robot committed
191
  }
Kitware Robot's avatar
Kitware Robot committed
192 193 194

  /* If we still have memory allocate space for the new command
     buffer.  */
Kitware Robot's avatar
Kitware Robot committed
195
  if (!failed) {
Kitware Robot's avatar
Kitware Robot committed
196
    kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin;
Kitware Robot's avatar
Kitware Robot committed
197 198
    newCommand = (char**)malloc((size_t)(n + 1) * sizeof(char*));
  }
Kitware Robot's avatar
Kitware Robot committed
199

Kitware Robot's avatar
Kitware Robot committed
200
  if (newCommand) {
Kitware Robot's avatar
Kitware Robot committed
201 202
    /* Copy the arguments into the new command buffer.  */
    kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin;
Kitware Robot's avatar
Kitware Robot committed
203
    memcpy(newCommand, pointer_begin, sizeof(char*) * (size_t)(n));
Kitware Robot's avatar
Kitware Robot committed
204
    newCommand[n] = 0;
Kitware Robot's avatar
Kitware Robot committed
205
  } else {
Kitware Robot's avatar
Kitware Robot committed
206
    /* Free arguments already allocated.  */
Kitware Robot's avatar
Kitware Robot committed
207
    while (pointer_end != pointer_begin) {
Kitware Robot's avatar
Kitware Robot committed
208 209
      free(*(--pointer_end));
    }
Kitware Robot's avatar
Kitware Robot committed
210
  }
Kitware Robot's avatar
Kitware Robot committed
211 212

  /* Free temporary buffers.  */
Kitware Robot's avatar
Kitware Robot committed
213
  if (pointer_begin != local_pointers) {
Kitware Robot's avatar
Kitware Robot committed
214
    free(pointer_begin);
Kitware Robot's avatar
Kitware Robot committed
215 216
  }
  if (buffer_begin != local_buffer) {
Kitware Robot's avatar
Kitware Robot committed
217
    free(buffer_begin);
Kitware Robot's avatar
Kitware Robot committed
218
  }
Kitware Robot's avatar
Kitware Robot committed
219 220 221 222 223 224 225 226 227 228 229

  /* 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.  */
Kitware Robot's avatar
Kitware Robot committed
230
  if (flags != 0) {
Kitware Robot's avatar
Kitware Robot committed
231
    return 0;
Kitware Robot's avatar
Kitware Robot committed
232
  }
Kitware Robot's avatar
Kitware Robot committed
233 234 235 236

  /* Forward to our internal implementation.  */
  return kwsysSystem__ParseUnixCommand(command, flags);
}