From 83cf5fbbdcc74e8d65627ed84f8906988aecfc4e Mon Sep 17 00:00:00 2001 From: Anders Blomdell <anders.blomdell@control.lth.se> Date: Tue, 19 Feb 2019 11:57:44 +0100 Subject: [PATCH] Parsing working for first example --- moberg_config_parser.h | 20 +++-- moberg_driver.c | 20 +++-- moberg_driver.h | 11 +-- modules/comedi/comedi.c | 79 ++++++++++++-------- modules/serial2002/serial2002.c | 88 +++++++++++++++++----- parse_config.c | 128 ++++++++++++++++++-------------- test/a/moberg.conf | 14 ++-- 7 files changed, 226 insertions(+), 134 deletions(-) diff --git a/moberg_config_parser.h b/moberg_config_parser.h index faf48f1..d968b50 100644 --- a/moberg_config_parser.h +++ b/moberg_config_parser.h @@ -8,14 +8,18 @@ struct moberg_config_parser_token; enum moberg_config_parser_token_kind { tok_none, - tok_LBRACE = '{', - tok_RBRACE = '}', - tok_LBRACKET = '[', - tok_RBRACKET = ']', - tok_EQUAL = '=', - tok_COLON = ':', - tok_SEMICOLON = ';', - tok_INTEGER = 256, + tok_EOF, + tok_LPAREN, + tok_RPAREN, + tok_LBRACE, + tok_RBRACE, + tok_LBRACKET, + tok_RBRACKET, + tok_EQUAL, + tok_COMMA, + tok_COLON, + tok_SEMICOLON, + tok_INTEGER, tok_IDENT, tok_STRING, }; diff --git a/moberg_driver.c b/moberg_driver.c index a732345..1780950 100644 --- a/moberg_driver.c +++ b/moberg_driver.c @@ -4,21 +4,29 @@ #include <moberg_driver.h> #include <dlfcn.h> -struct moberg_driver *moberg_open_driver(struct moberg_config_parser_ident id) +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); - printf("%s", driver_name); void *handle = dlopen(driver_name, RTLD_LAZY || RTLD_DEEPBIND); - if (! handle) { goto free_driver_name; } + 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) { goto dlclose_driver; } + if (! module) { + fprintf(stderr, "No moberg_module in driver %s\n", driver_name); + goto dlclose_driver; + } result = malloc(sizeof(*result)); - if (! result) { goto dlclose_driver; } + 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; @@ -31,7 +39,7 @@ out: return result; } -void moberg_close_driver(struct moberg_driver *driver) +void moberg_driver_close(struct moberg_driver *driver) { dlclose(driver->handle); free(driver); diff --git a/moberg_driver.h b/moberg_driver.h index e7986f8..a774da5 100644 --- a/moberg_driver.h +++ b/moberg_driver.h @@ -3,13 +3,12 @@ #include <moberg_config_parser.h> -struct moberg_driver_config { -}; +struct moberg_driver_device; struct moberg_driver_map { }; -typedef struct moberg_driver_config (*moberg_driver_parse_config_t)( +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)( @@ -24,9 +23,11 @@ struct moberg_driver { } module; }; -struct moberg_driver *moberg_open_driver(struct moberg_config_parser_ident id); +struct moberg_driver *moberg_driver_open(struct moberg_config_parser_ident id); + +void moberg_driver_close(struct moberg_driver *driver); -void moberg_close_driver(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 b91b055..f5ae143 100644 --- a/modules/comedi/comedi.c +++ b/modules/comedi/comedi.c @@ -22,57 +22,64 @@ 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_config parse_config( +static struct moberg_driver_device *parse_config( struct moberg_config_parser_context *c) { - struct moberg_driver_config result; - token_t t; - printf("PARSE_CONFIG %s\n", __FILE__); - printf("LBRACE %d", acceptsym(c, tok_LBRACE, &t)); + struct moberg_driver_device *result = malloc(sizeof *result); + if (! result) { + fprintf(stderr, "Failed to allocate moberg device\n"); + goto err; + } + if (! acceptsym(c, tok_LBRACE, NULL)) { goto syntax_err; } for (;;) { if (acceptsym(c, tok_RBRACE, NULL)) { break; } else if (acceptkeyword(c, "device")) { token_t device; - if (! acceptsym(c, tok_EQUAL, NULL)) { goto err; } - if (! acceptsym(c, tok_STRING, &device)) { goto err; } - if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; } + 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); } else if (acceptkeyword(c, "config")) { - if (! acceptsym(c, tok_EQUAL, NULL)) { goto err; } - if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; } + if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; } + if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; } for (;;) { if (acceptsym(c, tok_RBRACKET, NULL)) { break; } else if (acceptsym(c, tok_IDENT, NULL) || acceptsym(c, tok_STRING, NULL)) { } else { - goto err; + goto syntax_err; } } - if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; } + if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; } } else if (acceptkeyword(c, "modprobe")) { - if (! acceptsym(c, tok_EQUAL, NULL)) { goto err; } - if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; } + if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; } + if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; } for (;;) { if (acceptsym(c, tok_RBRACKET, NULL)) { break; } else if (acceptsym(c, tok_IDENT, NULL) || acceptsym(c, tok_STRING, NULL)) { } else { - goto err; + goto syntax_err; } } - if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; } + if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; } } else { - goto err; + goto syntax_err; } } - printf("PARSE_CONFIG DONE%s\n", __FILE__); return result; - err: +syntax_err: moberg_config_parser_failed(c, stderr); - exit(1); +err: + return NULL; } static struct moberg_driver_map parse_map( @@ -81,20 +88,26 @@ static struct moberg_driver_map parse_map( { struct moberg_driver_map result; - token_t t; - printf("PARSE_MAP %s\n", __FILE__); - if (! acceptkeyword(c, "subdevice") != 0) { goto err; } - if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; } - if (! acceptsym(c, tok_INTEGER, &t)) { goto err; } - if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; } - -/* - const char *buf = context->buf; - while (*buf && *buf != '}') { - buf++; + if (! acceptsym(c, tok_LBRACE, NULL)) { goto err; } + for (;;) { + token_t subdevice; + if (! acceptkeyword(c, "subdevice") != 0) { goto err; } + if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; } + if (! acceptsym(c, tok_INTEGER, &subdevice)) { goto err; } + if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; } + if (acceptkeyword(c, "route")) { + token_t route; + 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_COLON, NULL)) { + if (! acceptsym(c, tok_INTEGER, NULL)) { goto err; } + } + if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; } + if (! acceptsym(c, tok_COMMA, NULL)) { break; } } - context->buf = buf + 1; -*/ + if (! acceptsym(c, tok_RBRACE, NULL)) { goto err; } return result; err: moberg_config_parser_failed(c, stderr); diff --git a/modules/serial2002/serial2002.c b/modules/serial2002/serial2002.c index a34e526..af26b0c 100644 --- a/modules/serial2002/serial2002.c +++ b/modules/serial2002/serial2002.c @@ -1,38 +1,90 @@ #include <moberg_config_parser.h> #include <moberg_driver.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> -static struct moberg_driver_config parse_config( - struct moberg_config_parser_context *context) +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) { - struct moberg_driver_config result; + return moberg_config_parser_acceptkeyword(c, keyword); +} + +struct moberg_driver_device { + const char *device; + int baud; +}; + - printf("PARSE_CONFIG %s\n", __FILE__); -/* - const char *buf = context->buf; - while (*buf && *buf != '}') { - buf++; +static struct moberg_driver_device *parse_config( + struct moberg_config_parser_context *c) +{ + struct moberg_driver_device *result = malloc(sizeof *result); + if (! result) { + fprintf(stderr, "Failed to allocate moberg device\n"); + goto err; + } + if (! acceptsym(c, tok_LBRACE, NULL)) { goto syntax_err; } + for (;;) { + if (acceptsym(c, tok_RBRACE, NULL)) { + break; + } else if (acceptkeyword(c, "device")) { + token_t device; + 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); + } 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; + } else { + goto syntax_err; + } } - context->buf = buf + 1; -*/ return result; +syntax_err: + moberg_config_parser_failed(c, stderr); +err: + return NULL; } static struct moberg_driver_map parse_map( - struct moberg_config_parser_context *context, + struct moberg_config_parser_context *c, enum moberg_config_parser_token_kind kind) { struct moberg_driver_map result; - printf("PARSE_MAP %s\n", __FILE__); -/* - const char *buf = context->buf; - while (*buf && *buf != '}') { - buf++; + 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; } + } + if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; } } - context->buf = buf + 1; -*/ return result; +err: + moberg_config_parser_failed(c, stderr); + exit(1); } struct moberg_driver_module moberg_module = { diff --git a/parse_config.c b/parse_config.c index f6f4659..53bde81 100644 --- a/parse_config.c +++ b/parse_config.c @@ -27,7 +27,6 @@ static inline int acceptkeyword(context_t *c, } #define MAX_EXPECTED 10 -static char expected_char[256][2]; typedef struct moberg_config_parser_context { char *buf; /* Pointer to data to be parsed */ @@ -41,6 +40,7 @@ typedef struct moberg_config_parser_context { 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++; @@ -54,15 +54,9 @@ static const void nextsym_ident(context_t *c) c->token.u.ident.length++; break; default: - goto out; - break; + return; } } -out: ; - const char *v = c->token.u.ident.value; - int l = c->token.u.ident.length; - c->token.kind = tok_IDENT; - printf("IDENT: %.*s %d\n", l, v, c->token.kind); } static const void nextsym_integer(context_t *c) @@ -74,12 +68,10 @@ static const void nextsym_integer(context_t *c) c->token.u.integer.value += *c->p - '0'; c->p++; } - printf("INTEGER: %d\n", c->token.u.integer.value); } static const void nextsym_string(context_t *c) { - printf("STTRING"); c->token.kind = tok_STRING; c->p++; c->token.u.string.value = c->p; @@ -95,7 +87,6 @@ static const void nextsym_string(context_t *c) } } c->p++; - printf("STRING: %.*s\n", c->token.u.string.length, c->token.u.string.value); } static int nextsym(context_t *c) @@ -103,7 +94,6 @@ 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] == '*') { - printf("Skipping COMMENT\n"); /* Skip comment */ c->p += 2; while (*c->p && (c->p[0] != '*' || c->p[1] != '/')) { @@ -120,6 +110,14 @@ static int nextsym(context_t *c) /* 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++; @@ -140,6 +138,10 @@ static int nextsym(context_t *c) 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++; @@ -165,10 +167,10 @@ static int nextsym(context_t *c) break; } } - printf("TOKEN %d %c\n\n", c->token.kind, c->token.kind<255?c->token.kind:' '); if (c->token.kind != tok_none) { return 1; } else { + c->token.kind = tok_EOF; return 0; } } @@ -191,7 +193,6 @@ int moberg_config_parser_acceptsym(context_t *c, token_t *token) { if (c->token.kind == kind) { - printf("ACCEPT %d %s", c->token.kind, expected_char[kind]); if (token) { *token = c->token; } @@ -203,13 +204,17 @@ int moberg_config_parser_acceptsym(context_t *c, 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 = "y;"; break; + case tok_SEMICOLON: what = ";"; break; case tok_INTEGER: what = "<INTEGER>"; break; case tok_IDENT: what = "<IDENT>"; break; case tok_STRING: what = "<STRING>"; break; @@ -219,7 +224,6 @@ int moberg_config_parser_acceptsym(context_t *c, c->expected.n++; } } - printf("REJECT %d (%d)", kind, c->token.kind); return 0; } @@ -245,25 +249,39 @@ void moberg_config_parser_failed( FILE *f) { fprintf(f, "EXPECTED "); - for (int i = 0 ; i < c->expected.n ; i++) { - fprintf(f, "%s ", c->expected.what[i]); + for (int i = 0 ; i < c->expected.n; i++) { + if (i > 0) { + fprintf(f, " | "); + } + fprintf(f, "'%s'", c->expected.what[i]); } - const char *what = ""; + fprintf(f, "\nGOT: "); switch (c->token.kind) { - case tok_none: 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_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; + 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, "\nGOT %s %s\n", what, c->p); + fprintf(f, "\n%s\n", c->p); } @@ -288,7 +306,6 @@ err: static int parse_map(context_t *c, struct moberg_driver *driver) { - printf("parsemap"); if (acceptkeyword(c, "analog_in") || acceptkeyword(c, "analog_out") || acceptkeyword(c, "digital_in") || @@ -297,7 +314,6 @@ static int parse_map(context_t *c, if (! parse_map_range(c)) { goto err; } if (! acceptsym(c, tok_EQUAL, NULL)) { goto err; } driver->module.parse_map(c, 0); - if (! parse_map_range(c)) { goto err; } if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; } } else { goto err; @@ -329,36 +345,34 @@ err: return 0; } -static int parse_driver(context_t *c, - ident_t name) -{ - struct moberg_driver *driver = moberg_open_driver(name); - if (! driver) { - printf("Driver not found\n"); - goto err; - } else { - int OK = parse_device(c, driver); - moberg_close_driver(driver); - if (! OK) { goto err; } - } - return 1; -err: - return 0; -} - static int parse_config(context_t *c) { for (;;) { - token_t t; - if (acceptsym(c, tok_IDENT, &t)) { - printf("DRIVER=%.*s\n", t.u.ident.length, t.u.ident.value); - if (! parse_driver(c, t.u.ident)) { goto err; } + 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: - printf("Failed!!"); - exit (1); return 0; } diff --git a/test/a/moberg.conf b/test/a/moberg.conf index 81092d1..9523ce1 100644 --- a/test/a/moberg.conf +++ b/test/a/moberg.conf @@ -1,4 +1,4 @@ -comedi { +driver(comedi) { config { /* Parsed by parse_config in libmoberg_comedi.so */ device = "/dev/comedi0" ; @@ -7,13 +7,13 @@ 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_out[0:1] = subdevice[1][0:1] ; - map digital_in[0] = subdevice[7][15] ; - map digital_in[1] = subdevice[7][2] ; - map digital_out[0:1] = subdevice[7] route 16 [0:1]; + map analog_in[0:7] = { subdevice[0][0:7] }; + 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] }; } -serial2002 { +driver(serial2002) { config { /* Parsed by parse_config in libmoberg_serial2002.so */ device = "/dev/ttyS0" ; -- GitLab