diff --git a/tools/emile_config.c b/tools/emile_config.c new file mode 100644 index 0000000..1bd94d2 --- /dev/null +++ b/tools/emile_config.c @@ -0,0 +1,306 @@ +/* + * + * (c) 2007 Laurent Vivier + * + */ + +#include +#include +#include + +#include "emile_config.h" + +static int read_char(FILE* fd) +{ + int c; + + c = getc(fd); + + if (c == '#') + while ( (c = getc(fd)) != '\n'); + + return c; +} + +static void skip_blank(FILE* fd) +{ + int c; + + do { + c = read_char(fd); + } while ( (c == ' ') || (c == '\t') ); + + ungetc(c, fd); +} + +static void skip_blank_line(FILE* fd) +{ + int c; + + do { + skip_blank(fd); + c = read_char(fd); + } while (c == '\n'); + + ungetc(c, fd); +} + +static int read_word(FILE* fd, char* word) +{ + int index = 0; + int c; + + skip_blank(fd); + + c = read_char(fd); + if (c == -1) + return -1; + + if (c == '\n') + { + word[index++] = c; + word[index] = 0; + return index; + } + while ( (c != ' ') && (c != '\t') && (c != '\n') && (c != -1) ) + { + word[index++] = c; + c = read_char(fd); + } + ungetc(c, fd); + word[index] = 0; + return index; +} + +static int read_line(FILE* fd, char *name, char *value) +{ + int c; + int index = 0; + + skip_blank_line(fd); + + if (read_word(fd, name) == -1) + return -1; + + skip_blank(fd); + + c = read_char(fd); + while ( (c != '\n') && (c != -1) ) + { + value[index++] = c; + c = read_char(fd); + } + while ( (value[index-1] == ' ') || (value[index-1] == '\t') ) + index--; + value[index] = 0; +} + +static char* set_tag(char* string, int tag, char* value) +{ + int len; + + len = strlen(value); + *string++ = tag; + *string++ = len + 2; + strcpy(string, value); + string += len; + *string++ = 0; + + *string = CONFIG_END; /* mark end of string */ + + return string; +} + +static char* get_tag(char* string, int tag) +{ + while (*string != tag) + { + if (*string == CONFIG_END) + return NULL; + string++; + string += *string; + } + + return string + 2; +} + +static int read_header(FILE* fd, char* header, int size) +{ + int offset = 0; + char name[256]; + char value[1024]; + int len; + + rewind(fd); + + while (read_line(fd, name, value) != -1) + { + if (strcmp("partition", name) == 0) + { + header = set_tag(header, CONFIG_PARTITION, value); + } + else if (strcmp("first_level", name) == 0) + { + header = set_tag(header, CONFIG_FIRST_LEVEL, value); + } + else if (strcmp("second_level", name) == 0) + { + header = set_tag(header, CONFIG_SECOND_LEVEL, value); + } + else if (strcmp("timeout", name) == 0) + { + header = set_tag(header, CONFIG_TIMEOUT, value); + } + else if (strcmp("default", name) == 0) + { + header = set_tag(header, CONFIG_DEFAULT, value); + } + else if (strcmp("title", name) == 0) + { + fseek(fd, offset, SEEK_SET); + break; + } + else + { + fprintf(stderr, "ERROR: syntax error on word %s\n", name); + return -1; + } + offset = ftell(fd); + } + return 0; +} + +emile_config* emile_config_open(char* name) +{ + int ret; + FILE* fd; + emile_config* config; + + fd = fopen(name, "r"); + if (fd == NULL) + return NULL; + + config = (emile_config*)malloc(sizeof(emile_config)); + if (config == NULL) + goto close_file; + + memset(config, 0, sizeof(emile_config)); + + config->fd = fd; + config->header_size = 1024; + config->header = (char*)malloc(config->header_size); + if (config->header == NULL) + goto free_config; + config->current_size = 1024; + config->current = (char*)malloc(config->current_size); + if (config->current == NULL) + goto free_header; + + ret = read_header(config->fd, config->header, config->header_size); + if (ret == -1) + goto free_current; + + return config; +free_current: + free(config->current); +free_header: + free(config->header); +free_config: + free(config); +close_file: + fclose(fd); + return NULL; +} + +void emile_config_close(emile_config* config) +{ + free(config->current); + free(config->header); + fclose(config->fd); + free(config); +} + +static int read_description(FILE* fd, char* desc, int size) +{ + int offset = 0; + char name[256]; + char value[1024]; + int len; + int found = 0; + + while (read_line(fd, name, value) != -1) + { + if (strcmp("title", name) == 0) + { + if (found) + { + fseek(fd, offset, SEEK_SET); + break; + } + found = 1; + desc = set_tag(desc, CONFIG_TITLE, value); + } + else if (strcmp("kernel", name) == 0) + { + desc = set_tag(desc, CONFIG_KERNEL, value); + } + else if (strcmp("args", name) == 0) + { + desc = set_tag(desc, CONFIG_ARGS, value); + } + else if (strcmp("initrd", name) == 0) + { + desc = set_tag(desc, CONFIG_INITRD, value); + } + else + { + fprintf(stderr, "ERROR: syntax error on word %s\n", name); + return -1; + } + offset = ftell(fd); + } + return 0; +} + +int emile_config_read_next(emile_config* config) +{ + return read_description(config->fd, config->current, config->current_size); +} + +int emile_config_read_first_entry(emile_config* config) +{ + int offset = 0; + char name[256]; + char value[1024]; + + rewind(config->fd); + while (read_line(config->fd, name, value) != -1) + { + if (strcmp("title", name) == 0) + { + fseek(config->fd, offset, SEEK_SET); + break; + } + offset = ftell(config->fd); + } + return read_description(config->fd, config->current, config->current_size); +} + +char* emile_config_get(emile_config* config, int tag) +{ + switch(tag) + { + case CONFIG_PARTITION: + case CONFIG_FIRST_LEVEL: + case CONFIG_SECOND_LEVEL: + case CONFIG_TIMEOUT: + case CONFIG_DEFAULT: + return get_tag(config->header, tag); + case CONFIG_TITLE: + case CONFIG_KERNEL: + case CONFIG_ARGS: + case CONFIG_INITRD: + return get_tag(config->current, tag); + } + return NULL; +} diff --git a/tools/emile_config.h b/tools/emile_config.h new file mode 100644 index 0000000..a8e73eb --- /dev/null +++ b/tools/emile_config.h @@ -0,0 +1,34 @@ +/* + * + * (c) 2007 Laurent Vivier + * + */ + +typedef struct emile_config { + FILE* fd; + char* header; + int header_size; + char* current; + int current_size; +} emile_config; + +enum { + CONFIG_END, + CONFIG_PARTITION, + CONFIG_FIRST_LEVEL, + CONFIG_SECOND_LEVEL, + CONFIG_TIMEOUT, + CONFIG_DEFAULT, + CONFIG_TITLE, + CONFIG_KERNEL, + CONFIG_ARGS, + CONFIG_INITRD, +}; + +extern emile_config* emile_config_open(char* name); +extern void emile_config_close(emile_config* config); + +extern int emile_config_read_first_entry(emile_config* config); +extern int emile_config_read_next(emile_config* config); + +extern char* emile_config_get(emile_config* config, int tag);