#include "ktk_parse.h" #include #include #include struct ktkNumber ktk_parseNumber(const char *text) { struct ktkNumber number = {0, 0, 0}; char **words = NULL; size_t w; size_t word_count = ktk_explodeString(text, '~', 1024, &words); // stupidly get our type with substring search if (strstr(text, "%") != NULL) { number.type |= ktk_PERCENT; } else { number.type |= ktk_DIGIT; } // if we have more than one result from '-' explode, we are a range if (word_count > 1) { number.type |= ktk_RANGE; } if (word_count > 0) { number.a = atoi(words[0]); number.b = atoi(words[word_count-1]); number.type |= ktk_ISSET; } // free words for (w = 0; w < word_count; w++) { free(words[w]); } free(words); return number; } struct ktkNumberSet *ktk_parseNumberSet(struct ktkNumberSet *set, const char *text) { char **words = NULL; size_t w; size_t word_count = ktk_explodeString(text, ',', 1024, &words); // stupidly get our type with substring search // free words and parse at same time set->count = word_count; set->sets = realloc(set->sets, set->count*sizeof(struct ktkNumber)); for (w = 0; w < word_count; w++) { set->sets[w] = ktk_parseNumber(words[w]); free(words[w]); } free(words); return set; } int ktk_parseSFile(struct ktkProgram *program, const char *filename) { FILE *file; // our file pointer! :) char read_buf[16]; // file read buffer char *current_read = NULL; // dynamic char* for storing up to \n or \0 int current_read_size = 0; // size of current_read int current_read_i = 0; // index position of current_read int first_ch = 0; // used to remove beginning spaces int n; // fread count int i; // index for reading read_buf to current_read int state = 0; // our current operating state #define ktk_PARSE_NONE 0 // find a structure state #define ktk_PARSE_STRUCTURE 1 // read vars/find relation block state #define ktk_PARSE_RELATIONS 2 // find a relation state #define ktk_PARSE_RELATION_STRUCTURE 3// read relation structure vars #define ktk_PARSE_REPLACE 4 // read cell replace state #define ktk_PARSE_PATHS 5 // find a path definition #define ktk_PARSE_PATH_DEFINITION 6 // read path structure vars if ((file = fopen(filename, "r")) == NULL) { // TODO: set errcode return 1; } // read our file in 16-byte chunks while((n = fread(read_buf, 1, 16, file))) { read_buf[n] = '\0'; // resize current_read to fit at least n current_read_size += n; current_read = realloc(current_read, current_read_size*sizeof(char)); // handle newlines, read read_buf into current_read, etc. for (i = 0; i < n; i++) { // we found a non-space/tab, mark it as so if (read_buf[i] != ' ' && read_buf[i] != '\t') first_ch = 1; // skip empty spaces if we haven't found a regular char yet if ((read_buf[i] == ' ' || read_buf[i] == '\t') && first_ch != 1) continue; // end of line/file found, let's read it for data now if (read_buf[i] == '\n' || read_buf[i] == '\0') { current_read[current_read_i] = '\0'; // use exploded strings to acquire variables and values char **words = NULL; // exploded results int word_count = 0; // count of words read // **** read logic section **** if (state == ktk_PARSE_NONE) { word_count = ktk_explodeString(current_read, ' ', 1, &words); // word count should be 2, for "structure {" if (word_count > 1) { if (words[1][0] == '{') { // create and initialize new structure program->structure_count++; program->structures = realloc(program->structures, program->structure_count*(sizeof(struct ktkStructure))); program->structures[program->structure_count-1] = ktk_STRUCTURE_DEFAULT; program->structure_name = realloc(program->structure_name, program->structure_count*(sizeof(char*))); // copy string over to structure_name size_t name_size = strlen(words[0])+1; program->structure_name[program->structure_count-1] = malloc(name_size*sizeof(char)); memcpy(program->structure_name[program->structure_count-1], words[0], name_size); // copy string to structure's name program->structures[program->structure_count-1].name = malloc(name_size*sizeof(char)); memcpy(program->structures[program->structure_count-1].name, words[0], name_size); state = ktk_PARSE_STRUCTURE; } else { // it's garbage } } } else if (state == ktk_PARSE_STRUCTURE) { // ** structure reading logic word_count = ktk_explodeString(current_read, ' ', 1, &words); if (word_count == 1) { if (words[0][0] == '}') { state = ktk_PARSE_NONE; } else { ktk_parseSVars(&program->structures[program->structure_count-1], words, 1); } } else if (word_count == 2) { if (words[1][0] == '{') { if (strcmp(words[0], "relations") == 0) { state = ktk_PARSE_RELATIONS; } else if (strcmp(words[0], "replace") == 0) { state = ktk_PARSE_REPLACE; } else if (strcmp(words[0], "paths") == 0) { state = ktk_PARSE_PATHS; } } else { ktk_parseSVars(&program->structures[program->structure_count-1], words, 2); } } // ** end structure reading logic } else if (state == ktk_PARSE_RELATIONS) { // ** relation reading logic if ((word_count = ktk_explodeString(current_read, ' ', 1, &words)) >= 1) { if (words[1][0] == '{') { // I'm bad. :) program->structures[program->structure_count-1].relation_count++; program->structures[program->structure_count-1].relations = realloc(program->structures[program->structure_count-1].relations, program->structures[program->structure_count-1].relation_count*sizeof(struct ktkRelation)); program->structures[program->structure_count-1].relations[program->structures[program->structure_count-1].relation_count-1] = ktk_RELATION_DEFAULT; size_t name_size = strlen(words[0])+1; program->structures[program->structure_count-1].relations[program->structures[program->structure_count-1].relation_count-1].name = malloc(name_size*sizeof(char)); memcpy(program->structures[program->structure_count-1].relations[program->structures[program->structure_count-1].relation_count-1].name, words[0], name_size); state = ktk_PARSE_RELATION_STRUCTURE; } else if (words[0][0] == '}') { state = ktk_PARSE_STRUCTURE; } } // ** relation reading logic } else if (state == ktk_PARSE_RELATION_STRUCTURE) { word_count = ktk_explodeString(current_read, ' ', 1, &words); if (word_count == 1) { if (words[0][0] == '}') { state = ktk_PARSE_RELATIONS; } else { ktk_parseSRelation(&(program->structures[program->structure_count-1].relations[program->structures[program->structure_count-1].relation_count-1]), words, word_count); } } else if (word_count == 2) { ktk_parseSRelation(&(program->structures[program->structure_count-1].relations[program->structures[program->structure_count-1].relation_count-1]), words, word_count); } // ** replace reading logic } else if (state == ktk_PARSE_REPLACE) { word_count = ktk_explodeString(current_read, ' ', 1, &words); if (word_count == 1) { if (words[0][0] == '}') { state = ktk_PARSE_STRUCTURE; } } else if (word_count == 2) { if (strcmp(words[0], "id_1") == 0) { ktk_parseNumberSet(&(program->structures[program->structure_count-1].replace_id_1), words[1]); } else if (strcmp(words[0], "id_2") == 0) { ktk_parseNumberSet(&(program->structures[program->structure_count-1].replace_id_2), words[1]); } } // ** paths reading logic } else if (state == ktk_PARSE_PATHS) { word_count = ktk_explodeString(current_read, ' ', 1, &words); if (word_count >= 1) { if (words[1][0] == '{') { // I'm bad. :) program->structures[program->structure_count-1].path_count++; program->structures[program->structure_count-1].paths = realloc(program->structures[program->structure_count-1].paths, program->structures[program->structure_count-1].path_count*sizeof(struct ktkPath)); program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1] = ktk_PATH_DEFAULT; size_t name_size = strlen(words[0])+1; program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1].name = malloc(name_size*sizeof(char)); memcpy(program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1].name, words[0], name_size); state = ktk_PARSE_PATH_DEFINITION; } else if (words[0][0] == '}') { state = ktk_PARSE_STRUCTURE; } } } else if (state == ktk_PARSE_PATH_DEFINITION) { word_count = ktk_explodeString(current_read, ' ', 1, &words); if (word_count == 1) { if (words[0][0] == '}') { state = ktk_PARSE_PATHS; } else { ktk_parseSPath(&(program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1]), words, word_count); } } else if (word_count == 2) { ktk_parseSPath(&(program->structures[program->structure_count-1].paths[program->structures[program->structure_count-1].path_count-1]), words, word_count); } } // **** end logic section **** // free our explode results int w; for (w = 0; w < word_count; w++) { free(words[w]); } free(words); // free our current read and reset to defaults first_ch = 0; current_read_i = 0; free(current_read); current_read = NULL; current_read = realloc(current_read, current_read_size*sizeof(char)); } else { // normal characters are copied to current_read plainly current_read[current_read_i++] = read_buf[i]; } } } fclose(file); return 0; } int ktk_parseSVars(struct ktkStructure *structure, const char **vars, size_t var_count) { if (var_count == 0) { return 1; } else if (var_count == 2) { if (strcmp(vars[0], "flags") == 0) { char **words = NULL; int w, word_count = 0; word_count = ktk_explodeString(vars[1], '|', 1024, &words); for (w = 0; w < word_count; w++) { if (strcmp(words[w], "WORLD") == 0) { structure->flags |= ktk_STRUCTURE_WORLD; } else if (strcmp(words[w], "FILL") == 0) { structure->flags |= ktk_STRUCTURE_FILL; } else if (strcmp(words[w], "BORDER") == 0) { structure->flags |= ktk_STRUCTURE_BORDER; } else if (strcmp(words[w], "ORIGIN") == 0) { structure->flags |= ktk_STRUCTURE_ORIGIN; } else if (strcmp(words[w], "CONSTRAIN") == 0) { structure->flags |= ktk_STRUCTURE_CONSTRAIN; } else if (strcmp(words[w], "OVERLAP") == 0) { structure->flags |= ktk_STRUCTURE_OVERLAP; } else if (strcmp(words[w], "CIRCLE") == 0) { structure->flags |= ktk_STRUCTURE_CIRCLE; } else if (strcmp(words[w], "RECT") == 0) { structure->flags |= ktk_STRUCTURE_RECT; } free(words[w]); } free(words); } else if (strcmp(vars[0], "x") == 0) { structure->x = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "y") == 0) { structure->y = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "size_x") == 0) { structure->size_x = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "size_y") == 0) { structure->size_y = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "id_1") == 0) { ktk_parseNumberSet(&structure->id_1, vars[1]); } else if (strcmp(vars[0], "id_2") == 0) { ktk_parseNumberSet(&structure->id_2, vars[1]); } } return 0; } int ktk_parseSRelation(struct ktkRelation *relation, const char **vars, size_t var_count) { if (var_count == 2) { if (strcmp(vars[0], "flags") == 0) { char **words = NULL; int w, word_count = 0; word_count = ktk_explodeString(vars[1], '|', 1024, &words); for (w = 0; w < word_count; w++) { if (strcmp(words[w], "WORLD") == 0) { relation->flags |= ktk_STRUCTURE_WORLD; } else if (strcmp(words[w], "FILL") == 0) { relation->flags |= ktk_STRUCTURE_FILL; } else if (strcmp(words[w], "BORDER") == 0) { relation->flags |= ktk_STRUCTURE_BORDER; } else if (strcmp(words[w], "ORIGIN") == 0) { relation->flags |= ktk_STRUCTURE_ORIGIN; } else if (strcmp(words[w], "CONSTRAIN") == 0) { relation->flags |= ktk_STRUCTURE_CONSTRAIN; } else if (strcmp(words[w], "OVERLAP") == 0) { relation->flags |= ktk_STRUCTURE_OVERLAP; } else if (strcmp(words[w], "CIRCLE") == 0) { relation->flags |= ktk_STRUCTURE_CIRCLE; } else if (strcmp(words[w], "RECT") == 0) { relation->flags |= ktk_STRUCTURE_RECT; } free(words[w]); } free(words); } else if (strcmp(vars[0], "x") == 0) { relation->x = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "y") == 0) { relation->y = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "size_x") == 0) { relation->size_x = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "size_y") == 0) { relation->size_y = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "count") == 0) { relation->count = ktk_parseNumber(vars[1]); } } return 0; } int ktk_parseSPath(struct ktkPath *path, const char **vars, size_t var_count) { if (var_count == 2) { if (strcmp(vars[0], "flags") == 0) { char **words = NULL; int w, word_count = 0; word_count = ktk_explodeString(vars[1], '|', 1024, &words); for (w = 0; w < word_count; w++) { if (strcmp(words[w], "A*") == 0) { } else if (strcmp(words[w], "DUMB") == 0) { } else if (strcmp(words[w], "ALL") == 0) { } free(words[w]); } free(words); } else if (strcmp(vars[0], "to") == 0) { size_t size = strlen(vars[1])+1; path->to = malloc(size); memcpy(path->to, vars[1], size); } else if (strcmp(vars[0], "to_flags") == 0) { } else if (strcmp(vars[0], "to_x") == 0) { path->to_x = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "to_y") == 0) { path->to_y = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "from") == 0) { size_t size = strlen(vars[1])+1; path->from = malloc(size); memcpy(path->from, vars[1], size); } else if (strcmp(vars[0], "from_flags") == 0) { } else if (strcmp(vars[0], "from_x") == 0) { path->from_x = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "from_y") == 0) { path->from_y = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "x") == 0) { path->x = ktk_parseNumber(vars[1]); } else if (strcmp(vars[0], "y") == 0) { path->y = ktk_parseNumber(vars[1]); } } return 0; }