From 0ffde34faac958a28842a952157852fd072834a5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 26 Jul 2013 14:22:18 +0200 Subject: [PATCH] Convert mmss to C++, add parser --- CMakeLists.txt | 7 +- FindFLEX.cmake | 120 +++++++++++++++++++++++++++ mmss/CMakeLists.txt | 21 +++-- mmss/config.cpp | 125 +++++++++++++++++++++++++++++ mmss/config.l | 129 ++++++++++++++++++++++++++++++ mmss/config.y | 93 +++++++++++++++++++++ mmss/{iface.c => iface.cpp} | 8 +- mmss/{log.c => log.cpp} | 27 +++++-- mmss/{mmss.c => mmss.cpp} | 25 +++--- mmss/{mmss.h => mmss.hpp} | 68 +++++++++++++++- mmss/{protocol.c => protocol.cpp} | 6 +- mmss/{queue.c => queue.cpp} | 8 +- mmss/{queue.h => queue.hpp} | 4 +- mmss/{schedule.c => schedule.cpp} | 8 +- mmss/{types.h => types.hpp} | 7 ++ 15 files changed, 609 insertions(+), 47 deletions(-) create mode 100644 FindFLEX.cmake create mode 100644 mmss/config.cpp create mode 100644 mmss/config.l create mode 100644 mmss/config.y rename mmss/{iface.c => iface.cpp} (94%) rename mmss/{log.c => log.cpp} (81%) rename mmss/{mmss.c => mmss.cpp} (82%) rename mmss/{mmss.h => mmss.hpp} (61%) rename mmss/{protocol.c => protocol.cpp} (92%) rename mmss/{queue.c => queue.cpp} (94%) rename mmss/{queue.h => queue.hpp} (97%) rename mmss/{schedule.c => schedule.cpp} (93%) rename mmss/{types.h => types.hpp} (91%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31d4066..08a9052 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,10 @@ cmake_minimum_required(VERSION 2.8.3) -project(GMRF C) +project(GMRF C CXX) + +set(CMAKE_MODULE_PATH ${GMRF_SOURCE_DIR}) + +find_package(BISON 2.5 REQUIRED) +find_package(FLEX REQUIRED) add_subdirectory(mmss) add_subdirectory(mmss-protocol) diff --git a/FindFLEX.cmake b/FindFLEX.cmake new file mode 100644 index 0000000..fe83369 --- /dev/null +++ b/FindFLEX.cmake @@ -0,0 +1,120 @@ +#============================================================================= +# Copyright 2009 Kitware, Inc. +# Copyright 2006 Tristan Carel +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ------------------------------------------------------------------------------ +# +# The above copyright and license notice applies to distributions of +# CMake in source and binary form. Some source files contain additional +# notices of original copyright by their contributors; see each source +# for details. Third-party software packages supplied with CMake under +# compatible licenses provide their own copyright notices documented in +# corresponding subdirectories. +#============================================================================= + +FIND_PROGRAM(FLEX_EXECUTABLE flex DOC "path to the flex executable") +MARK_AS_ADVANCED(FLEX_EXECUTABLE) + +FIND_LIBRARY(FL_LIBRARY NAMES fl + DOC "Path to the fl library") + +FIND_PATH(FLEX_INCLUDE_DIR FlexLexer.h + DOC "Path to the flex headers") + +MARK_AS_ADVANCED(FL_LIBRARY FLEX_INCLUDE_DIR) + +SET(FLEX_INCLUDE_DIRS ${FLEX_INCLUDE_DIR}) +SET(FLEX_LIBRARIES ${FL_LIBRARY}) + +IF(FLEX_EXECUTABLE) + + EXECUTE_PROCESS(COMMAND ${FLEX_EXECUTABLE} --version + OUTPUT_VARIABLE FLEX_version_output + ERROR_VARIABLE FLEX_version_error + RESULT_VARIABLE FLEX_version_result + OUTPUT_STRIP_TRAILING_WHITESPACE) + IF(NOT ${FLEX_version_result} EQUAL 0) + IF(FLEX_FIND_REQUIRED) + MESSAGE(SEND_ERROR "Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}") + ELSE() + MESSAGE("Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}\nFLEX_VERSION will not be available") + ENDIF() + ELSE() + STRING(REGEX REPLACE "^flex (.*)$" "\\1" + FLEX_VERSION "${FLEX_version_output}") + ENDIF() + + #============================================================ + # FLEX_TARGET (public macro) + #============================================================ + # + MACRO(FLEX_TARGET Name Input Output) + SET(FLEX_TARGET_usage "FLEX_TARGET( [COMPILE_FLAGS ]") + IF(${ARGC} GREATER 3) + IF(${ARGC} EQUAL 5) + IF("${ARGV3}" STREQUAL "COMPILE_FLAGS") + SET(FLEX_EXECUTABLE_opts "${ARGV4}") + SEPARATE_ARGUMENTS(FLEX_EXECUTABLE_opts) + ELSE() + MESSAGE(SEND_ERROR ${FLEX_TARGET_usage}) + ENDIF() + ELSE() + MESSAGE(SEND_ERROR ${FLEX_TARGET_usage}) + ENDIF() + ENDIF() + + STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${Output}") + STRING(REPLACE "c" "h" _fileext ${_fileext}) + STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}" + OutputHeader "${Output}") + + ADD_CUSTOM_COMMAND(OUTPUT ${Output} ${OutputHeader} + COMMAND ${FLEX_EXECUTABLE} + ARGS ${FLEX_EXECUTABLE_opts} -o${Output} --header-file=${OutputHeader} ${Input} + DEPENDS ${Input} + COMMENT "[FLEX][${Name}] Building scanner with flex ${FLEX_VERSION}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + + SET(FLEX_${Name}_DEFINED TRUE) + SET(FLEX_${Name}_OUTPUTS ${Output} ${OutputHeader}) + SET(FLEX_${Name}_OUTPUT_HEADER ${OutputHeader}) + SET(FLEX_${Name}_INPUT ${Input}) + SET(FLEX_${Name}_COMPILE_FLAGS ${FLEX_EXECUTABLE_opts}) + ENDMACRO(FLEX_TARGET) + #============================================================ + + +ENDIF(FLEX_EXECUTABLE) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(FLEX REQUIRED_VARS FLEX_EXECUTABLE + VERSION_VAR FLEX_VERSION) + +# FindFLEX.cmake ends here diff --git a/mmss/CMakeLists.txt b/mmss/CMakeLists.txt index c200d7a..cd719e0 100644 --- a/mmss/CMakeLists.txt +++ b/mmss/CMakeLists.txt @@ -1,11 +1,18 @@ -include_directories(${GMRF_SOURCE_DIR}/include) +include_directories(${GMRF_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +FLEX_TARGET(mmss_config_lex config.l ${CMAKE_CURRENT_BINARY_DIR}/config.ll.cpp) +BISON_TARGET(mmss_config_parse config.y ${CMAKE_CURRENT_BINARY_DIR}/config.yy.cpp) add_executable(mmss - iface.c - log.c - mmss.c - protocol.c - queue.c - schedule.c + config.cpp + iface.cpp + log.cpp + mmss.cpp + protocol.cpp + queue.cpp + schedule.cpp + ${FLEX_mmss_config_lex_OUTPUTS} + ${BISON_mmss_config_parse_OUTPUTS} ) target_link_libraries(mmss dl) +set_target_properties(mmss PROPERTIES COMPILE_FLAGS -std=c++11) diff --git a/mmss/config.cpp b/mmss/config.cpp new file mode 100644 index 0000000..0be95fb --- /dev/null +++ b/mmss/config.cpp @@ -0,0 +1,125 @@ +/* + Copyright (c) 2013, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "mmss.hpp" +#include +#include + +#include + + +void mmss_config_add_network(mmss_t *mmss, mmss_config_t *conf, const char *name) { + mmss_logf(mmss, LOG_NOTICE, "Adding network `%s'", name); + + mmss_network_t *net = new mmss_network_t; + + net->name = strdup(name); + net->mtu = 1500; + + net->next = conf->networks; + conf->networks = net; +} + +bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename) { + bool ret = true; + char *oldcwd = get_current_dir_name(); + char *filename2 = NULL; + char *dir = NULL; + FILE *file; + yyscan_t scanner; + mmss_config_pstate *ps; + mmss_string_stack_t *strings = NULL; + int token; + YYSTYPE token_val; + YYLTYPE loc = {1, 0, 1, 0}; + int parse_ret; + + + mmss_config_yylex_init(&scanner); + ps = mmss_config_pstate_new(); + + if (!filename) { + file = stdin; + } + else { + file = fopen(filename, "r"); + if (!file) { + mmss_logf(mmss, LOG_ERR, "can't open config file `%s': %s", filename, strerror(errno)); + ret = false; + goto end_free; + } + } + + mmss_config_yyset_in(file, scanner); + + if (filename) { + filename2 = strdup(filename); + dir = dirname(filename2); + + if (chdir(dir)) { + mmss_logf(mmss, LOG_ERR, "change from directory `%s' to `%s' failed", oldcwd, dir); + ret = false; + goto end_free; + } + } + + do { + token = mmss_config_yylex(&token_val, &loc, scanner); + + if (token < 0) { + mmss_logf(mmss, LOG_ERR, "config error: %s at %s:%i:%i", token_val.error, filename, loc.first_line, loc.first_column); + ret = false; + goto end_free; + } + + if (token == TOK_STRING) { + token_val.str->next = strings; + strings = token_val.str; + } + + parse_ret = mmss_config_push_parse(ps, token, &token_val, &loc, mmss, conf, filename); + } while (parse_ret == YYPUSH_MORE); + + if (parse_ret) + ret = false; + + end_free: + mmss_string_stack_free(strings); + + mmss_config_pstate_delete(ps); + mmss_config_yylex_destroy(scanner); + + if(chdir(oldcwd)) + mmss_logf(mmss, LOG_ERR, "can't chdir to `%s': %s", oldcwd, strerror(errno)); + + free(filename2); + free(oldcwd); + + if (filename && file) + fclose(file); + + return ret; +} diff --git a/mmss/config.l b/mmss/config.l new file mode 100644 index 0000000..6f20423 --- /dev/null +++ b/mmss/config.l @@ -0,0 +1,129 @@ +/* + Copyright (c) 2013, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +%option prefix="mmss_config_yy" +%option noyywrap +%option nounput +%option noinput +%option bison-bridge +%option bison-locations +%option reentrant +%option warn + + +%top { + #include +} + +%s NEEDSPACE +%s STRING +%s COMMENT + +%% +%{ + #define UPDATE_LOCATION do { \ + yylloc->first_line = yylloc->last_line; \ + yylloc->first_column = yylloc->last_column+1; \ + yylloc->last_column += yyleng; \ + } while (0) + + #define TOKEN(tok) do { UPDATE_LOCATION; BEGIN(NEEDSPACE); return tok; } while (0) +%} + +{ +[0-9]+ { UPDATE_LOCATION; yylval->num = atoi(yytext); BEGIN(NEEDSPACE); return TOK_INTEGER; } + +yes { TOKEN(TOK_YES); } +no { TOKEN(TOK_NO); } +network { TOKEN(TOK_NETWORK); } + +[;:\{\}] { UPDATE_LOCATION; return yytext[0]; } + +[ \t] { yylloc->last_column++; } +\n { yylloc->last_column = 0; yylloc->last_line++; } +\r ; +} + +{ +[;:\{\}] { UPDATE_LOCATION; BEGIN(INITIAL); return yytext[0]; } + +[ \t] { yylloc->last_column++; BEGIN(INITIAL); } +\n { yylloc->last_column = 0; yylloc->last_line++; BEGIN(INITIAL); } +\r ; +} + +\" { UPDATE_LOCATION; BEGIN(STRING); } +[^"\\\n\r] { yylloc->last_column++; yymore(); } +\n { yylloc->last_line++; yylloc->last_column = 0; yymore(); } +\r { yymore(); } +\\. { yylloc->last_column+=2; yymore(); } +\\\n { yylloc->last_line++; yylloc->last_column = 0; yymore(); } +\" { + int i, esc = 0; + + for (i = 0; i < yyleng; i++) { + if (yytext[i] == '\\') { + i++; + if (yytext[i] == '\n') { + esc+=2; + } + else { + yytext[i-esc-1] = yytext[i]; + esc++; + } + } + else if(esc) { + yytext[i-esc] = yytext[i]; + } + } + yytext[yyleng-esc-1] = 0; + yylval->str = mmss_string_stack_dup(yytext); + BEGIN(NEEDSPACE); + yylloc->last_column++; + return TOK_STRING; + + } + +#.* { yylloc->last_column += yyleng; } +\/\/.* { yylloc->last_column += yyleng; } + +\/\* { UPDATE_LOCATION; BEGIN(COMMENT); } +\*\/ { yylloc->last_column += yyleng; BEGIN(INITIAL); } +[^\n\r] { yylloc->last_column++; } +\n { yylloc->last_line++; yylloc->last_column = 0; } +\r {} + +. { + yylloc->first_line = yylloc->last_line; + yylloc->first_column = yylloc->last_column+1; + yylval->error = "syntax error"; + return -1; + } + +<> { return 0; } +<> { yylval->error = "unterminated block comment"; return -1; } +<> { yylval->error = "unterminated string"; return -1; } +%% diff --git a/mmss/config.y b/mmss/config.y new file mode 100644 index 0000000..722ce25 --- /dev/null +++ b/mmss/config.y @@ -0,0 +1,93 @@ +/* + Copyright (c) 2013, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +%define api.pure +%define api.push-pull push +%name-prefix "mmss_config_" +%locations +%parse-param {mmss_t *mmss} +%parse-param {mmss_config_t *conf} +%parse-param {const char *filename} + + +%code requires { + #include + + #include +} + +%union { + int num; + mmss_string_stack_t *str; + bool boolean; + + const char *error; +} + +%token TOK_INTEGER +%token TOK_STRING + +%token TOK_NETWORK +%token TOK_YES +%token TOK_NO + + +%code { + void mmss_config_error(YYLTYPE *loc, mmss_t *mmss, mmss_config_t *conf, const char *filename, const char *s); +} + + +%type boolean + +%% + +start: config + ; + +config: config statement + | + ; + +statement: TOK_NETWORK network '{' network_config '}' + ; + +network: TOK_STRING { + mmss_config_add_network(mmss, conf, $1->str); + } + ; + +network_config: + ; + +boolean: TOK_YES { $$ = true; } + | TOK_NO { $$ = false; } + ; + +%% + +void mmss_config_error(YYLTYPE *loc, mmss_t *mmss, mmss_config_t *conf, const char *filename, const char *s) { + mmss_logf(mmss, LOG_ERR, "config error: %s at %s:%i:%i", s, filename, loc->first_line, loc->first_column); +} diff --git a/mmss/iface.c b/mmss/iface.cpp similarity index 94% rename from mmss/iface.c rename to mmss/iface.cpp index 6d636ce..441da4a 100644 --- a/mmss/iface.c +++ b/mmss/iface.cpp @@ -24,9 +24,9 @@ */ -#include "mmss.h" +#include "mmss.hpp" -#include +#include gmrf_addr_t gmrf_iface_get_addr(gmrf_t *gmrf, gmrf_iface_t *iface) { @@ -42,7 +42,7 @@ size_t gmrf_iface_get_mtu(gmrf_t *gmrf, gmrf_iface_t *iface) { } static void enqueue(mmss_t *mmss, gmrf_iface_t *source, gmrf_iface_t *dest, const void *data, size_t len) { - mmss_packet_t *packet = calloc(1, sizeof(mmss_packet_t) + len); + mmss_packet_t *packet = reinterpret_cast(calloc(1, sizeof(mmss_packet_t) + len)); packet->sent = mmss->now; packet->source = source; @@ -82,7 +82,7 @@ void mmss_dispatch(mmss_packet_t *packet) { } void mmss_add_iface(gmrf_t *node, mmss_network_t *net, const char *name, const gmrf_addr_t *address) { - gmrf_iface_t *iface = calloc(1, sizeof(gmrf_iface_t)); + gmrf_iface_t *iface = new gmrf_iface_t; iface->name = strdup(name); iface->address = *address; diff --git a/mmss/log.c b/mmss/log.cpp similarity index 81% rename from mmss/log.c rename to mmss/log.cpp index 5599e95..eb2ce03 100644 --- a/mmss/log.c +++ b/mmss/log.cpp @@ -24,9 +24,9 @@ */ -#include "mmss.h" +#include "mmss.hpp" -#include +#include static inline int snprintf_safe(char *buffer, size_t size, const char *format, ...) { @@ -57,17 +57,30 @@ static inline const char* get_log_prefix(int log_level) { } } - -void gmrf_logf(gmrf_t *gmrf, int priority, const char *format, ...) { +void mmss_logf(mmss_t *mmss, int priority, const char *format, ...) { char buf[1024]; size_t pos = 0; - pos += snprintf_safe(buf, sizeof(buf), "[% 5u.%03u] %s: %s", gmrf->mmss->now/1000, gmrf->mmss->now%1000, gmrf->name, get_log_prefix(priority)); + pos += snprintf_safe(buf, sizeof(buf), "[% 5u.%03u] ", mmss->now/1000, mmss->now%1000); - va_list ap; - va_start(ap, format); + va_list ap; + va_start(ap, format); vsnprintf(buf+pos, sizeof(buf)-pos, format, ap); va_end(ap); fprintf(stderr, "%s\n", buf); } + +void gmrf_logf(gmrf_t *gmrf, int priority, const char *format, ...) { + char buf[1024]; + size_t pos = 0; + + pos += snprintf_safe(buf, sizeof(buf), "%s: %s", gmrf->name, get_log_prefix(priority)); + + va_list ap; + va_start(ap, format); + vsnprintf(buf+pos, sizeof(buf)-pos, format, ap); + va_end(ap); + + mmss_logf(gmrf->mmss, priority, "%s", buf); +} diff --git a/mmss/mmss.c b/mmss/mmss.cpp similarity index 82% rename from mmss/mmss.c rename to mmss/mmss.cpp index a260983..8447e5e 100644 --- a/mmss/mmss.c +++ b/mmss/mmss.cpp @@ -24,11 +24,11 @@ */ -#include "mmss.h" +#include "mmss.hpp" -#include -#include -#include +#include +#include +#include gmrf_time_t gmrf_now(gmrf_t *gmrf) { @@ -36,7 +36,7 @@ gmrf_time_t gmrf_now(gmrf_t *gmrf) { } void gmrf_random_bytes(gmrf_t *gmrf, void *buffer, size_t len) { - uint8_t *data = buffer; + uint8_t *data = reinterpret_cast(buffer); size_t i; for (i = 0; i < len; i++) @@ -78,11 +78,14 @@ int main(int argc, char *argv[]) { return 1; mmss_t mmss = { .now = 0 }; + mmss_config_t conf = {}; + + mmss_read_config(&mmss, &conf, "babel_test.mmss"); mmss_network_t net0 = { .mtu = 1500 }, net1 = { .mtu = 1500 }; - gmrf_t node1 = { .name = "node1", .mmss = &mmss, .rand_seed = 1, .proto = proto }; - gmrf_t node2 = { .name = "node2", .mmss = &mmss, .rand_seed = 2, .proto = proto }; - gmrf_t node3 = { .name = "node3", .mmss = &mmss, .rand_seed = 3, .proto = proto }; + gmrf_t node1 = { .name = strdup("node1"), .mmss = &mmss, .rand_seed = 1, .proto = proto }; + gmrf_t node2 = { .name = strdup("node2"), .mmss = &mmss, .rand_seed = 2, .proto = proto }; + gmrf_t node3 = { .name = strdup("node3"), .mmss = &mmss, .rand_seed = 3, .proto = proto }; node2.next = &node1; node3.next = &node2; @@ -115,12 +118,12 @@ int main(int argc, char *argv[]) { assert(timeout == 0); while (timeout == 0) { - mmss_packet_t *packet = mmss_queue_get(&mmss, &mmss.packet_queue); - mmss_scheduled_t *scheduled = mmss_queue_get(&mmss, &mmss.scheduled_queue); + mmss_packet_t *packet = reinterpret_cast(mmss_queue_get(&mmss, &mmss.packet_queue)); + mmss_scheduled_t *scheduled = reinterpret_cast(mmss_queue_get(&mmss, &mmss.scheduled_queue)); assert(packet || scheduled); - if(packet) + if (packet) mmss_dispatch(packet); if (scheduled) diff --git a/mmss/mmss.h b/mmss/mmss.hpp similarity index 61% rename from mmss/mmss.h rename to mmss/mmss.hpp index 4b0e206..a2c2fe2 100644 --- a/mmss/mmss.h +++ b/mmss/mmss.hpp @@ -27,11 +27,17 @@ #ifndef _GMRF_MMSS_MMSS_H_ #define _GMRF_MMSS_MMSS_H_ +#include "queue.hpp" + +extern "C" { + #include #include -#include "queue.h" +} +#include +#include struct mmss { uint64_t now; @@ -39,11 +45,17 @@ struct mmss { mmss_queue_t scheduled_queue; }; +struct mmss_config { + mmss_network_t *networks; + gmrf_t *nodes; +}; + struct mmss_network { mmss_network_t *next; - gmrf_iface_t *interfaces; + char *name; + gmrf_iface_t *interfaces; size_t mtu; }; @@ -63,11 +75,16 @@ struct mmss_scheduled { void *arg; }; +struct mmss_string_stack { + mmss_string_stack_t *next; + char str[]; +}; + struct gmrf { gmrf_t *next; - const char *name; + char *name; mmss_t *mmss; gmrf_context_t *ctx; @@ -92,11 +109,17 @@ struct gmrf_iface { const mmss_protocol_t* mmss_load_protocol(const char *module); +void mmss_config_add_network(mmss_t *mmss, mmss_config_t *conf, const char *name); + +bool mmss_read_config(mmss_t *mmss, mmss_config_t *conf, const char *filename); + void mmss_add_iface(gmrf_t *node, mmss_network_t *net, const char *name, const gmrf_addr_t *address); void mmss_dispatch(mmss_packet_t *packet); void mmss_run_scheduled(mmss_scheduled_t *scheduled); +void mmss_logf(mmss_t *mmss, int priority, const char *format, ...); + static inline int max(int a, int b) { return (a > b) ? a : b; @@ -107,4 +130,43 @@ static inline int min(int a, int b) { } +static inline size_t alignto(size_t l, size_t a) { + return ((l+a-1)/a)*a; +} + +static inline mmss_string_stack_t* mmss_string_stack_dup(const char *str) { + mmss_string_stack_t *ret = reinterpret_cast(std::malloc(alignto(sizeof(mmss_string_stack_t) + strlen(str) + 1, 8))); + ret->next = NULL; + std::strcpy(ret->str, str); + + return ret; +} + +static inline mmss_string_stack_t* mmss_string_stack_dupn(const char *str, size_t len) { + size_t str_len = strnlen(str, len); + mmss_string_stack_t *ret = reinterpret_cast(std::malloc(alignto(sizeof(mmss_string_stack_t) + str_len + 1, 8))); + ret->next = NULL; + std::strncpy(ret->str, str, str_len); + ret->str[str_len] = 0; + + return ret; +} + +static inline mmss_string_stack_t* mmss_string_stack_push(mmss_string_stack_t *stack, const char *str) { + mmss_string_stack_t *ret = reinterpret_cast(std::malloc(alignto(sizeof(mmss_string_stack_t) + strlen(str) + 1, 8))); + ret->next = stack; + std::strcpy(ret->str, str); + + return ret; +} + +static inline void mmss_string_stack_free(mmss_string_stack_t *str) { + while(str) { + mmss_string_stack_t *next = str->next; + std::free(str); + str = next; + } +} + + #endif /* _GMRF_MMSS_MMSS_H_ */ diff --git a/mmss/protocol.c b/mmss/protocol.cpp similarity index 92% rename from mmss/protocol.c rename to mmss/protocol.cpp index 046cb58..ace3560 100644 --- a/mmss/protocol.c +++ b/mmss/protocol.cpp @@ -24,10 +24,10 @@ */ -#include "mmss.h" +#include "mmss.hpp" #include -#include +#include const mmss_protocol_t* mmss_load_protocol(const char *module) { @@ -38,7 +38,7 @@ const mmss_protocol_t* mmss_load_protocol(const char *module) { } dlerror(); - const mmss_protocol_t *proto = dlsym(handle, "mmss_protocol_info"); + const mmss_protocol_t *proto = reinterpret_cast(dlsym(handle, "mmss_protocol_info")); if (!proto) { fprintf(stderr, "unable to load protocol from `%s': %s\n", module, dlerror()); dlclose(handle); diff --git a/mmss/queue.c b/mmss/queue.cpp similarity index 94% rename from mmss/queue.c rename to mmss/queue.cpp index c7c475b..a5d2142 100644 --- a/mmss/queue.c +++ b/mmss/queue.cpp @@ -24,10 +24,10 @@ */ -#include "queue.h" -#include "mmss.h" +#include "queue.hpp" +#include "mmss.hpp" -#include +#include typedef struct mmss_queue_entry mmss_queue_entry_t; @@ -43,7 +43,7 @@ void mmss_queue_put(mmss_t *mmss, mmss_queue_t *queue, void *data, uint64_t time while (*queue && timeout >= (*queue)->timeout) queue = &(*queue)->next; - mmss_queue_entry_t *entry = malloc(sizeof(mmss_queue_entry_t)); + mmss_queue_entry_t *entry = new mmss_queue_entry_t; entry->timeout = timeout; entry->data = data; diff --git a/mmss/queue.h b/mmss/queue.hpp similarity index 97% rename from mmss/queue.h rename to mmss/queue.hpp index 6e2648b..d24bff6 100644 --- a/mmss/queue.h +++ b/mmss/queue.hpp @@ -27,9 +27,9 @@ #ifndef _GMRF_MMSS_QUEUE_H_ #define _GMRF_MMSS_QUEUE_H_ -#include +#include "types.hpp" -#include "types.h" +#include typedef struct mmss_queue_entry *mmss_queue_t; diff --git a/mmss/schedule.c b/mmss/schedule.cpp similarity index 93% rename from mmss/schedule.c rename to mmss/schedule.cpp index 0474613..adebf19 100644 --- a/mmss/schedule.c +++ b/mmss/schedule.cpp @@ -24,13 +24,11 @@ */ -#include "mmss.h" - -#include +#include "mmss.hpp" void gmrf_schedule(gmrf_t *gmrf, gmrf_scheduled_func f, void *arg, unsigned delay) { - mmss_scheduled_t *scheduled = calloc(1, sizeof(mmss_scheduled_t)); + mmss_scheduled_t *scheduled = new mmss_scheduled_t; scheduled->node = gmrf; scheduled->f = f; @@ -41,5 +39,5 @@ void gmrf_schedule(gmrf_t *gmrf, gmrf_scheduled_func f, void *arg, unsigned dela void mmss_run_scheduled(mmss_scheduled_t *scheduled) { scheduled->f(scheduled->node, scheduled->node->ctx, scheduled->arg); - free(scheduled); + delete scheduled; } diff --git a/mmss/types.h b/mmss/types.hpp similarity index 91% rename from mmss/types.h rename to mmss/types.hpp index 04c77be..52ace0f 100644 --- a/mmss/types.h +++ b/mmss/types.hpp @@ -27,9 +27,16 @@ #ifndef _GMRF_MMSS_TYPES_H_ #define _GMRF_MMSS_TYPES_H_ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + typedef struct mmss mmss_t; +typedef struct mmss_config mmss_config_t; typedef struct mmss_network mmss_network_t; typedef struct mmss_packet mmss_packet_t; typedef struct mmss_scheduled mmss_scheduled_t; +typedef struct mmss_string_stack mmss_string_stack_t; + #endif /* _GMRF_MMSS_TYPES_H_ */