Skip to content
Snippets Groups Projects
Commit 8bed28b1 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Parser error messages added

parent 672dcb89
Branches
Tags
No related merge requests found
......@@ -29,7 +29,7 @@ $(MODULES):
.PHONY: test
test: all
LD_LIBRARY_PATH=build \
./parse_config test/*/*.conf
valgrind ./parse_config test/*/*.conf
LD_LIBRARY_PATH=build HOME=$$(pwd)/test \
valgrind -q --error-exitcode=1 test/test_c
......
#ifndef __MOBERG_CONFIG_PARSER_H__
#define __MOBERG_CONFIG_PARSER_H__
#include <stdio.h>
struct moberg_config_parser_context;
struct moberg_config_parser_token;
......@@ -14,13 +16,6 @@ enum moberg_config_parser_token_kind {
tok_COLON = ':',
tok_SEMICOLON = ';',
tok_INTEGER = 256,
tok_CONFIG,
tok_MAP,
tok_ANALOGIN,
tok_ANALOGOUT,
tok_DIGITALIN,
tok_DIGITALOUT,
tok_ENCODERIN,
tok_IDENT,
tok_STRING,
};
......@@ -46,8 +41,12 @@ int moberg_config_parser_acceptsym(
enum moberg_config_parser_token_kind kind,
struct moberg_config_parser_token *token);
int moberg_config_parser_peeksym(
int moberg_config_parser_acceptkeyword(
struct moberg_config_parser_context *c,
struct moberg_config_parser_token *token);
const char *keyword);
void moberg_config_parser_failed(
struct moberg_config_parser_context *c,
FILE *f);
#endif
......@@ -4,11 +4,24 @@
#include <stdlib.h>
#include <string.h>
#define acceptsym moberg_config_parser_acceptsym
#define peeksym moberg_config_parser_peeksym
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);
}
static struct moberg_driver_config parse_config(
struct moberg_config_parser_context *c)
......@@ -20,30 +33,46 @@ static struct moberg_driver_config parse_config(
for (;;) {
if (acceptsym(c, tok_RBRACE, NULL)) {
break;
} else if (acceptsym(c, tok_IDENT, &t) ||
acceptsym(c, tok_CONFIG, &t)) {
const char *v = t.u.ident.value;
int l = t.u.ident.length;
if (strncmp("device", v, l) == 0) {
printf("DEVICE\n");
} else if (strncmp("modprobe", v, l) == 0) {
printf("MODPROBE\n");
} else if (strncmp("config", v, l) == 0) {
printf("CONFIG\n");
} 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; }
} else if (acceptkeyword(c, "config")) {
if (! acceptsym(c, tok_EQUAL, NULL)) { goto err; }
if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; }
for (;;) {
if (acceptsym(c, tok_RBRACKET, NULL)) {
break;
} else if (acceptsym(c, tok_IDENT, NULL) ||
acceptsym(c, tok_STRING, NULL)) {
} else {
goto err;
}
acceptsym(c, tok_EQUAL, NULL);
}
if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; }
} else if (acceptkeyword(c, "modprobe")) {
if (! acceptsym(c, tok_EQUAL, NULL)) { goto err; }
if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; }
for (;;) {
peeksym(c, &t);
acceptsym(c, t.kind, NULL);
printf("%d\n", t.kind);
if (t.kind == tok_SEMICOLON) { break; }
if (acceptsym(c, tok_RBRACKET, NULL)) {
break;
} else if (acceptsym(c, tok_IDENT, NULL) ||
acceptsym(c, tok_STRING, NULL)) {
} else {
goto err;
}
}
if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; }
} else {
break;
goto err;
}
}
printf("PARSE_CONFIG DONE%s\n", __FILE__);
return result;
err:
moberg_config_parser_failed(c, stderr);
exit(1);
}
static struct moberg_driver_map parse_map(
......@@ -54,14 +83,10 @@ static struct moberg_driver_map parse_map(
token_t t;
printf("PARSE_MAP %s\n", __FILE__);
if (acceptsym(c, tok_IDENT, &t)) {
if (strncmp("subdevice", t.u.ident.value, t.u.ident.length) != 0) {
goto err;
}
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;
......@@ -72,6 +97,7 @@ static struct moberg_driver_map parse_map(
*/
return result;
err:
moberg_config_parser_failed(c, stderr);
exit(1);
}
......
......@@ -8,21 +8,38 @@
#include <moberg_config_parser.h>
#include <moberg_driver.h>
#define token moberg_config_parser_token
#define token_kind moberg_config_parser_token_kind
#define acceptsym moberg_config_parser_acceptsym
#define peeksym moberg_config_parser_peeksym
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
static char expected_char[256][2];
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_or_keyword(context_t *c)
static const void nextsym_ident(context_t *c)
{
c->token.u.ident.length = 1;
c->token.u.ident.value = c->p;
......@@ -44,23 +61,7 @@ static const void nextsym_ident_or_keyword(context_t *c)
out: ;
const char *v = c->token.u.ident.value;
int l = c->token.u.ident.length;
if (strncmp("config", v, l) == 0) {
c->token.kind = tok_CONFIG;
} else if (strncmp("map", v, l) == 0) {
c->token.kind = tok_MAP;
} else if (strncmp("analog_in", v, l) == 0) {
c->token.kind = tok_ANALOGIN;
} else if (strncmp("analog_out", v, l) == 0) {
c->token.kind = tok_ANALOGOUT;
} else if (strncmp("digital_in", v, l) == 0) {
c->token.kind = tok_DIGITALIN;
} else if (strncmp("digital_out", v, l) == 0) {
c->token.kind = tok_DIGITALOUT;
} else if (strncmp("encoder_in", v, l) == 0) {
c->token.kind = tok_ENCODERIN;
} else {
c->token.kind = tok_IDENT;
}
printf("IDENT: %.*s %d\n", l, v, c->token.kind);
}
......@@ -153,7 +154,7 @@ static int nextsym(context_t *c)
case 'a'...'z':
case 'A'...'Z':
case '_':
nextsym_ident_or_keyword(c);
nextsym_ident(c);
break;
case '0'...'9':
nextsym_integer(c);
......@@ -172,31 +173,100 @@ static int nextsym(context_t *c)
}
}
int moberg_config_parser_acceptsym(context_t *c,
enum token_kind kind,
static int peeksym(context_t *c,
kind_t kind,
token_t *token)
{
if (c->token.kind == kind) {
printf("ACCEPT %d", c->token.kind);
if (token) {
*token = c->token;
}
nextsym(c);
return 1;
}
printf("REJECT %d (%d)", kind, c->token.kind);
return 0;
}
int moberg_config_parser_peeksym(context_t *c,
int moberg_config_parser_acceptsym(context_t *c,
kind_t kind,
token_t *token)
{
if (c->token.kind == kind) {
printf("ACCEPT %d %s", c->token.kind, expected_char[kind]);
if (token) {
*token = c->token;
}
return *c->p != 0;
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_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 = "y;"; 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++;
}
}
printf("REJECT %d (%d)", kind, c->token.kind);
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++) {
fprintf(f, "%s ", c->expected.what[i]);
}
const char *what = "";
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;
}
fprintf(f, "\nGOT %s %s\n", what, c->p);
}
static int parse_map_range(context_t *c)
{
token_t low, high;
......@@ -210,7 +280,8 @@ static int parse_map_range(context_t *c)
if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; }
return 1;
err:
printf("OOPS");
moberg_config_parser_failed(c, stderr);
exit(1);
return 0;
}
......@@ -218,36 +289,23 @@ static int parse_map(context_t *c,
struct moberg_driver *driver)
{
printf("parsemap");
struct token t;
if (acceptsym(c, tok_ANALOGIN, &t) ||
acceptsym(c, tok_ANALOGOUT, &t) ||
acceptsym(c, tok_DIGITALIN, &t) ||
acceptsym(c, tok_DIGITALOUT, &t) ||
acceptsym(c, tok_ENCODERIN, &t)) {
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, t.kind);
driver->module.parse_map(c, 0);
if (! parse_map_range(c)) { goto err; }
if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto err; }
switch (t.kind) {
case tok_ANALOGIN:
case tok_ANALOGOUT:
case tok_DIGITALIN:
case tok_DIGITALOUT:
case tok_ENCODERIN:
break;
default:
goto err;
}
} else {
goto err;
}
return 1;
err:
moberg_config_parser_failed(c, stderr);
exit(1);
return 0;
}
......@@ -256,12 +314,9 @@ static int parse_device(context_t *c,
{
if (! acceptsym(c, tok_LBRACE, NULL)) { goto err; }
for (;;) {
struct token t;
peeksym(c, &t);
printf("PEEK %d", t.kind);
if (acceptsym(c, tok_CONFIG, NULL)) {
if (acceptkeyword(c, "config")) {
driver->module.parse_config(c);
} else if (acceptsym(c, tok_MAP, NULL)) {
} else if (acceptkeyword(c, "map")) {
parse_map(c, driver);
} else if (acceptsym(c, tok_RBRACE, NULL)) {
break;
......@@ -294,9 +349,7 @@ err:
static int parse_config(context_t *c)
{
for (;;) {
struct token t;
peeksym(c, &t);
printf("PEEK %d", t.kind);
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; }
......
......@@ -2,7 +2,7 @@ comedi {
config {
/* Parsed by parse_config in libmoberg_comedi.so */
device = "/dev/comedi0" ;
modprobe = [ comedi 8255 comedi_fc mite ni_tio ni_tiocmd ni_pcimio ] ;
modprobe = [ comedi "8255" comedi_fc mite ni_tio ni_tiocmd ni_pcimio ] ;
config = [ ni_pcimio ] ;
}
/* Moberg mapping[indices] = {driver specific}[indices]
......@@ -11,7 +11,7 @@ comedi {
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][0:1] route 16 ;
map digital_out[0:1] = subdevice[7] route 16 [0:1];
}
serial2002 {
config {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment