diff --git a/Makefile b/Makefile index cf7b049fc4480dd9ed30cd0566f54b72676ea9b5..18201813d5613e8ac5b1ec6ace02682487bd36f3 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ MODULES:=$(wildcard modules/*) export CCFLAGS LDFLAGS LDFLAGS_parse_config=-ldl -export-dynamic -all: $(LIBRARIES:%=build/%) $(MODULES) parse_config +all: $(LIBRARIES:%=build/%) $(MODULES) echo $(MODULES) echo $(CCFLAGS) @@ -34,18 +34,20 @@ $(MODULES): .PHONY: test test: all $(MAKE) -C test test - LD_LIBRARY_PATH=build \ - valgrind ./parse_config test/*/*.conf +# LD_LIBRARY_PATH=build \ +# valgrind ./parse_config test/*/*.conf # LD_LIBRARY_PATH=build HOME=$$(pwd)/test \ # valgrind -q --error-exitcode=1 test/test_c clean: - rm build/* + find build -type f -delete + rm *~ - -build/libmoberg.so: build/lib/moberg_driver.o +build/libmoberg.so: build/lib/moberg_config.o +build/libmoberg.so: build/lib/moberg_device.o build/libmoberg.so: build/lib/moberg_config_parser.o +build/lib/moberg_device.o: moberg_device.h build/parse_config.o: moberg_config_parser.h parse_config: build/moberg_driver.o parse_config: build/parse_config.o diff --git a/moberg.c b/moberg.c index 8df1bab409bbadb90400d05716680062e759421f..f89e8b2f927fde0c5acf48f7973a4cf23c4f7738 100644 --- a/moberg.c +++ b/moberg.c @@ -20,6 +20,7 @@ struct moberg_digital_in_t { }; struct moberg { + struct moberg_config *config; struct { int count; struct moberg_digital_in_t *value; @@ -42,9 +43,15 @@ static void parse_config_at( buf[statbuf.st_size] = 0; } printf("Parsing... %s %d %d\n", pathname, dirfd, fd); - struct moberg_config *config; - config = moberg_config_parse(buf); + struct moberg_config *config = moberg_config_parse(buf); + printf("-> %p\n", config); if (config) { + if (! moberg->config) { + moberg->config = config; + } else { + moberg_config_join(moberg->config, config); + moberg_config_free(config); + } } free(buf); } @@ -85,7 +92,10 @@ struct moberg *moberg_new( struct moberg_config *config) { struct moberg *result = malloc(sizeof(*result)); - if (result) { + if (! result) { + fprintf(stderr, "Failed to allocate moberg struct\n"); + } else { + result->config = NULL; if (! config) { /* Parse default configuration(s) */ const char * const *config_paths = xdgSearchableConfigDirectories(NULL); @@ -96,6 +106,7 @@ struct moberg *moberg_new( parse_config_at(result, dirfd1, "moberg.conf"); int dirfd2 = openat(dirfd1, "moberg.d", O_DIRECTORY); if (dirfd2 >= 0) { + parse_config_dir_at(result, dirfd2); parse_config_dir_at(result, dirfd2); close(dirfd2); } @@ -115,7 +126,10 @@ struct moberg *moberg_new( void moberg_free(struct moberg *moberg) { - free(moberg); + if (moberg) { + moberg_config_free(moberg->config); + free(moberg); + } } enum moberg_status moberg_start( diff --git a/moberg_config.c b/moberg_config.c new file mode 100644 index 0000000000000000000000000000000000000000..b9f4e1ce51a7c951e2686231eb07eecaf590431d --- /dev/null +++ b/moberg_config.c @@ -0,0 +1,99 @@ +#include <stdlib.h> +#include <string.h> +#include <moberg_config.h> + +#define LIST_COND_GROW(LIST, INDEX, ONERR) \ + ({ \ + if (LIST.capacity <= INDEX) { \ + int new_cap; \ + for (new_cap = 2 ; new_cap <= INDEX ; new_cap *= 2); \ + void *new = realloc(LIST.value, new_cap * sizeof(*LIST.value)); \ + if (! new) { ONERR; } \ + void *p = new + LIST.capacity * sizeof(*LIST.value); \ + memset(p, 0, (new_cap - LIST.capacity) * sizeof(*LIST.value)); \ + LIST.value = new; \ + LIST.capacity= new_cap; \ + } \ + }) + +#define LIST_SET(LIST, INDEX, VALUE, ONERR) \ + ( LIST_COND_GROW(LIST, INDEX, ONERR), \ + LIST.value[INDEX] = VALUE ) + +#define LIST_GET(LIST, INDEX, VALUE, ONERR) \ + ( LIST_COND_GROW(LIST, INDEX, ONERR), \ + LIST.value[INDEX] ) + +struct moberg_config +{ + struct device_entry { + struct device_entry *next; + struct moberg_device *device; + } *device; + struct { + int capacity; + struct analog_in_entry { + struct moberg_device* device; + struct moberg_device_analog_in *channel; + } *value; + } analog_in; +}; + +struct moberg_config *moberg_config_new() +{ + struct moberg_config *result = malloc(sizeof *result); + + result->device = NULL; + + return result; +} + +void moberg_config_free(struct moberg_config *config) +{ + struct device_entry *entry = config->device; + while (entry) { + struct device_entry *tmp = entry; + entry = entry->next; + moberg_device_free(tmp->device); + free(tmp); + } + free(config); +} + +int moberg_config_join(struct moberg_config *dest, + struct moberg_config *src) +{ + if (src && dest) { + struct device_entry **tail; + for (tail = &dest->device ; *tail ; tail = &(*tail)->next) { } + *tail = src->device; + src->device = NULL; + return 1; + } + return 0; +} + +int moberg_config_add_device(struct moberg_config *config, + struct moberg_device *device) +{ + struct device_entry *entry = malloc(sizeof(*entry)); + + entry->next = config->device; + entry->device = device; + config->device = entry; + + return 1; +} + +int moberg_config_add_analog_in(struct moberg_config *config, + int index, + struct moberg_device* device, + struct moberg_device_analog_in *channel) +{ + struct analog_in_entry e = { device, channel }; + LIST_SET(config->analog_in, index, e, goto err); + return 1; +err: + return 0; +} + diff --git a/moberg_config.h b/moberg_config.h index 832b10a5ac92f3bc6b7a448685836bca0f91fc9e..d8a9ef2a6879e247c9a6969f229b37f2135d5bff 100644 --- a/moberg_config.h +++ b/moberg_config.h @@ -1,6 +1,45 @@ #ifndef __MOBERG_CONFIG_H__ #define __MOBERG_CONFIG_H__ +#include <moberg_device.h> + struct moberg_config; +struct moberg_config *moberg_config_new(); + +void moberg_config_free(struct moberg_config *config); + +int moberg_config_join(struct moberg_config *dest, + struct moberg_config *src); + +int moberg_config_add_device(struct moberg_config *config, + struct moberg_device *device); + +int moberg_config_add_analog_in(struct moberg_config *config, + int index, + struct moberg_device* device, + struct moberg_device_analog_in *channel); + +int moberg_config_add_analog_out(struct moberg_config *config, + int index, + struct moberg_device* device, + struct moberg_device_analog_out *channel); + +int moberg_config_add_digital_in(struct moberg_config *config, + int index, + struct moberg_device* device, + struct moberg_device_digital_in *channel); + +int moberg_config_add_digital_out(struct moberg_config *config, + int index, + struct moberg_device* device, + struct moberg_device_digital_out *channel); + +int moberg_config_add_encoder_in(struct moberg_config *config, + int index, + struct moberg_device* device, + struct moberg_device_encoder_in *channel); + + + #endif diff --git a/moberg_config_parser.c b/moberg_config_parser.c index 27b61c63677326dee15c0730dcc43dbbe08fe6e9..3ede13b07b6c73539ea98d9aeebb78192d9e087f 100644 --- a/moberg_config_parser.c +++ b/moberg_config_parser.c @@ -7,7 +7,6 @@ #include <string.h> #include <moberg_config_parser.h> #include <moberg_config_parser_module.h> -#include <moberg_driver.h> #include <moberg_device.h> typedef enum moberg_config_parser_token_kind kind_t; @@ -17,6 +16,7 @@ typedef struct moberg_config_parser_ident ident_t; #define MAX_EXPECTED 10 typedef struct moberg_config_parser_context { + struct moberg_config *config; const char *buf; /* Pointer to data to be parsed */ const char *p; /* current parse location */ token_t token; @@ -287,74 +287,78 @@ void moberg_config_parser_failed( } -static int parse_map_range(context_t *c) +static int parse_map_range(context_t *c, + struct moberg_device_map_range *range) { - token_t low, high; - if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; } - if (! acceptsym(c, tok_INTEGER, &low)) { goto err; } + token_t min, max; + if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; } + if (! acceptsym(c, tok_INTEGER, &min)) { goto syntax_err; } if (acceptsym(c, tok_COLON, NULL)) { - if (! acceptsym(c, tok_INTEGER, &high)) { goto err; } + if (! acceptsym(c, tok_INTEGER, &max)) { goto syntax_err; } } else { - high = low; + max = min; } - if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; } + if (! acceptsym(c, tok_RBRACKET, NULL)) { goto syntax_err; } + if (! range) { + fprintf(stderr, "Range is NULL\n"); + goto err; + } + range->min = min.u.integer.value; + range->max = max.u.integer.value; return 1; -err: +syntax_err: moberg_config_parser_failed(c, stderr); - exit(1); +err: return 0; } static int parse_map(context_t *c, - struct moberg_driver *driver) + struct moberg_device *device) { - if (acceptkeyword(c, "analog_in") || - acceptkeyword(c, "analog_out") || - acceptkeyword(c, "digital_in") || - acceptkeyword(c, "digital_out") || - acceptkeyword(c, "encoder_in")) { - if (! parse_map_range(c)) { goto err; } - if (! acceptsym(c, tok_EQUAL, NULL)) { goto err; } - driver->module.parse_map(c, 0); - if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; } - } else { - goto err; - } + struct moberg_device_map_range range; + + if (acceptkeyword(c, "analog_in")) { range.kind = map_analog_in; } + else if (acceptkeyword(c, "analog_out")) { range.kind = map_analog_out; } + else if (acceptkeyword(c, "digital_in")) { range.kind = map_digital_in; } + else if (acceptkeyword(c, "digital_out")) { range.kind = map_digital_out; } + else if (acceptkeyword(c, "encoder_in")) { range.kind = map_encoder_in; } + else { goto syntax_err; } + if (! parse_map_range(c, &range)) { goto syntax_err; } + if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; } + if (! moberg_device_parse_map(device, c, range)) { goto err; } + if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; } return 1; -err: +syntax_err: moberg_config_parser_failed(c, stderr); - exit(1); +err: return 0; } -struct moberg_device *parse_device(context_t *c, - struct moberg_driver *driver) +static int parse_device(context_t *c, + struct moberg_device *device) { - struct moberg_device *result = moberg_device_new(driver); - if (! result) { - goto err; - } - if (! acceptsym(c, tok_LBRACE, NULL)) { goto syntax_err; } for (;;) { if (acceptkeyword(c, "config")) { + moberg_device_parse_config(device, c); +/* void *config = driver->module.parse_config(c); result->add_config(config); free(config); +*/ } else if (acceptkeyword(c, "map")) { - result->add_map(parse_map(c, driver)); + if (! parse_map(c, device)) { goto err; } } else if (acceptsym(c, tok_RBRACE, NULL)) { break; } else { goto syntax_err; } } - return result; + return 1; syntax_err: moberg_config_parser_failed(c, stderr); err: - moberg_device_free(result); - return NULL; + return 0; } static int parse(context_t *c) @@ -364,24 +368,31 @@ static int parse(context_t *c) break; } else { token_t t; - struct moberg_driver *driver; + struct moberg_device *device; if (! acceptkeyword(c, "driver")) { goto syntax_err; } if (! acceptsym(c, tok_LPAREN, NULL)) { goto syntax_err; } if (! acceptsym(c, tok_IDENT, &t)) { goto syntax_err; } if (! acceptsym(c, tok_RPAREN, NULL)) { goto syntax_err; } - - if (! (driver = moberg_driver_open(t.u.ident))) { - fprintf(stderr, "Could not open driver '%.*s'\n", + + char *name = strndup(t.u.ident.value, t.u.ident.length); + if (! name) { + fprintf(stderr, "Failed to allocate driver name '%.*s'\n", t.u.ident.length, t.u.ident.value); goto err; } - struct moberg_device *device = parse_device(c, driver); - moberg_driver_close(driver); - if (! device) { + device = moberg_device_new(name); + free(name); + if (! device) { goto err; } + + if (! parse_device(c, device)) { + moberg_device_free(device); + goto err; + } + if (! moberg_config_add_device(c->config, device)) { + moberg_device_free(device); goto err; } - fprintf(stderr, "SAVE device\n"); } } return 1; @@ -396,13 +407,19 @@ struct moberg_config *moberg_config_parse(const char *buf) { context_t context; - context.expected.n = 0; - context.buf = buf; - context.p = context.buf; - nextsym(&context); - parse(&context); + context.config = moberg_config_new(); + if (context.config) { + context.expected.n = 0; + context.buf = buf; + context.p = context.buf; + nextsym(&context); + if (! parse(&context)) { + moberg_config_free(context.config); + context.config = NULL; + } + } - return NULL; + return context.config; } diff --git a/moberg_config_parser.h b/moberg_config_parser.h index 5990c0fa34c1b2b697f51f60b54050a59b7c02d0..cc50adcf09589a1b526a56c13fde16b9da1520c6 100644 --- a/moberg_config_parser.h +++ b/moberg_config_parser.h @@ -3,6 +3,8 @@ #include <moberg_config.h> +struct moberg_config_parser_context; + struct moberg_config *moberg_config_parse(const char *buf); #endif diff --git a/moberg_config_parser_module.h b/moberg_config_parser_module.h index bcfd2c87e397f83b975a6fbf823dd837eaa8ac71..e51fb6e21d5275c0c07c609a4359b91a186a08e9 100644 --- a/moberg_config_parser_module.h +++ b/moberg_config_parser_module.h @@ -2,8 +2,8 @@ #define __MOBERG_CONFIG_PARSER_MODULE_H__ #include <stdio.h> +#include <moberg_config_parser.h> -struct moberg_config_parser_context; struct moberg_config_parser_token; enum moberg_config_parser_token_kind { diff --git a/moberg_device.c b/moberg_device.c new file mode 100644 index 0000000000000000000000000000000000000000..a7e2fae3ab965914179311d53166d72412b343af --- /dev/null +++ b/moberg_device.c @@ -0,0 +1,153 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <moberg_config.h> +#include <moberg_device.h> + +struct moberg_device { + void *driver_handle; + struct moberg_device_driver driver; + struct moberg_device_config *config; + struct moberg_device_map_range *range; +}; + +struct moberg_device *moberg_device_new(const char *driver) +{ + struct moberg_device *result = NULL; + + char *name = malloc(strlen("libmoberg_.so") + strlen(driver) + 1); + if (!name) { goto out; } + sprintf(name, "libmoberg_%s.so", driver); + void *handle = dlopen(name, RTLD_LAZY || RTLD_DEEPBIND); + if (! handle) { + fprintf(stderr, "Could not find driver %s\n", name); + goto free_name; + } + struct moberg_device_driver *device_driver = + (struct moberg_device_driver *) dlsym(handle, "moberg_device_driver"); + if (! device_driver) { + fprintf(stderr, "No moberg_device_driver in driver %s\n", name); + goto dlclose_driver; + } + result = malloc(sizeof(*result)); + if (! result) { + fprintf(stderr, "Could not allocate result for %s\n", name); + goto dlclose_driver; + } + result->driver_handle = handle; + result->driver = *device_driver; + result->config = NULL; + goto free_name; + +dlclose_driver: + dlclose(handle); +free_name: + free(name); +out: + return result; +} + +void moberg_device_free(struct moberg_device *device) +{ + device->driver.config_free(device->config); + free(device->config); + free(device); +} + +int moberg_device_parse_config(struct moberg_device *device, + struct moberg_config_parser_context *context) +{ + return device->driver.parse_config(device, context); +} + +int moberg_device_set_config(struct moberg_device *device, + struct moberg_device_config *config) +{ + if (device->config) { + device->driver.config_free(device->config); + free(device->config); + } + device->config = config; + return 1; +} + +int moberg_device_parse_map(struct moberg_device* device, + struct moberg_config_parser_context *context, + struct moberg_device_map_range range) +{ + int result; + struct moberg_device_map_range r = range; + device->range = &r; + result = device->driver.parse_map(device, context, range.kind); + device->range = NULL; + printf("RRR %d %d\n", r.min, r.max); + return result; +} + +int moberg_device_add_analog_in(struct moberg_device* device, + struct moberg_device_analog_in *channel) +{ + if (device->range->kind == map_analog_in && + device->range->min <= device->range->max) { + printf("Mapping %d\n", device->range->min); + // moberg_config_add_analog_in() + device->range->min++; + return 1; + } else { + return 0; + } +} + +int moberg_device_add_analog_out(struct moberg_device* device, + struct moberg_device_analog_out *channel) +{ + if (device->range->kind == map_analog_out && + device->range->min <= device->range->max) { + printf("Mapping %d\n", device->range->min); + device->range->min++; + return 1; + } else { + return 0; + } +} + +int moberg_device_add_digital_in(struct moberg_device* device, + struct moberg_device_digital_in *channel) +{ + if (device->range->kind == map_digital_in && + device->range->min <= device->range->max) { + printf("Mapping %d\n", device->range->min); + device->range->min++; + return 1; + } else { + return 0; + } +} + +int moberg_device_add_digital_out(struct moberg_device* device, + struct moberg_device_digital_out *channel) +{ + if (device->range->kind == map_digital_out && + device->range->min <= device->range->max) { + printf("Mapping %d\n", device->range->min); + device->range->min++; + return 1; + } else { + return 0; + } +} + +int moberg_device_add_encoder_in(struct moberg_device* device, + struct moberg_device_encoder_in *channel) +{ + if (device->range->kind == map_encoder_in && + device->range->min <= device->range->max) { + printf("Mapping %d\n", device->range->min); + device->range->min++; + return 1; + } else { + return 0; + } +} + diff --git a/moberg_device.h b/moberg_device.h index b792a758d30274288f243bda7c619a050296ff6c..c379b3d877471b0b687ef2ae0920bdc8c3bef2e5 100644 --- a/moberg_device.h +++ b/moberg_device.h @@ -1,13 +1,101 @@ #ifndef __MOBERG_DEVICE_H__ #define __MOBERG_DEVICE_H__ -struct moberg_device { - int (*add_config)(void *config); - int (*add_map)(int config); +#include <moberg_config.h> +#include <moberg_config_parser.h> + +struct moberg_device_map_range { + enum moberg_device_map_kind { + map_analog_in, + map_analog_out, + map_digital_in, + map_digital_out, + map_encoder_in + } kind; + int min; + int max; +}; + +struct moberg_device_analog_in { + struct moberg_device_analog_in_context *context; + int (*open)(struct moberg_device_analog_in_context *); + int (*close)(struct moberg_device_analog_in_context *); + int (*read)(struct moberg_device_analog_in_context *, double *value); +}; + +struct moberg_device_analog_out { + struct moberg_device_analog_out_context *context; + int (*open)(struct moberg_device_analog_out_context *); + int (*close)(struct moberg_device_analog_out_context *); + int (*write)(struct moberg_device_analog_out_context *, double value); +}; + +struct moberg_device_digital_in { + struct moberg_device_digital_in_context *context; + int (*open)(struct moberg_device_digital_in_context *); + int (*close)(struct moberg_device_digital_in_context *); + int (*read)(struct moberg_device_digital_in_context *, int *value); +}; + +struct moberg_device_digital_out { + struct moberg_device_digital_out_context *context; + int (*open)(struct moberg_device_digital_out_context *); + int (*close)(struct moberg_device_digital_out_context *); + int (*write)(struct moberg_device_digital_out_context *, int value); +}; + +struct moberg_device_encoder_in { + struct moberg_device_encoder_in_context *context; + int (*open)(struct moberg_device_encoder_in_context *); + int (*close)(struct moberg_device_encoder_in_context *); + int (*read)(struct moberg_device_encoder_in_context *, long *value); }; + +struct moberg_config_parser_context; +struct moberg_device; +struct moberg_device_config; -struct moberg_device *moberg_device_new(struct moberg_driver *driver); +struct moberg_device_driver { + int (*parse_config)( + struct moberg_device* device, + struct moberg_config_parser_context *context); + int (*parse_map)( + struct moberg_device* device, + struct moberg_config_parser_context *context, + enum moberg_device_map_kind kind); + int (*config_free)( + struct moberg_device_config *config); +}; + +struct moberg_device; + +struct moberg_device *moberg_device_new(const char *driver); void moberg_device_free(struct moberg_device *device); +int moberg_device_parse_config(struct moberg_device* device, + struct moberg_config_parser_context *context); + +int moberg_device_set_config(struct moberg_device* device, + struct moberg_device_config *config); + +int moberg_device_parse_map(struct moberg_device* device, + struct moberg_config_parser_context *context, + struct moberg_device_map_range range); + +int moberg_device_add_analog_in(struct moberg_device* device, + struct moberg_device_analog_in *channel); + +int moberg_device_add_analog_out(struct moberg_device* device, + struct moberg_device_analog_out *channel); + +int moberg_device_add_digital_in(struct moberg_device* device, + struct moberg_device_digital_in *channel); + +int moberg_device_add_digital_out(struct moberg_device* device, + struct moberg_device_digital_out *channel); + +int moberg_device_add_encoder_in(struct moberg_device* device, + struct moberg_device_encoder_in *channel); + #endif diff --git a/moberg_driver.c b/moberg_driver.c deleted file mode 100644 index 1780950ba5813a9930316001368aa8801805f675..0000000000000000000000000000000000000000 --- a/moberg_driver.c +++ /dev/null @@ -1,47 +0,0 @@ -#include <stddef.h> -#include <stdlib.h> -#include <stdio.h> -#include <moberg_driver.h> -#include <dlfcn.h> - -struct moberg_driver *moberg_driver_open(struct moberg_config_parser_ident id) -{ - struct moberg_driver *result = NULL; - - char *driver_name = malloc(sizeof("libmoberg_.so") + id.length + 1); - if (!driver_name) { goto out; } - sprintf(driver_name, "libmoberg_%.*s.so", id.length, id.value); - void *handle = dlopen(driver_name, RTLD_LAZY || RTLD_DEEPBIND); - if (! handle) { - fprintf(stderr, "Could not find driver %s\n", driver_name); - goto free_driver_name; - } - struct moberg_driver_module *module = - (struct moberg_driver_module *) dlsym(handle, "moberg_module"); - if (! module) { - fprintf(stderr, "No moberg_module in driver %s\n", driver_name); - goto dlclose_driver; - } - result = malloc(sizeof(*result)); - if (! result) { - fprintf(stderr, "Could not allocate result for %s\n", driver_name); - goto dlclose_driver; - } - result->handle = handle; - result->module = *module; - goto free_driver_name; - -dlclose_driver: - dlclose(handle); -free_driver_name: - free(driver_name); -out: - return result; -} - -void moberg_driver_close(struct moberg_driver *driver) -{ - dlclose(driver->handle); - free(driver); -} - diff --git a/moberg_driver.h b/moberg_driver.h deleted file mode 100644 index ca1b3051e12346b7749633120c1a878d5159e1ae..0000000000000000000000000000000000000000 --- a/moberg_driver.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __MOBERG_DRIVER_H__ -#define __MOBERG_DRIVER_H__ - -#include <moberg_config_parser_module.h> - -struct moberg_driver_device; - -struct moberg_driver_map { -}; - -typedef struct moberg_driver_device *(*moberg_driver_parse_config_t)( - struct moberg_config_parser_context *context); - -typedef struct moberg_driver_map (*moberg_driver_parse_map_t)( - struct moberg_config_parser_context *context, - enum moberg_config_parser_token_kind kind); - -struct moberg_driver { - void *handle; - struct moberg_driver_module { - moberg_driver_parse_config_t parse_config; - moberg_driver_parse_map_t parse_map; - } module; -}; - -struct moberg_driver *moberg_driver_open(struct moberg_config_parser_ident id); - -void moberg_driver_close(struct moberg_driver *driver); - -void moberg_driver_device_free(struct moberg_driver_device *device); - - -#endif diff --git a/modules/comedi/comedi.c b/modules/comedi/comedi.c index 59977600872a1325503f8ca35385ccf138040b01..457c2a78c99ae43eb9bd13019ba9ac0c624b697d 100644 --- a/modules/comedi/comedi.c +++ b/modules/comedi/comedi.c @@ -1,5 +1,7 @@ +#include <moberg_config.h> +#include <moberg_config_parser.h> #include <moberg_config_parser_module.h> -#include <moberg_driver.h> +#include <moberg_device.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -9,6 +11,11 @@ typedef struct moberg_config_parser_token token_t; typedef struct moberg_config_parser_ident ident_t; typedef struct moberg_config_parser_context context_t; +struct moberg_device_map {}; +struct moberg_device_config { + char *device; +}; + static inline int acceptsym(context_t *c, kind_t kind, token_t *token) @@ -22,17 +29,13 @@ static inline int acceptkeyword(context_t *c, return moberg_config_parser_acceptkeyword(c, keyword); } -struct moberg_driver_device { - const char *device; -}; - - -static struct moberg_driver_device *parse_config( +static int parse_config( + struct moberg_device *device, struct moberg_config_parser_context *c) { - struct moberg_driver_device *result = malloc(sizeof *result); - if (! result) { - fprintf(stderr, "Failed to allocate moberg device\n"); + struct moberg_device_config *config = malloc(sizeof *config); + if (! config) { + fprintf(stderr, "Failed to allocate moberg device config\n"); goto err; } if (! acceptsym(c, tok_LBRACE, NULL)) { goto syntax_err; } @@ -44,7 +47,7 @@ static struct moberg_driver_device *parse_config( if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; } if (! acceptsym(c, tok_STRING, &device)) { goto syntax_err; } if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; } - result->device = strndup(device.u.string.value, device.u.string.length); + config->device = strndup(device.u.string.value, device.u.string.length); } else if (acceptkeyword(c, "config")) { if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; } if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; } @@ -75,18 +78,21 @@ static struct moberg_driver_device *parse_config( goto syntax_err; } } - return result; + moberg_device_set_config(device, config); + return 1; syntax_err: moberg_config_parser_failed(c, stderr); + free(config); err: - return NULL; + return 0; } -static struct moberg_driver_map parse_map( +static int parse_map( + struct moberg_device *device, struct moberg_config_parser_context *c, - enum moberg_config_parser_token_kind kind) + enum moberg_device_map_kind kind) { - struct moberg_driver_map result; + token_t min, max; if (! acceptsym(c, tok_LBRACE, NULL)) { goto err; } for (;;) { @@ -100,21 +106,50 @@ static struct moberg_driver_map parse_map( if (! acceptsym(c, tok_INTEGER, &route)) { goto err; } } if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; } - if (! acceptsym(c, tok_INTEGER, NULL)) { goto err; } + if (! acceptsym(c, tok_INTEGER, &min)) { goto err; } if (acceptsym(c, tok_COLON, NULL)) { - if (! acceptsym(c, tok_INTEGER, NULL)) { goto err; } + if (! acceptsym(c, tok_INTEGER, &max)) { goto err; } + } else { + max = min; + } + for (int i = min.u.integer.value ; i <= max.u.integer.value ; i++) { + switch (kind) { + case map_analog_in: + moberg_device_add_analog_in(device, NULL); + break; + case map_analog_out: + moberg_device_add_analog_out(device, NULL); + break; + case map_digital_in: + moberg_device_add_digital_in(device, NULL); + break; + case map_digital_out: + moberg_device_add_digital_out(device, NULL); + break; + case map_encoder_in: + moberg_device_add_encoder_in(device, NULL); + break; + } } if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; } if (! acceptsym(c, tok_COMMA, NULL)) { break; } + } if (! acceptsym(c, tok_RBRACE, NULL)) { goto err; } - return result; + return 1; err: moberg_config_parser_failed(c, stderr); - exit(1); + return 0; +} + +static int config_free(struct moberg_device_config *config) +{ + free(config->device); + return 1; } -struct moberg_driver_module moberg_module = { +struct moberg_device_driver moberg_device_driver = { .parse_config = parse_config, .parse_map = parse_map, + .config_free = config_free }; diff --git a/modules/serial2002/serial2002.c b/modules/serial2002/serial2002.c index 35a7d344afc18b26c580970da2739733241900e8..b1e2a8cb4d50b3ac035801b5692ae4d1d9073112 100644 --- a/modules/serial2002/serial2002.c +++ b/modules/serial2002/serial2002.c @@ -1,17 +1,18 @@ +#include <moberg_config.h> +#include <moberg_config_parser.h> #include <moberg_config_parser_module.h> -#include <moberg_driver.h> +#include <moberg_device.h> #include <stdio.h> #include <stdlib.h> #include <string.h> typedef enum moberg_config_parser_token_kind kind_t; typedef struct moberg_config_parser_token token_t; -typedef struct moberg_config_parser_ident ident_t; typedef struct moberg_config_parser_context context_t; static inline int acceptsym(context_t *c, - kind_t kind, - token_t *token) + kind_t kind, + token_t *token) { return moberg_config_parser_acceptsym(c, kind, token); } @@ -22,18 +23,18 @@ static inline int acceptkeyword(context_t *c, return moberg_config_parser_acceptkeyword(c, keyword); } -struct moberg_driver_device { - const char *device; +struct moberg_device_config { + char *device; int baud; }; - -static struct moberg_driver_device *parse_config( +static int parse_config( + struct moberg_device *device, struct moberg_config_parser_context *c) { - struct moberg_driver_device *result = malloc(sizeof *result); - if (! result) { - fprintf(stderr, "Failed to allocate moberg device\n"); + struct moberg_device_config *config = malloc(sizeof *config); + if (! config) { + fprintf(stderr, "Failed to allocate moberg device config\n"); goto err; } if (! acceptsym(c, tok_LBRACE, NULL)) { goto syntax_err; } @@ -45,49 +46,82 @@ static struct moberg_driver_device *parse_config( if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; } if (! acceptsym(c, tok_STRING, &device)) { goto syntax_err; } if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; } - result->device = strndup(device.u.string.value, device.u.string.length); + config->device = strndup(device.u.string.value, device.u.string.length); } else if (acceptkeyword(c, "baud")) { token_t baud; if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; } if (! acceptsym(c, tok_INTEGER, &baud)) { goto syntax_err; } if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; } - result->baud = baud.u.integer.value; + config->baud = baud.u.integer.value; } else { goto syntax_err; } } - return result; + moberg_device_set_config(device, config); + return 1; syntax_err: moberg_config_parser_failed(c, stderr); + free(config); err: - return NULL; + return 0; } -static struct moberg_driver_map parse_map( +static int parse_map( + struct moberg_device *device, struct moberg_config_parser_context *c, - enum moberg_config_parser_token_kind kind) + enum moberg_device_map_kind ignore) { - struct moberg_driver_map result; - - if (acceptkeyword(c, "analog_in") || - acceptkeyword(c, "analog_out") || - acceptkeyword(c, "digital_in") || - acceptkeyword(c, "digital_out") || - acceptkeyword(c, "encoder_in")) { - if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; } - if (! acceptsym(c, tok_INTEGER, NULL)) { goto err; } - if (acceptsym(c, tok_COLON, NULL)) { - if (! acceptsym(c, tok_INTEGER, NULL)) { goto err; } + enum moberg_device_map_kind kind; + token_t min, max; + + if (acceptkeyword(c, "analog_in")) { kind = map_analog_in; } + else if (acceptkeyword(c, "analog_out")) { kind = map_analog_out; } + else if (acceptkeyword(c, "digital_in")) { kind = map_digital_in; } + else if (acceptkeyword(c, "digital_out")) { kind = map_digital_out; } + else if (acceptkeyword(c, "encoder_in")) { kind = map_encoder_in; } + else { goto syntax_err; } + if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; } + if (! acceptsym(c, tok_INTEGER, &min)) { goto syntax_err; } + if (acceptsym(c, tok_COLON, NULL)) { + if (! acceptsym(c, tok_INTEGER, &max)) { goto syntax_err; } + } else { + max = min; + } + if (! acceptsym(c, tok_RBRACKET, NULL)) { goto syntax_err; } + for (int i = min.u.integer.value ; i <= max.u.integer.value ; i++) { + switch (kind) { + case map_analog_in: + moberg_device_add_analog_in(device, NULL); + break; + case map_analog_out: + moberg_device_add_analog_out(device, NULL); + break; + case map_digital_in: + moberg_device_add_digital_in(device, NULL); + break; + case map_digital_out: + moberg_device_add_digital_out(device, NULL); + break; + case map_encoder_in: + moberg_device_add_encoder_in(device, NULL); + break; } - if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; } } - return result; -err: + return 1; +syntax_err: moberg_config_parser_failed(c, stderr); - exit(1); + return 0; } -struct moberg_driver_module moberg_module = { +static int config_free(struct moberg_device_config *config) +{ + free(config->device); + return 1; +} + + +struct moberg_device_driver moberg_device_driver = { .parse_config = parse_config, .parse_map = parse_map, + .config_free = config_free }; diff --git a/parse_config.c b/parse_config.c deleted file mode 100644 index 2c2b398c0ce35f8cf63c48cceca7b4777953589e..0000000000000000000000000000000000000000 --- a/parse_config.c +++ /dev/null @@ -1,399 +0,0 @@ -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <moberg_config_parser.h> -#include <moberg_config_parser_module.h> -#include <moberg_driver.h> - -typedef enum moberg_config_parser_token_kind kind_t; -typedef struct moberg_config_parser_token token_t; -typedef struct moberg_config_parser_ident ident_t; -typedef struct moberg_config_parser_context context_t; - -static inline int acceptsym(context_t *c, - kind_t kind, - token_t *token) -{ - return moberg_config_parser_acceptsym(c, kind, token); -} - -static inline int acceptkeyword(context_t *c, - const char *keyword) -{ - return moberg_config_parser_acceptkeyword(c, keyword); -} - -#define MAX_EXPECTED 10 - -typedef struct moberg_config_parser_context { - char *buf; /* Pointer to data to be parsed */ - const char *p; /* current parse location */ - token_t token; - struct { - int n; - const char *what[MAX_EXPECTED]; - } expected; -} context_t; - -static const void nextsym_ident(context_t *c) -{ - c->token.kind = tok_IDENT; - c->token.u.ident.length = 1; - c->token.u.ident.value = c->p; - c->p++; - while (*c->p) { - switch (*c->p) { - case 'a'...'z': - case 'A'...'Z': - case '0'...'9': - case '_': - c->p++; - c->token.u.ident.length++; - break; - default: - return; - } - } -} - -static const void nextsym_integer(context_t *c) -{ - c->token.kind = tok_INTEGER; - c->token.u.integer.value = 0; - while (*c->p && '0' <= *c->p && *c->p <= '9') { - c->token.u.integer.value *= 10; - c->token.u.integer.value += *c->p - '0'; - c->p++; - } -} - -static const void nextsym_string(context_t *c) -{ - c->token.kind = tok_STRING; - c->p++; - c->token.u.string.value = c->p; - c->token.u.string.length = 0; - while (*c->p && *c->p != '"') { - if (*c->p == '\\') { - c->token.u.string.length++; - c->p++; - } - if (*c->p) { - c->token.u.string.length++; - c->p++; - } - } - c->p++; -} - -static int nextsym(context_t *c) -{ - c->token.kind = tok_none; - while (c->p && *c->p && c->token.kind == tok_none) { - if (c->p[0] == '/' && c->p[1] == '*') { - /* Skip comment */ - c->p += 2; - while (*c->p && (c->p[0] != '*' || c->p[1] != '/')) { - c->p++; - } - c->p += 2; - continue; - } - switch (*c->p) { - case ' ': - case '\t': - case '\n': - case '\r': - /* Skip whitespace */ - c->p++; - break; - case '(': - c->token.kind = tok_LPAREN; - c->p++; - break; - case ')': - c->token.kind = tok_RPAREN; - c->p++; - break; - case '{': - c->token.kind = tok_LBRACE; - c->p++; - break; - case '}': - c->token.kind = tok_RBRACE; - c->p++; - break; - case '[': - c->token.kind = tok_LBRACKET; - c->p++; - break; - case ']': - c->token.kind = tok_RBRACKET; - c->p++; - break; - case '=': - c->token.kind = tok_EQUAL; - c->p++; - break; - case ',': - c->token.kind = tok_COMMA; - c->p++; - break; - case ':': - c->token.kind = tok_COLON; - c->p++; - break; - case ';': - c->token.kind = tok_SEMICOLON; - c->p++; - break; - case '"': - nextsym_string(c); - break; - case 'a'...'z': - case 'A'...'Z': - case '_': - nextsym_ident(c); - break; - case '0'...'9': - nextsym_integer(c); - break; - default: - printf("UNEXPECTED %c\n\n", *c->p); - c->p++; - break; - } - } - if (c->token.kind != tok_none) { - return 1; - } else { - c->token.kind = tok_EOF; - return 0; - } -} - -static int peeksym(context_t *c, - kind_t kind, - token_t *token) -{ - if (c->token.kind == kind) { - if (token) { - *token = c->token; - } - return 1; - } - return 0; -} - -int moberg_config_parser_acceptsym(context_t *c, - kind_t kind, - token_t *token) -{ - if (c->token.kind == kind) { - if (token) { - *token = c->token; - } - nextsym(c); - c->expected.n = 0; - return 1; - } - if (c->expected.n < MAX_EXPECTED) { - const char *what = NULL; - switch (kind) { - case tok_none: break; - case tok_EOF: what = "<EOF>"; break; - case tok_LPAREN: what = "("; break; - case tok_RPAREN: what = ")"; break; - case tok_LBRACE: what = "{"; break; - case tok_RBRACE: what = "}"; break; - case tok_LBRACKET: what = "["; break; - case tok_RBRACKET: what = "]"; break; - case tok_EQUAL: what = "="; break; - case tok_COMMA: what = ","; break; - case tok_COLON: what = ":"; break; - case tok_SEMICOLON: what = ";"; break; - case tok_INTEGER: what = "<INTEGER>"; break; - case tok_IDENT: what = "<IDENT>"; break; - case tok_STRING: what = "<STRING>"; break; - } - if (what) { - c->expected.what[c->expected.n] = what; - c->expected.n++; - } - } - return 0; -} - -int moberg_config_parser_acceptkeyword(context_t *c, - const char *keyword) -{ - token_t t; - if (peeksym(c, tok_IDENT, &t) && - strncmp(keyword, t.u.ident.value, t.u.ident.length) == 0) { - nextsym(c); - c->expected.n = 0; - return 1; - } - if (c->expected.n < MAX_EXPECTED) { - c->expected.what[c->expected.n] = keyword; - c->expected.n++; - } - return 0; -} - -void moberg_config_parser_failed( - struct moberg_config_parser_context *c, - FILE *f) -{ - fprintf(f, "EXPECTED "); - for (int i = 0 ; i < c->expected.n; i++) { - if (i > 0) { - fprintf(f, " | "); - } - fprintf(f, "'%s'", c->expected.what[i]); - } - fprintf(f, "\nGOT: "); - switch (c->token.kind) { - case tok_none: break; - case tok_EOF: fprintf(f, "<EOF>"); break; - case tok_LPAREN: fprintf(f, "("); break; - case tok_RPAREN: fprintf(f, ")"); break; - case tok_LBRACE: fprintf(f, "{"); break; - case tok_RBRACE: fprintf(f, "}"); break; - case tok_LBRACKET: fprintf(f, "["); break; - case tok_RBRACKET: fprintf(f, "]"); break; - case tok_EQUAL: fprintf(f, "="); break; - case tok_COMMA: fprintf(f, ","); break; - case tok_COLON: fprintf(f, ":"); break; - case tok_SEMICOLON: fprintf(f, ";"); break; - case tok_INTEGER: - fprintf(f, "%d (<INTEGER>)", c->token.u.integer.value); - break; - case tok_IDENT: - fprintf(f, "%.*s (<IDENT>)", - c->token.u.ident.length, c->token.u.ident.value); - break; - case tok_STRING: - fprintf(f, "\"%.*s'\" (<STRING>)", - c->token.u.string.length, c->token.u.string.value); - break; - } - fprintf(f, "\n%s\n", c->p); -} - - -static int parse_map_range(context_t *c) -{ - token_t low, high; - if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; } - if (! acceptsym(c, tok_INTEGER, &low)) { goto err; } - if (acceptsym(c, tok_COLON, NULL)) { - if (! acceptsym(c, tok_INTEGER, &high)) { goto err; } - } else { - high = low; - } - if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; } - return 1; -err: - moberg_config_parser_failed(c, stderr); - exit(1); - return 0; -} - -static int parse_map(context_t *c, - struct moberg_driver *driver) -{ - if (acceptkeyword(c, "analog_in") || - acceptkeyword(c, "analog_out") || - acceptkeyword(c, "digital_in") || - acceptkeyword(c, "digital_out") || - acceptkeyword(c, "encoder_in")) { - if (! parse_map_range(c)) { goto err; } - if (! acceptsym(c, tok_EQUAL, NULL)) { goto err; } - driver->module.parse_map(c, 0); - if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; } - } else { - goto err; - } - return 1; -err: - moberg_config_parser_failed(c, stderr); - exit(1); - return 0; -} - -static int parse_device(context_t *c, - struct moberg_driver *driver) -{ - if (! acceptsym(c, tok_LBRACE, NULL)) { goto err; } - for (;;) { - if (acceptkeyword(c, "config")) { - driver->module.parse_config(c); - } else if (acceptkeyword(c, "map")) { - parse_map(c, driver); - } else if (acceptsym(c, tok_RBRACE, NULL)) { - break; - } else { - goto err; - } - } - return 1; -err: - return 0; -} - -static int parse_config(context_t *c) -{ - for (;;) { - if (acceptsym(c, tok_EOF, NULL)) { - break; - } else { - token_t t; - struct moberg_driver *driver; - - if (! acceptkeyword(c, "driver")) { goto syntax_err; } - if (! acceptsym(c, tok_LPAREN, NULL)) { goto syntax_err; } - if (! acceptsym(c, tok_IDENT, &t)) { goto syntax_err; } - if (! acceptsym(c, tok_RPAREN, NULL)) { goto syntax_err; } - - if (! (driver = moberg_driver_open(t.u.ident))) { goto driver_not_found; } - int OK = parse_device(c, driver); - moberg_driver_close(driver); - if (! OK) { goto err; } - } - } - return 1; -syntax_err: - moberg_config_parser_failed(c, stderr); - goto err; -driver_not_found: - fprintf(stderr, "Could not open\n"); - goto err; -err: - return 0; -} - -static char *read_fd(int fd) -{ - char *result = malloc(10000); /* HACK */ - int pos = read(fd, result, 10000); - result[pos] = 0; - return result; -} - -int main(int argc, char *argv[]) -{ - context_t context; - int fd = open(argv[1], O_RDONLY); - context.buf = read_fd(fd); - context.p = context.buf; - close(fd); - printf("%s\n", context.buf); - nextsym(&context); - parse_config(&context); - free(context.buf); -} diff --git a/test/.config/moberg.d/moberg.conf b/test/.config/moberg.d/moberg.conf index 9523ce1625d4cfb32c01da6c34920855acf2dbd8..8db1afc61935a9f1346a1c001d81ec74d5f017d6 100644 --- a/test/.config/moberg.d/moberg.conf +++ b/test/.config/moberg.d/moberg.conf @@ -7,11 +7,21 @@ driver(comedi) { } /* Moberg mapping[indices] = {driver specific}[indices] {driver specific} is parsed by parse_map in libmoberg_comedi.so */ - map analog_in[0:7] = { subdevice[0][0:7] }; + map analog_in[0:15] = { subdevice[0][0:15] }; map analog_out[0:1] = { subdevice[1][0:1] }; - map digital_in[0:1] = { subdevice[7][15] , - subdevice[7][2] }; - map digital_out[0:1] = { subdevice[7] route 16 [0:1] }; + map digital_in[0:7] = { subdevice[7][15], + subdevice[7][2], + subdevice[7][11], + subdevice[7][4], + subdevice[7][3], + subdevice[7][10], + subdevice[7][8], + subdevice[7][9] }; + map digital_out[0:7] = { subdevice[7] route 16 [0:1], + subdevice[7] route 16 [5:7], + subdevice[7] route 16 [14], + subdevice[7] route 16 [13], + subdevice[7] route 16 [12] }; } driver(serial2002) { config { @@ -21,5 +31,9 @@ driver(serial2002) { } /* Moberg mapping[indices] = {driver specific}[indices] {driver specific} is parsed by parse_map in libmoberg_serial2002.so */ + map analog_in[30:37] = analog_in[0:7] ; + map analog_out[30:37] = analog_out[0:7] ; map digital_in[30:37] = digital_in[0:7] ; + map digital_out[30:37] = digital_out[0:7] ; + map encoder_in[30:37] = encoder_in[0:7] ; } diff --git a/test/test_start_stop.c b/test/test_start_stop.c index d5fd56671db61aab842f20992880dd6f50d9f09b..393d9328350d50aef54094c852b7fddfbb4b9e49 100644 --- a/test/test_start_stop.c +++ b/test/test_start_stop.c @@ -8,5 +8,6 @@ int main(int argc, char *argv[]) moberg_start(moberg, stdout); printf("STOP:\n"); moberg_stop(moberg, stdout); + printf("DONE\n"); moberg_free(moberg); }