| /* See LICENSE.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("SDL_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("SDL_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; | |
| } |