From b7e009a98698c4ed81b16cbc274a3b47793c1bab Mon Sep 17 00:00:00 2001 From: cbdev Date: Sat, 3 Jun 2017 23:02:46 +0200 Subject: Config parser --- config.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 config.c (limited to 'config.c') diff --git a/config.c b/config.c new file mode 100644 index 0000000..de6767d --- /dev/null +++ b/config.c @@ -0,0 +1,138 @@ +#include +#include +#include "midimonster.h" +#include "config.h" +#include "backend.h" + +enum { + none, + backend_cfg, + instance_cfg, + map +} parser_state = none; + +backend* current_backend = NULL; +instance* current_instance = NULL; + +static char* config_trim_line(char* in){ + ssize_t u; + //trim front + for(; *in && !isgraph(*in); in++){ + } + + //trim back + for(u = strlen(in); u >= 0 && !isgraph(in[u]); u--){ + in[u] = 0; + } + + return in; +} + +int config_read(char* cfg_file){ + int rv = 1; + size_t line_alloc = 0; + ssize_t status; + char* line_raw = NULL, *line, *separator; + FILE* source = fopen(cfg_file, "r"); + if(!source){ + fprintf(stderr, "Failed to open configuration file for reading\n"); + return 1; + } + + for(status = getline(&line_raw, &line_alloc, source); status >= 0; status = getline(&line_raw, &line_alloc, source)){ + line = config_trim_line(line_raw); + if(*line == ';' || strlen(line) == 0){ + //skip comments + continue; + } + if(*line == '[' && line[strlen(line) - 1] == ']'){ + if(!strncmp(line, "[backend ", 9)){ + //backend configuration + parser_state = backend_cfg; + line[strlen(line) - 1] = 0; + current_backend = backend_match(line + 9); + + if(!current_backend){ + fprintf(stderr, "Cannot configure unknown backend %s\n", line + 9); + goto bail; + } + } + else if(!strcmp(line, "[map]")){ + //mapping configuration + parser_state = map; + } + else{ + //backend instance configuration + parser_state = instance_cfg; + + //trim braces + line[strlen(line) - 1] = 0; + line++; + + //find separating space and terminate + for(separator = line; *separator && *separator != ' '; separator++){ + } + if(!*separator){ + fprintf(stderr, "No instance name specified for backend %s\n", line); + goto bail; + } + *separator = 0; + separator++; + + current_backend = backend_match(line); + if(!current_backend){ + fprintf(stderr, "No such backend %s\n", line); + goto bail; + } + + current_instance = current_backend->create(); + if(!current_instance){ + fprintf(stderr, "Failed to instantiate backend %s\n", line); + goto bail; + } + + current_instance->name = strdup(separator); + current_instance->backend = current_backend; + fprintf(stderr, "Created %s instance %s\n", line, separator); + } + } + else{ + //pass to parser + //find separator + for(separator = line; *separator && *separator != '='; separator++){ + } + + if(!*separator){ + fprintf(stderr, "No assignment: %s\n", line); + goto bail; + } + + *separator = 0; + separator++; + + if(parser_state == backend_cfg && current_backend->conf(config_trim_line(line), config_trim_line(separator))){ + fprintf(stderr, "Failed to configure backend %s\n", current_backend->name); + goto bail; + } + else if(parser_state == instance_cfg && current_backend->conf_instance(current_instance, config_trim_line(line), config_trim_line(separator))){ + fprintf(stderr, "Failed to configure instance %s\n", current_instance->name); + goto bail; + } + else if(parser_state == map){ + //TODO map two channels + } + } + } + + rv = 0; +bail: + fclose(source); + free(line_raw); + return rv; +} + +void mm_instance_free(instance* inst){ + free(inst->name); + inst->name = NULL; + inst->backend = NULL; +} -- cgit v1.2.3