• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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