System.c 7.0 KB

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