summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2013-07-28 22:12:35 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2013-07-28 22:12:35 +0200
commit37c21678743c752cbbc2297871c47a3117303309 (patch)
tree6ff34969c1fb744af18ee3708be48c529b88bf2d
parenta713d2931ebd26bd2bc1b6c1cce574940736e718 (diff)
downloadgmrf-37c21678743c752cbbc2297871c47a3117303309.tar
gmrf-37c21678743c752cbbc2297871c47a3117303309.zip
Implement config parser
-rw-r--r--mmss/config.cpp79
-rw-r--r--mmss/config.hpp21
-rw-r--r--mmss/config.l19
-rw-r--r--mmss/config.y50
-rw-r--r--mmss/context.cpp27
5 files changed, 163 insertions, 33 deletions
diff --git a/mmss/config.cpp b/mmss/config.cpp
index 8e7cea3..0692d5f 100644
--- a/mmss/config.cpp
+++ b/mmss/config.cpp
@@ -26,6 +26,8 @@
#include "context.hpp"
#include "network.hpp"
+#include "node.hpp"
+#include "protocol.hpp"
#include <config.ll.hpp>
#include <config.yy.hpp>
@@ -38,12 +40,83 @@
namespace MMSS {
-void config_t::add_network(const char *name) {
- mmss->logf(LOG_NOTICE, "adding network `%s'", name);
+bool config_t::load_proto(const char *name, const char *module, bool def) {
+ if (protos.find(name) != protos.end()) {
+ mmss->logf(LOG_ERR, "config error: duplicate protocol `%s'", name);
+ return false;
+ }
+
+
+ std::shared_ptr<const protocol_t> proto = protocol_t::load(mmss, module);
+
+ if (!proto)
+ return false;
+
+ if (def)
+ default_proto = proto;
- network.push_back(std::make_shared<network_t>(name));
+ protos.insert(std::make_pair(name, std::move(proto)));
+
+ return true;
}
+bool config_t::add_network(const char *name) {
+ if (networks.find(name) != networks.end()) {
+ mmss->logf(LOG_ERR, "config error: duplicate network `%s'", name);
+ return false;
+ }
+
+
+ networks.insert(std::make_pair(name, std::make_shared<network_t>(name)));
+
+ return true;
+}
+
+bool config_t::add_node(const char *name, const char *proto) {
+ if (nodes.find(name) != nodes.end()) {
+ mmss->logf(LOG_ERR, "config error: duplicate node `%s'", name);
+ return false;
+ }
+
+ const std::shared_ptr<const protocol_t> *proto_ptr = &default_proto;
+
+ if (proto) {
+ auto it = protos.find(proto);
+
+ if (it == protos.end()) {
+ mmss->logf(LOG_ERR, "config error: no protocol `%s' found", proto);
+ return false;
+ }
+
+ proto_ptr = &it->second;
+ }
+
+ if (!*proto_ptr) {
+ mmss->logf(LOG_ERR, "config error: node `%s': no protocol given and no default protocol defined", name);
+ return false;
+ }
+
+ current_node = &nodes.insert(std::make_pair(name, node_t::create(mmss, name, rand_seed++, *proto_ptr))).first->second;
+
+ return true;
+}
+
+bool config_t::add_iface(const char *name, const char *net, const gmrf_addr_t *addr) {
+ // TODO duplicate name, address check
+
+ auto it = networks.find(net);
+
+ if (it == networks.end()) {
+ mmss->logf(LOG_ERR, "config error: no network `%s' found", net);
+ return false;
+ }
+
+ iface_t::add(*current_node, it->second, name, addr);
+
+ return true;
+}
+
+
std::shared_ptr<const config_t> config_t::read(context_t *mmss, const char *filename) {
std::shared_ptr<config_t> conf = std::shared_ptr<config_t>(new config_t(mmss));
char *oldcwd = get_current_dir_name();
diff --git a/mmss/config.hpp b/mmss/config.hpp
index 702f142..69ad6a0 100644
--- a/mmss/config.hpp
+++ b/mmss/config.hpp
@@ -28,8 +28,9 @@
#include "types.hpp"
-#include <list>
#include <memory>
+#include <string>
+#include <unordered_map>
namespace MMSS {
@@ -38,17 +39,27 @@ class config_t : public nocopy_t {
private:
context_t *mmss;
- std::list<std::shared_ptr<network_t>> network;
- std::list<std::shared_ptr<node_t>> nodes;
+ int rand_seed;
- config_t(context_t *mmss0) : mmss(mmss0) {}
+ std::shared_ptr<const protocol_t> default_proto;
+ std::unordered_map<std::string, std::shared_ptr<const protocol_t>> protos;
+
+ std::unordered_map<std::string, std::shared_ptr<network_t>> networks;
+
+ const std::shared_ptr<node_t> *current_node;
+ std::unordered_map<std::string, std::shared_ptr<node_t>> nodes;
+
+ config_t(context_t *mmss0) : mmss(mmss0), rand_seed(0) {}
public:
context_t* get_context() const {
return mmss;
}
- void add_network(const char *name);
+ bool load_proto(const char *name, const char *module, bool def);
+ bool add_network(const char *name);
+ bool add_node(const char *name, const char *proto);
+ bool add_iface(const char *name, const char *net, const gmrf_addr_t *addr);
static std::shared_ptr<const config_t> read(context_t *mmss, const char *filename);
};
diff --git a/mmss/config.l b/mmss/config.l
index f612613..4fdd346 100644
--- a/mmss/config.l
+++ b/mmss/config.l
@@ -36,6 +36,9 @@
%top {
#include <config.yy.hpp>
+
+ #include <cassert>
+ #include <cstdio>
}
%s NEEDSPACE
@@ -59,6 +62,22 @@
yes { TOKEN(TOK_YES); }
no { TOKEN(TOK_NO); }
network { TOKEN(TOK_NETWORK); }
+protocol { TOKEN(TOK_PROTOCOL); }
+node { TOKEN(TOK_NODE); }
+load { TOKEN(TOK_LOAD); }
+default { TOKEN(TOK_DEFAULT); }
+interface { TOKEN(TOK_INTERFACE); }
+address { TOKEN(TOK_ADDRESS); }
+
+([[:xdigit:]]{2}:){7}[[:xdigit:]]{2} {
+ UPDATE_LOCATION;
+
+ assert(std::sscanf(yytext, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ &yylval->addr.d[0], &yylval->addr.d[1], &yylval->addr.d[2], &yylval->addr.d[3],
+ &yylval->addr.d[4], &yylval->addr.d[5], &yylval->addr.d[6], &yylval->addr.d[7]) == 8);
+
+ return TOK_GMRF_ADDRESS;
+}
[;:\{\}] { UPDATE_LOCATION; return yytext[0]; }
diff --git a/mmss/config.y b/mmss/config.y
index 2b5fb72..6eade61 100644
--- a/mmss/config.y
+++ b/mmss/config.y
@@ -43,16 +43,24 @@
int num;
bool boolean;
char *str;
+ gmrf_addr_t addr;
const char *error;
}
%token <num> TOK_INTEGER
%token <str> TOK_STRING
+%token <addr> TOK_GMRF_ADDRESS
-%token TOK_NETWORK
%token TOK_YES
%token TOK_NO
+%token TOK_NETWORK
+%token TOK_PROTOCOL
+%token TOK_NODE
+%token TOK_LOAD
+%token TOK_DEFAULT
+%token TOK_INTERFACE
+%token TOK_ADDRESS
%code {
@@ -61,6 +69,8 @@
%type <boolean> boolean
+%type <boolean> maybe_default
+%type <str> maybe_protocol
%%
@@ -72,20 +82,56 @@ config: config statement
;
statement: TOK_NETWORK network '{' network_config '}'
+ | TOK_PROTOCOL protocol ';'
+ | TOK_NODE node '{' node_config '}'
;
network: TOK_STRING {
- conf->add_network($1);
+ if (!conf->add_network($1))
+ YYERROR;
}
;
network_config:
;
+protocol: TOK_STRING TOK_LOAD TOK_STRING maybe_default {
+ if (!conf->load_proto($1, $3, $4))
+ YYERROR;
+ }
+ ;
+
+node: TOK_STRING maybe_protocol {
+ if (!conf->add_node($1, $2))
+ YYERROR;
+ }
+ ;
+
+node_config: node_config node_statement
+ |
+ ;
+
+node_statement: TOK_INTERFACE node_interface ';'
+ ;
+
+node_interface: TOK_STRING TOK_NETWORK TOK_STRING TOK_ADDRESS TOK_GMRF_ADDRESS {
+ if (!conf->add_iface($1, $3, &$5))
+ YYERROR;
+ }
+ ;
+
boolean: TOK_YES { $$ = true; }
| TOK_NO { $$ = false; }
;
+maybe_default: TOK_DEFAULT { $$ = true; }
+ | { $$ = false; }
+ ;
+
+maybe_protocol: TOK_PROTOCOL TOK_STRING { $$ = $2; }
+ | { $$ = nullptr; }
+ ;
+
%%
void mmss_config_error(YYLTYPE *loc, const std::shared_ptr<config_t> &conf, const char *filename, const char *s) {
diff --git a/mmss/context.cpp b/mmss/context.cpp
index 349c6cf..d1e01c0 100644
--- a/mmss/context.cpp
+++ b/mmss/context.cpp
@@ -88,34 +88,15 @@ void context_t::logf(int priority, const char *format, ...) {
void context_t::run(int argc, char *argv[]) {
if (argc != 2) {
- std::fprintf(stderr, "usage: %s protocol_module\n", argv[0]);
+ std::fprintf(stderr, "usage: %s config\n", argv[0]);
std::exit(1);
}
- std::shared_ptr<const protocol_t> proto = protocol_t::load(this, argv[1]);
- if (!proto)
- std::exit(1);
-
- std::shared_ptr<const config_t> conf = config_t::read(this, "babel_test.mmss");
-
- std::shared_ptr<network_t> net0 = std::make_shared<network_t>("net0");
- std::shared_ptr<network_t> net1 = std::make_shared<network_t>("net1");
- std::shared_ptr<node_t> node1 = node_t::create(this, "node1", 1, proto);
- std::shared_ptr<node_t> node2 = node_t::create(this, "node2", 2, proto);
- std::shared_ptr<node_t> node3 = node_t::create(this, "node3", 3, proto);
+ std::shared_ptr<const config_t> conf = config_t::read(this, argv[1]);
- std::list<std::shared_ptr<node_t>> nodes;
-
- nodes.push_back(node1);
- nodes.push_back(node2);
- nodes.push_back(node3);
-
- gmrf_addr_t addr1 = {{1}}, addr2 = {{2}}, addr3 = {{3}}, addr4 = {{4}};
- iface_t::add(node1, net0, "mmss0", &addr1);
- iface_t::add(node2, net0, "mmss0", &addr2);
- iface_t::add(node2, net1, "mmss1", &addr3);
- iface_t::add(node3, net1, "mmss1", &addr4);
+ if (!conf)
+ std::exit(1);
while (true) {
if (now() > 10000000)