Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/kwsys/System.c
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
3
#include "kwsysPrivate.h"
4
#include KWSYS_HEADER(String.h)
5
#include KWSYS_HEADER(System.h)
6
7
/* Work-around CMake dependency scanning limitation.  This must
8
   duplicate the above list of headers.  */
9
#if 0
10
#  include "String.h.in"
11
#  include "System.h.in"
12
#endif
13
14
#include <stddef.h> /* ptrdiff_t */
15
#include <stdlib.h> /* malloc, free */
16
#include <string.h> /* memcpy */
17
18
#include <stdio.h>
19
20
#if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T
21
typedef ptrdiff_t kwsysSystem_ptrdiff_t;
22
#else
23
typedef int kwsysSystem_ptrdiff_t;
24
#endif
25
26
static int kwsysSystem__AppendByte(char const* local, char** begin, char** end,
27
                                   int* size, char c)
28
0
{
29
  /* Allocate space for the character.  */
30
0
  if ((*end - *begin) >= *size) {
31
0
    kwsysSystem_ptrdiff_t length = *end - *begin;
32
0
    char* newBuffer = (char*)malloc((size_t)(*size * 2));
33
0
    if (!newBuffer) {
34
0
      return 0;
35
0
    }
36
0
    memcpy(newBuffer, *begin, (size_t)(length) * sizeof(char));
37
0
    if (*begin != local) {
38
0
      free(*begin);
39
0
    }
40
0
    *begin = newBuffer;
41
0
    *end = *begin + length;
42
0
    *size *= 2;
43
0
  }
44
45
  /* Store the character.  */
46
0
  *(*end)++ = c;
47
0
  return 1;
48
0
}
49
50
static int kwsysSystem__AppendArgument(char** local, char*** begin,
51
                                       char*** end, int* size, char* arg_local,
52
                                       char** arg_begin, char** arg_end,
53
                                       int* arg_size)
54
0
{
55
  /* Append a null-terminator to the argument string.  */
56
0
  if (!kwsysSystem__AppendByte(arg_local, arg_begin, arg_end, arg_size,
57
0
                               '\0')) {
58
0
    return 0;
59
0
  }
60
61
  /* Allocate space for the argument pointer.  */
62
0
  if ((*end - *begin) >= *size) {
63
0
    kwsysSystem_ptrdiff_t length = *end - *begin;
64
0
    char** newPointers = (char**)malloc((size_t)(*size) * 2 * sizeof(char*));
65
0
    if (!newPointers) {
66
0
      return 0;
67
0
    }
68
0
    memcpy(newPointers, *begin, (size_t)(length) * sizeof(char*));
69
0
    if (*begin != local) {
70
0
      free(*begin);
71
0
    }
72
0
    *begin = newPointers;
73
0
    *end = *begin + length;
74
0
    *size *= 2;
75
0
  }
76
77
  /* Allocate space for the argument string.  */
78
0
  **end = (char*)malloc((size_t)(*arg_end - *arg_begin));
79
0
  if (!**end) {
80
0
    return 0;
81
0
  }
82
83
  /* Store the argument in the command array.  */
84
0
  memcpy(**end, *arg_begin, (size_t)(*arg_end - *arg_begin));
85
0
  ++(*end);
86
87
  /* Reset the argument to be empty.  */
88
0
  *arg_end = *arg_begin;
89
90
0
  return 1;
91
0
}
92
93
0
#define KWSYSPE_LOCAL_BYTE_COUNT 1024
94
0
#define KWSYSPE_LOCAL_ARGS_COUNT 32
95
static char** kwsysSystem__ParseUnixCommand(char const* command, int flags)
96
0
{
97
  /* Create a buffer for argument pointers during parsing.  */
98
0
  char* local_pointers[KWSYSPE_LOCAL_ARGS_COUNT];
99
0
  int pointers_size = KWSYSPE_LOCAL_ARGS_COUNT;
100
0
  char** pointer_begin = local_pointers;
101
0
  char** pointer_end = pointer_begin;
102
103
  /* Create a buffer for argument strings during parsing.  */
104
0
  char local_buffer[KWSYSPE_LOCAL_BYTE_COUNT];
105
0
  int buffer_size = KWSYSPE_LOCAL_BYTE_COUNT;
106
0
  char* buffer_begin = local_buffer;
107
0
  char* buffer_end = buffer_begin;
108
109
  /* Parse the command string.  Try to behave like a UNIX shell.  */
110
0
  char** newCommand = 0;
111
0
  char const* c = command;
112
0
  int in_argument = 0;
113
0
  int in_escape = 0;
114
0
  int in_single = 0;
115
0
  int in_double = 0;
116
0
  int failed = 0;
117
0
  for (; *c; ++c) {
118
0
    if (in_escape) {
119
      /* This character is escaped so do no special handling.  */
120
0
      if (!in_argument) {
121
0
        in_argument = 1;
122
0
      }
123
0
      if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end,
124
0
                                   &buffer_size, *c)) {
125
0
        failed = 1;
126
0
        break;
127
0
      }
128
0
      in_escape = 0;
129
0
    } else if (*c == '\\') {
130
      /* The next character should be escaped.  */
131
0
      in_escape = 1;
132
0
    } else if (*c == '\'' && !in_double) {
133
      /* Enter or exit single-quote state.  */
134
0
      if (in_single) {
135
0
        in_single = 0;
136
0
      } else {
137
0
        in_single = 1;
138
0
        if (!in_argument) {
139
0
          in_argument = 1;
140
0
        }
141
0
      }
142
0
    } else if (*c == '"' && !in_single) {
143
      /* Enter or exit double-quote state.  */
144
0
      if (in_double) {
145
0
        in_double = 0;
146
0
      } else {
147
0
        in_double = 1;
148
0
        if (!in_argument) {
149
0
          in_argument = 1;
150
0
        }
151
0
      }
152
0
    } else if (kwsysString_isspace(*c)) {
153
0
      if (in_argument) {
154
0
        if (in_single || in_double) {
155
          /* This space belongs to a quoted argument.  */
156
0
          if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin,
157
0
                                       &buffer_end, &buffer_size, *c)) {
158
0
            failed = 1;
159
0
            break;
160
0
          }
161
0
        } else {
162
          /* This argument has been terminated by whitespace.  */
163
0
          if (!kwsysSystem__AppendArgument(
164
0
                local_pointers, &pointer_begin, &pointer_end, &pointers_size,
165
0
                local_buffer, &buffer_begin, &buffer_end, &buffer_size)) {
166
0
            failed = 1;
167
0
            break;
168
0
          }
169
0
          in_argument = 0;
170
0
        }
171
0
      }
172
0
    } else {
173
      /* This character belong to an argument.  */
174
0
      if (!in_argument) {
175
0
        in_argument = 1;
176
0
      }
177
0
      if (!kwsysSystem__AppendByte(local_buffer, &buffer_begin, &buffer_end,
178
0
                                   &buffer_size, *c)) {
179
0
        failed = 1;
180
0
        break;
181
0
      }
182
0
    }
183
0
  }
184
185
  /* Finish the last argument.  */
186
0
  if (in_argument) {
187
0
    if (!kwsysSystem__AppendArgument(
188
0
          local_pointers, &pointer_begin, &pointer_end, &pointers_size,
189
0
          local_buffer, &buffer_begin, &buffer_end, &buffer_size)) {
190
0
      failed = 1;
191
0
    }
192
0
  }
193
194
  /* If we still have memory allocate space for the new command
195
     buffer.  */
196
0
  if (!failed) {
197
0
    kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin;
198
0
    newCommand = (char**)malloc((size_t)(n + 1) * sizeof(char*));
199
0
  }
200
201
0
  if (newCommand) {
202
    /* Copy the arguments into the new command buffer.  */
203
0
    kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin;
204
0
    memcpy(newCommand, pointer_begin, sizeof(char*) * (size_t)(n));
205
0
    newCommand[n] = 0;
206
0
  } else {
207
    /* Free arguments already allocated.  */
208
0
    while (pointer_end != pointer_begin) {
209
0
      free(*(--pointer_end));
210
0
    }
211
0
  }
212
213
  /* Free temporary buffers.  */
214
0
  if (pointer_begin != local_pointers) {
215
0
    free(pointer_begin);
216
0
  }
217
0
  if (buffer_begin != local_buffer) {
218
0
    free(buffer_begin);
219
0
  }
220
221
  /* The flags argument is currently unused.  */
222
0
  (void)flags;
223
224
  /* Return the final command buffer.  */
225
0
  return newCommand;
226
0
}
227
228
char** kwsysSystem_Parse_CommandForUnix(char const* command, int flags)
229
0
{
230
  /* Validate the flags.  */
231
0
  if (flags != 0) {
232
0
    return 0;
233
0
  }
234
235
  /* Forward to our internal implementation.  */
236
0
  return kwsysSystem__ParseUnixCommand(command, flags);
237
0
}