1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

rscad: finished rudimentary parsing of RSCAD .inf file by using POSIX regular expressions

This commit is contained in:
Steffen Vogel 2017-06-29 19:05:49 +02:00
parent 296dacead4
commit 93f9f2a687
3 changed files with 163 additions and 57 deletions

View file

@ -37,24 +37,31 @@ struct rscad_inf_timing_record {
};
union rscad_inf_value {
float f;
int i;
char *s;
};
struct rscad_inf_element {
enum {
char *name;
enum rscad_inf_type {
RSCAD_INF_ELEMENT_STRING,
RSCAD_INF_ELEMENT_OUTPUT,
RSCAD_INF_ELEMENT_PUSHBUTTON,
RSCAD_INF_ELEMENT_SLIDER
} type;
enum {
enum rscad_inf_datatype {
RSCAD_INF_DATATYPE_IEEE,
RSCAD_INF_DATATYPE_INT
RSCAD_INF_DATATYPE_INT,
RSCAD_INF_DATATYPE_STRING
} datatype;
union {
float f;
int i;
char *s;
} init_value, min, max;
union rscad_inf_value init_value;
union rscad_inf_value min;
union rscad_inf_value max;
int rack;
uint32_t address;

View file

@ -23,6 +23,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <regex.h>
#include "utils.h"
#include "log.h"
@ -53,6 +54,53 @@ static int rscad_inf_getline(char **line, size_t *linelen, FILE *f)
return 1;
}
static int rscad_inf_getattr(char **line, char **key, char **value)
{
int ret;
size_t kl, vl;
regex_t regex;
regmatch_t matches[4];
regmatch_t *km, *vm, *all;
ret = regcomp(&regex, "([a-z]+)=(\"([^\"]+)\"|[^\" ]+)", REG_EXTENDED | REG_ICASE);
if (ret) {
char buf[512];
regerror(ret, &regex, buf, sizeof(buf));
warn("Failed to compile RE: %s", buf);
return ret;
}
ret = regexec(&regex, *line, 4, matches, 0);
if (ret)
return ret;
int quotes = matches[3].rm_so > 0;
all = &matches[0];
km = &matches[1];
vm = &matches[quotes ? 3 : 2];
kl = km->rm_eo - km->rm_so;
vl = vm->rm_eo - vm->rm_so;
*key = realloc(*key, kl + 1);
*value = realloc(*value, vl + 1);
strncpy(*key, *line + km->rm_so, kl);
strncpy(*value, *line + vm->rm_so, vl);
(*key)[kl] = '\0';
(*value)[vl] = '\0';
*line += all->rm_eo;
regfree(&regex);
return 0;
}
static int rscad_inf_destroy_attribute(struct rscad_inf_attribute *a)
{
if (a->key)
@ -75,6 +123,9 @@ static int rscad_inf_destroy_element(struct rscad_inf_element *e)
if (e->units)
free(e->units);
if (e->name)
free(e->name);
if (e->type == RSCAD_INF_ELEMENT_STRING && e->init_value.s)
free(e->init_value.s);
@ -121,52 +172,60 @@ static int rscad_inf_parse_attributes(struct list *l, FILE *f)
return 0;
}
static int rscad_inf_parse_value(const char *value, enum rscad_inf_datatype dt, union rscad_inf_value *v)
{
char *endptr;
switch (dt) {
case RSCAD_INF_DATATYPE_IEEE:
v->f = strtod(value, &endptr);
break;
case RSCAD_INF_DATATYPE_INT:
v->i = strtoul(value, &endptr, 10);
break;
case RSCAD_INF_DATATYPE_STRING:
v->s = strdup(value);
break;
default:
return -1;
}
return value == endptr;
}
static int rscad_inf_parse_elements(struct list *l, FILE *f)
{
int ret = 0;
char *line = NULL;
int ret;
char *line = NULL, *key = NULL, *value = NULL;
size_t linelen = 0;
while (rscad_inf_getline(&line, &linelen, f)) {
struct rscad_inf_element e;
char *type, *attrs;
int i = 0;
char *p = line;
type = line;
/* Handwritten tokenizer */
char *tokens[32];
bool inquote = false;
while (*p && i < 32) {
/* Skip leading whitespace */
while (*p == ' ')
p++;
/* Save token */
tokens[i] = p;
while (*p) {
if (inquote) {
if (*p == '"') {
inquote = false;
break;
}
}
else {
if (*p == ' ' || *p == '=')
break;
}
p++;
}
*p = '\0';
i++;
}
tokens[i] = NULL;
attrs = strchr(line, ' ');
if (!attrs)
goto fail;
*attrs++ = '\0';
struct rscad_inf_element e = {
.name = NULL,
.description = NULL,
.group = NULL,
.units = NULL,
.address = -1,
.rack = -1,
.datatype = RSCAD_INF_DATATYPE_STRING,
.init_value.i = 0,
.min.i = 0,
.max.i = 0
};
if (!strcmp(type, "String"))
e.type = RSCAD_INF_ELEMENT_STRING;
else if (!strcmp(type, "Output"))
@ -176,21 +235,59 @@ static int rscad_inf_parse_elements(struct list *l, FILE *f)
else if (!strcmp(type, "Slider"))
e.type = RSCAD_INF_ELEMENT_SLIDER;
else
goto warn;
goto fail;
while (1) {
scanf(line, "%")
while (rscad_inf_getattr(&attrs, &key, &value) == 0) {
if (!strcmp(key, "Desc"))
e.description = strdup(value);
else if (!strcmp(key, "Group"))
e.group = strdup(value);
else if (!strcmp(key, "Units"))
e.units = strdup(value);
else if (!strcmp(key, "Adr"))
e.address = strtoul(value, NULL, 16);
else if (!strcmp(key, "Rack"))
e.rack = strtoul(value, NULL, 10);
else if (!strcmp(key, "Type")) {
if (!strcmp(value, "INT"))
e.datatype = RSCAD_INF_DATATYPE_INT;
else if (!strcmp(value, "IEEE"))
e.datatype = RSCAD_INF_DATATYPE_IEEE;
else
goto fail;
}
else if (!strcmp(key, "InitValue")) {
ret = rscad_inf_parse_value(value, e.datatype, &e.init_value);
if (ret)
goto fail;
}
else if (!strcmp(key, "Min")) {
ret = rscad_inf_parse_value(value, e.datatype, &e.min);
if (ret)
goto fail;
}
else if (!strcmp(key, "Max")) {
ret = rscad_inf_parse_value(value, e.datatype, &e.max);
if (ret)
goto fail;
}
else
goto fail;
}
if (e.group && e.description)
strcatf(&e.name, "%s|%s", e.group, e.description);
list_push(l, memdup(&e, sizeof(e)));
continue;
warn:
fail:
warn("Failed to parse element: %s", line);
}
free(line);
free(key);
free(value);
return 0;
}
@ -230,7 +327,7 @@ void rscad_inf_dump(struct rscad_inf *i)
for (size_t j = 0; j < list_length(&i->elements); j++) {
struct rscad_inf_element *e = list_at(&i->elements, j);
info("Element: type=%d", e->type);
info("Element: %s", e->name);
}
}

View file

@ -54,15 +54,17 @@ Test(rtds, rscad_inf)
rscad_inf_dump(&i);
e = rscad_inf_lookup_element(&i, "Subsystem #1|Sources|src|ABCmag");
e = list_lookup(&i.elements, "Subsystem #1|Node Voltages|S1) N1");
cr_assert_not_null(e);
cr_assert_eq(e->address, 0x783014);
cr_assert_eq(e->address, 0x20000C);
cr_assert_eq(e->rack, 4);
cr_assert_eq(e->datatype, RSCAD_INF_DATATYPE_IEEE);
cr_assert_eq(e->init_value.f, 230.0);
cr_assert_eq(e->min.f, 0.0);
cr_assert_eq(e->max.f, 460.0);
cr_assert_eq(e->max.f, 1.0);
cr_assert_str_eq(e->units, "kV");
cr_assert_str_eq(e->group, "Subsystem #1|Node Voltages");
cr_assert_str_eq(e->description, "S1) N1");
ret = rscad_inf_destroy(&i);
cr_assert_eq(ret, 0);