359 lines
16 KiB
C
359 lines
16 KiB
C
#include "ktk_parse.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
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;
|
|
}
|