Implement config parser
This commit is contained in:
parent
a713d2931e
commit
37c2167874
5 changed files with 164 additions and 34 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
network.push_back(std::make_shared<network_t>(name));
|
||||
|
||||
std::shared_ptr<const protocol_t> proto = protocol_t::load(mmss, module);
|
||||
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
if (def)
|
||||
default_proto = proto;
|
||||
|
||||
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();
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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]; }
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -88,35 +88,16 @@ 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::shared_ptr<const config_t> conf = config_t::read(this, argv[1]);
|
||||
|
||||
if (!conf)
|
||||
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::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);
|
||||
|
||||
while (true) {
|
||||
if (now() > 10000000)
|
||||
break;
|
||||
|
|
Reference in a new issue