proclib/ktk_parse.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;
}