From 37c21678743c752cbbc2297871c47a3117303309 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 28 Jul 2013 22:12:35 +0200 Subject: Implement config parser --- mmss/config.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- mmss/config.hpp | 21 +++++++++++---- mmss/config.l | 19 ++++++++++++++ mmss/config.y | 50 +++++++++++++++++++++++++++++++++-- mmss/context.cpp | 27 +++---------------- 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 #include @@ -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 proto = protocol_t::load(mmss, module); + + if (!proto) + return false; + + if (def) + default_proto = proto; - network.push_back(std::make_shared(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(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 *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 config_t::read(context_t *mmss, const char *filename) { std::shared_ptr conf = std::shared_ptr(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 #include +#include +#include namespace MMSS { @@ -38,17 +39,27 @@ class config_t : public nocopy_t { private: context_t *mmss; - std::list> network; - std::list> nodes; + int rand_seed; - config_t(context_t *mmss0) : mmss(mmss0) {} + std::shared_ptr default_proto; + std::unordered_map> protos; + + std::unordered_map> networks; + + const std::shared_ptr *current_node; + std::unordered_map> 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 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 + + #include + #include } %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 TOK_INTEGER %token TOK_STRING +%token 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 +%type maybe_default +%type 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 &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 proto = protocol_t::load(this, argv[1]); - if (!proto) - std::exit(1); - - std::shared_ptr conf = config_t::read(this, "babel_test.mmss"); - - std::shared_ptr net0 = std::make_shared("net0"); - std::shared_ptr net1 = std::make_shared("net1"); - std::shared_ptr node1 = node_t::create(this, "node1", 1, proto); - std::shared_ptr node2 = node_t::create(this, "node2", 2, proto); - std::shared_ptr node3 = node_t::create(this, "node3", 3, proto); + std::shared_ptr conf = config_t::read(this, argv[1]); - std::list> 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) -- cgit v1.2.3