System.c 7.9 KB

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