]> git.itanic.dy.fi Git - log-plotter/commitdiff
Add primitive config file parsing support
authorTimo Kokkonen <timo.t.kokkonen@iki.fi>
Tue, 29 Oct 2013 19:41:26 +0000 (21:41 +0200)
committerTimo Kokkonen <timo.t.kokkonen@iki.fi>
Thu, 31 Oct 2013 19:17:43 +0000 (21:17 +0200)
This supports parsing "variable = value" style lines from a config
file. The file can also have blank lines and comments starting with
'#' character. Anything it doesn't understand are skipped.

Signed-off-by: Timo Kokkonen <timo.t.kokkonen@iki.fi>
Makefile
config.c [new file with mode: 0644]
config.h [new file with mode: 0644]
main.c
options.c
options.h

index 328d6a2dd365c717f1d5a50430e7e1632fb2e769..f77068675a1fa62f759dd273dfd807a21ec566f9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC=gcc
 LD=ld
 CFLAGS=-Wall -O2 -g -fPIC
 
 LD=ld
 CFLAGS=-Wall -O2 -g -fPIC
 
-LOG-PLOTTER_OBJS = baud.o main.o options.o trace.o data.o
+LOG-PLOTTER_OBJS = baud.o main.o options.o trace.o data.o config.o
 
 ALL_OBJS = $(LOG-PLOTTER_OBJS)
 ALL_DEBS = $(patsubst %.o,.%.o.d,$(ALL_OBJS))
 
 ALL_OBJS = $(LOG-PLOTTER_OBJS)
 ALL_DEBS = $(patsubst %.o,.%.o.d,$(ALL_OBJS))
diff --git a/config.c b/config.c
new file mode 100644 (file)
index 0000000..54f672e
--- /dev/null
+++ b/config.c
@@ -0,0 +1,135 @@
+#include <stdio.h>
+#include <glob.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "trace.h"
+
+static int parse_config_line(char *line, char **variable, char **value)
+{
+#define SKIP_UNTIL(_str, _cond)                \
+       while (*_str && (_cond))        \
+               _str++;
+
+       SKIP_UNTIL(line, isspace(*line));
+
+       /* Skip comments */
+       if (*line == '#')
+               return -1;
+
+       /* The actual variable name begins here */
+       *variable = line;
+
+       /* Find where the variable name ends */
+       SKIP_UNTIL(line, !isspace(*line) && *line != '=');
+
+       if (*line == '=') {
+               *line = '\0';
+               line++;
+               goto value_start;
+       }
+
+       /* If we encounter line end already, the line can't be valid */
+       if (!*line)
+               return -1;
+
+       /* Terminate the variable name */
+       *line = '\0';
+       line++;
+        
+       /* Find the equal sign */
+       SKIP_UNTIL(line, *line != '=');
+
+       if (*line != '=')
+               return -1;
+       line++;
+
+       SKIP_UNTIL(line, isspace(*line));
+
+value_start:
+       *value = line;
+
+       SKIP_UNTIL(line, *line != '\n' && *line != '#');
+       *line = 0;
+
+       return 0;
+}
+
+static int store_variable_value_to_plotter_config(const char *variable,
+                                               const char *value,
+                                               struct plotter_config *cfg)
+{
+#define TEST_STR_STORE_STR_RETURN(_cfg, _variable, _str, _value)       \
+       if (!strcmp(_variable, #_str) && !cfg->_str) {                  \
+               cfg->_str = strdup(_value);                             \
+               return 0;                                               \
+       }
+
+#define TEST_STR_STORE_INT_RETURN(_cfg, _variable, _str, _value)       \
+       if (!strcmp(_variable, #_str)) {                                \
+               cfg->_str = atoi(_value);                               \
+               return 0;                                               \
+       }
+
+       TEST_STR_STORE_STR_RETURN(cfg, variable, charger_name, value);
+       TEST_STR_STORE_STR_RETURN(cfg, variable, plotter_scripts_dir, value);
+       TEST_STR_STORE_STR_RETURN(cfg, variable, images_output_dir, value);
+       TEST_STR_STORE_STR_RETURN(cfg, variable, device_path, value);
+       TEST_STR_STORE_STR_RETURN(cfg, variable, log_path, value);
+       TEST_STR_STORE_INT_RETURN(cfg, variable, baudrate, value);
+
+       return -1;
+}
+
+static int read_config_file(FILE *file, struct plotter_config *cfg)
+{
+       char line[1024];
+       char *variable, *value;
+
+       while (fgets(line, sizeof(line), file)) {
+               if (parse_config_line(line, &variable, &value))
+                       continue;
+
+               if (!store_variable_value_to_plotter_config(variable, value,
+                                                               cfg))
+                       continue;
+
+               pr_debug("Discarding unsupported config variable %s\n",
+                       variable);
+       }
+
+       return 0;
+}
+
+int populate_config_data_from_file(const char *path,
+                               struct plotter_config *cfg)
+{
+       glob_t globbuf;
+       FILE *file;
+       int ret;
+
+       ret = glob(path, GLOB_TILDE, NULL, &globbuf);
+       if (ret)
+               return -1;
+
+       if (globbuf.gl_pathc == 0) {
+               pr_debug("No config file foud from path %s\n", path);
+               return -1;
+       }
+
+       if (globbuf.gl_pathc > 1) {
+               pr_warn("Found multiple config files from path %s, using the first one\n",
+                       path);
+       }
+
+       file = fopen(globbuf.gl_pathv[0], "r");
+       if (!file) {
+               pr_err("Failed to open config file %s: %m\n",
+                       globbuf.gl_pathv[0]);
+               return -1;
+       }
+
+       return read_config_file(file, cfg);
+}
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..9f817fc
--- /dev/null
+++ b/config.h
@@ -0,0 +1,18 @@
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+struct plotter_config {
+       char *charger_name;
+
+       char *plotter_scripts_dir;
+       char *images_output_dir;
+
+       char *device_path;
+       int baudrate;
+       char *log_path;
+};
+
+int populate_config_data_from_file(const char *path,
+                               struct plotter_config *cfg);
+
+#endif
diff --git a/main.c b/main.c
index 39ef41cd859ba328c23d8b556ae0f4c72d8f96c0..05e3390968d01a9f3c0801509b04b2406dffe2a3 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,8 +1,10 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <string.h>
 
 #include "options.h"
 
 #include "options.h"
+#include "config.h"
 #include "baud.h"
 #include "trace.h"
 #include "data.h"
 #include "baud.h"
 #include "trace.h"
 #include "data.h"
 int main(int argc, char *argv[])
 {
        struct plotter_options options;
 int main(int argc, char *argv[])
 {
        struct plotter_options options;
+       struct plotter_config cfg;
        int fd, baud, ret = 0, out_fd = 0;
 
        int fd, baud, ret = 0, out_fd = 0;
 
+       bzero(&cfg, sizeof(cfg));
+
        if (read_args(argc, argv, &options))
                return 1;
 
        if (read_args(argc, argv, &options))
                return 1;
 
+       if (options.config_file_path)
+               populate_config_data_from_file(options.config_file_path, &cfg);
+
        baud = options.baud_rate;
        fd = open_at_baud(options.device_path, &baud);
        if (fd < 0)
        baud = options.baud_rate;
        fd = open_at_baud(options.device_path, &baud);
        if (fd < 0)
index 48cd259a3fa754dcf79723229fbd9e1b56eb07b5..18db9c5e44e173ba1b24f70f4a44a44079187d6b 100644 (file)
--- a/options.c
+++ b/options.c
@@ -15,6 +15,7 @@ void print_help_and_die(const char *exec_name)
        pr_info("  -o, --output            logfile path, stdout only if omited\n");
        pr_info("  -v, --verbose           increase verbosity\n");
        pr_info("  -q, --quiet             decrease verbosity\n");
        pr_info("  -o, --output            logfile path, stdout only if omited\n");
        pr_info("  -v, --verbose           increase verbosity\n");
        pr_info("  -q, --quiet             decrease verbosity\n");
+       pr_info("  -c, --config=PATH       config file path\n");
        pr_info("  -h, --help              show this help\n");
 
        exit(0);
        pr_info("  -h, --help              show this help\n");
 
        exit(0);
@@ -37,9 +38,10 @@ int read_args(int argc, char *argv[], struct plotter_options *opts)
                { .val = 'b', .name = "baud", .has_arg = 1 },
                { .val = 'v', .name = "verbose", .has_arg = 2 },
                { .val = 'q', .name = "quiet", },
                { .val = 'b', .name = "baud", .has_arg = 1 },
                { .val = 'v', .name = "verbose", .has_arg = 2 },
                { .val = 'q', .name = "quiet", },
+               { .val = 'c', .name = "config", .has_arg = 1 },
                { .val = 'h', .name = "help", },
        };
                { .val = 'h', .name = "help", },
        };
-       char short_options[] = "d:o:b:vqh";
+       char short_options[] = "d:o:b:vqc:h";
 
        set_default_options(opts);
 
 
        set_default_options(opts);
 
@@ -68,6 +70,9 @@ int read_args(int argc, char *argv[], struct plotter_options *opts)
                        trace_level--;
                        pr_debug("Degreased trace level to %d\n", trace_level);
                        break;
                        trace_level--;
                        pr_debug("Degreased trace level to %d\n", trace_level);
                        break;
+               case 'c':
+                       opts->config_file_path = optarg;
+                       break;
                case 'h':
                        print_help_and_die(argv[0]);
                        break;
                case 'h':
                        print_help_and_die(argv[0]);
                        break;
index 5312e42ac879dc2f9dd62ec812bec0093a13a50e..8ec9abc67a15d1d8b51a2f92912523740e816d5c 100644 (file)
--- a/options.h
+++ b/options.h
@@ -5,6 +5,7 @@ struct plotter_options {
        char *device_path;
        char *output_path;
        int baud_rate;
        char *device_path;
        char *output_path;
        int baud_rate;
+       char *config_file_path;
 };
 
 int read_args(int argc, char *argv[], struct plotter_options *opts);
 };
 
 int read_args(int argc, char *argv[], struct plotter_options *opts);