parsehelper.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /* See COPYING.txt for the full license governing this code. */
  2. /**
  3. * \file parsehelper.c
  4. *
  5. * Source file with some helper functions for parsing strings.
  6. */
  7. #include <SDL_test.h>
  8. #include "SDL_visualtest_harness_argparser.h"
  9. /* this function uses a DFA to count the number of tokens in an agruments string.
  10. state 0 is taken to be the start and end state. State 1 handles a double quoted
  11. argument and state 2 handles unquoted arguments. */
  12. static int
  13. CountTokens(char* args)
  14. {
  15. int index, num_tokens;
  16. int state; /* current state of the DFA */
  17. if(!args)
  18. return -1;
  19. index = 0;
  20. state = 0;
  21. num_tokens = 0;
  22. while(args[index])
  23. {
  24. char ch = args[index];
  25. switch(state)
  26. {
  27. case 0:
  28. if(ch == '\"')
  29. {
  30. state = 1;
  31. num_tokens++;
  32. }
  33. else if(!SDL_isspace(ch))
  34. {
  35. state = 2;
  36. num_tokens++;
  37. }
  38. break;
  39. case 1:
  40. if(ch == '\"')
  41. {
  42. state = 0;
  43. }
  44. break;
  45. case 2:
  46. if(SDL_isspace(ch))
  47. {
  48. state = 0;
  49. }
  50. break;
  51. }
  52. index++;
  53. }
  54. return num_tokens;
  55. }
  56. /* - size of tokens is num_tokens + 1
  57. - uses the same DFA used in CountTokens() to split args into an array of strings */
  58. static int
  59. TokenizeHelper(char* str, char** tokens, int num_tokens, int max_token_len)
  60. {
  61. int index, state, done, st_index, token_index;
  62. if(!str)
  63. {
  64. SDLTest_LogError("str argument cannot be NULL");
  65. return 0;
  66. }
  67. if(!tokens)
  68. {
  69. SDLTest_LogError("tokens argument cannot be NULL");
  70. return 0;
  71. }
  72. if(num_tokens <= 0)
  73. {
  74. SDLTest_LogError("num_tokens argument must be positive");
  75. return 0;
  76. }
  77. if(max_token_len <= 0)
  78. {
  79. SDLTest_LogError("max_token_len argument must be positive");
  80. return 0;
  81. }
  82. /* allocate memory for the tokens */
  83. tokens[num_tokens] = NULL;
  84. for(index = 0; index < num_tokens; index++)
  85. {
  86. tokens[index] = (char*)SDL_malloc(max_token_len);
  87. if(!tokens[index])
  88. {
  89. int i;
  90. SDLTest_LogError("malloc() failed.");
  91. for(i = 0; i < index; i++)
  92. SDL_free(tokens[i]);
  93. return 0;
  94. }
  95. tokens[index][0] = '\0';
  96. }
  97. /* copy the tokens into the array */
  98. st_index = 0;
  99. index = 0;
  100. token_index = 0;
  101. state = 0;
  102. done = 0;
  103. while(!done)
  104. {
  105. char ch = str[index];
  106. switch(state)
  107. {
  108. case 0:
  109. if(ch == '\"')
  110. {
  111. state = 1;
  112. st_index = index + 1;
  113. }
  114. else if(!ch)
  115. done = 1;
  116. else if(ch && !SDL_isspace(ch))
  117. {
  118. state = 2;
  119. st_index = index;
  120. }
  121. break;
  122. case 1:
  123. if(ch == '\"')
  124. {
  125. int i;
  126. state = 0;
  127. for(i = st_index; i < index; i++)
  128. {
  129. tokens[token_index][i - st_index] = str[i];
  130. }
  131. tokens[token_index][i - st_index] = '\0';
  132. token_index++;
  133. }
  134. else if(!ch)
  135. {
  136. SDLTest_LogError("Parsing Error!");
  137. done = 1;
  138. }
  139. break;
  140. case 2:
  141. if(!ch)
  142. done = 1;
  143. if(SDL_isspace(ch) || !ch)
  144. {
  145. int i;
  146. state = 0;
  147. for(i = st_index; i < index; i++)
  148. {
  149. tokens[token_index][i - st_index] = str[i];
  150. }
  151. tokens[token_index][i - st_index] = '\0';
  152. token_index++;
  153. }
  154. break;
  155. }
  156. index++;
  157. }
  158. return 1;
  159. }
  160. char**
  161. SDLVisualTest_Tokenize(char* str, int max_token_len)
  162. {
  163. int num_tokens;
  164. char** tokens;
  165. if(!str)
  166. {
  167. SDLTest_LogError("str argument cannot be NULL");
  168. return NULL;
  169. }
  170. if(max_token_len <= 0)
  171. {
  172. SDLTest_LogError("max_token_len argument must be positive");
  173. return NULL;
  174. }
  175. num_tokens = CountTokens(str);
  176. if(num_tokens == 0)
  177. return NULL;
  178. tokens = (char**)SDL_malloc(sizeof(char*) * (num_tokens + 1));
  179. if(!TokenizeHelper(str, tokens, num_tokens, max_token_len))
  180. {
  181. SDLTest_LogError("TokenizeHelper() failed");
  182. SDL_free(tokens);
  183. return NULL;
  184. }
  185. return tokens;
  186. }
  187. char**
  188. SDLVisualTest_ParseArgsToArgv(char* args)
  189. {
  190. char** argv;
  191. int num_tokens;
  192. num_tokens = CountTokens(args);
  193. if(num_tokens == 0)
  194. return NULL;
  195. /* allocate space for arguments */
  196. argv = (char**)SDL_malloc((num_tokens + 2) * sizeof(char*));
  197. if(!argv)
  198. {
  199. SDLTest_LogError("malloc() failed.");
  200. return NULL;
  201. }
  202. /* tokenize */
  203. if(!TokenizeHelper(args, argv + 1, num_tokens, MAX_SUT_ARGS_LEN))
  204. {
  205. SDLTest_LogError("TokenizeHelper() failed");
  206. SDL_free(argv);
  207. return NULL;
  208. }
  209. argv[0] = NULL;
  210. return argv;
  211. }