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