| /* See COPYING.txt for the full license governing this code. */ |
| /** |
| * \file parsehelper.c |
| * |
| * Source file with some helper functions for parsing strings. |
| */ |
| |
| #include <SDL_test.h> |
| #include "SDL_visualtest_harness_argparser.h" |
| |
| /* this function uses a DFA to count the number of tokens in an agruments string. |
| state 0 is taken to be the start and end state. State 1 handles a double quoted |
| argument and state 2 handles unquoted arguments. */ |
| static int |
| CountTokens(char* args) |
| { |
| int index, num_tokens; |
| int state; /* current state of the DFA */ |
| |
| if(!args) |
| return -1; |
| |
| index = 0; |
| state = 0; |
| num_tokens = 0; |
| while(args[index]) |
| { |
| char ch = args[index]; |
| switch(state) |
| { |
| case 0: |
| if(ch == '\"') |
| { |
| state = 1; |
| num_tokens++; |
| } |
| else if(!SDL_isspace(ch)) |
| { |
| state = 2; |
| num_tokens++; |
| } |
| break; |
| |
| case 1: |
| if(ch == '\"') |
| { |
| state = 0; |
| } |
| break; |
| |
| case 2: |
| if(SDL_isspace(ch)) |
| { |
| state = 0; |
| } |
| break; |
| } |
| index++; |
| } |
| return num_tokens; |
| } |
| |
| /* - size of tokens is num_tokens + 1 |
| - uses the same DFA used in CountTokens() to split args into an array of strings */ |
| static int |
| TokenizeHelper(char* str, char** tokens, int num_tokens, int max_token_len) |
| { |
| int index, state, done, st_index, token_index; |
| |
| if(!str) |
| { |
| SDLTest_LogError("str argument cannot be NULL"); |
| return 0; |
| } |
| if(!tokens) |
| { |
| SDLTest_LogError("tokens argument cannot be NULL"); |
| return 0; |
| } |
| if(num_tokens <= 0) |
| { |
| SDLTest_LogError("num_tokens argument must be positive"); |
| return 0; |
| } |
| if(max_token_len <= 0) |
| { |
| SDLTest_LogError("max_token_len argument must be positive"); |
| return 0; |
| } |
| |
| /* allocate memory for the tokens */ |
| tokens[num_tokens] = NULL; |
| for(index = 0; index < num_tokens; index++) |
| { |
| tokens[index] = (char*)SDL_malloc(max_token_len); |
| if(!tokens[index]) |
| { |
| int i; |
| SDLTest_LogError("malloc() failed."); |
| for(i = 0; i < index; i++) |
| SDL_free(tokens[i]); |
| return 0; |
| } |
| tokens[index][0] = '\0'; |
| } |
| |
| /* copy the tokens into the array */ |
| st_index = 0; |
| index = 0; |
| token_index = 0; |
| state = 0; |
| done = 0; |
| while(!done) |
| { |
| char ch = str[index]; |
| switch(state) |
| { |
| case 0: |
| if(ch == '\"') |
| { |
| state = 1; |
| st_index = index + 1; |
| } |
| else if(!ch) |
| done = 1; |
| else if(ch && !SDL_isspace(ch)) |
| { |
| state = 2; |
| st_index = index; |
| } |
| break; |
| |
| case 1: |
| if(ch == '\"') |
| { |
| int i; |
| state = 0; |
| for(i = st_index; i < index; i++) |
| { |
| tokens[token_index][i - st_index] = str[i]; |
| } |
| tokens[token_index][i - st_index] = '\0'; |
| token_index++; |
| } |
| else if(!ch) |
| { |
| SDLTest_LogError("Parsing Error!"); |
| done = 1; |
| } |
| break; |
| |
| case 2: |
| if(!ch) |
| done = 1; |
| if(SDL_isspace(ch) || !ch) |
| { |
| int i; |
| state = 0; |
| for(i = st_index; i < index; i++) |
| { |
| tokens[token_index][i - st_index] = str[i]; |
| } |
| tokens[token_index][i - st_index] = '\0'; |
| token_index++; |
| } |
| break; |
| } |
| index++; |
| } |
| return 1; |
| } |
| |
| char** |
| SDLVisualTest_Tokenize(char* str, int max_token_len) |
| { |
| int num_tokens; |
| char** tokens; |
| |
| if(!str) |
| { |
| SDLTest_LogError("str argument cannot be NULL"); |
| return NULL; |
| } |
| if(max_token_len <= 0) |
| { |
| SDLTest_LogError("max_token_len argument must be positive"); |
| return NULL; |
| } |
| |
| num_tokens = CountTokens(str); |
| if(num_tokens == 0) |
| return NULL; |
| |
| tokens = (char**)SDL_malloc(sizeof(char*) * (num_tokens + 1)); |
| if(!TokenizeHelper(str, tokens, num_tokens, max_token_len)) |
| { |
| SDLTest_LogError("TokenizeHelper() failed"); |
| SDL_free(tokens); |
| return NULL; |
| } |
| return tokens; |
| } |
| |
| char** |
| SDLVisualTest_ParseArgsToArgv(char* args) |
| { |
| char** argv; |
| int num_tokens; |
| |
| num_tokens = CountTokens(args); |
| if(num_tokens == 0) |
| return NULL; |
| |
| /* allocate space for arguments */ |
| argv = (char**)SDL_malloc((num_tokens + 2) * sizeof(char*)); |
| if(!argv) |
| { |
| SDLTest_LogError("malloc() failed."); |
| return NULL; |
| } |
| |
| /* tokenize */ |
| if(!TokenizeHelper(args, argv + 1, num_tokens, MAX_SUT_ARGS_LEN)) |
| { |
| SDLTest_LogError("TokenizeHelper() failed"); |
| SDL_free(argv); |
| return NULL; |
| } |
| argv[0] = NULL; |
| return argv; |
| } |