System.c 6.7 KB

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