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:
parent
296dacead4
commit
93f9f2a687
3 changed files with 163 additions and 57 deletions
|
@ -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;
|
||||
|
|
|
@ -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(®ex, "([a-z]+)=(\"([^\"]+)\"|[^\" ]+)", REG_EXTENDED | REG_ICASE);
|
||||
if (ret) {
|
||||
char buf[512];
|
||||
regerror(ret, ®ex, buf, sizeof(buf));
|
||||
|
||||
warn("Failed to compile RE: %s", buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regexec(®ex, *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(®ex);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue