From 322becfb0c87b219835be4ca704efb8bc75850f2 Mon Sep 17 00:00:00 2001 From: astand Date: Sat, 2 Jul 2022 21:05:09 +0300 Subject: [PATCH] Updates in fmon-* source code, some inner optimizations etc. Some service level improvements. New fmon generator and fmon model. Config section for MONO fmon mode. FS splitted to gen and file settings. Direct appending to fwriter. Removed useless methods. FileWriter API update. Mon generator with new FWriter API. Update in FWriter API. All users use new API. Added main header with empty lines in comments of some signals. Ignore vscode config. Driver compilation config printer as separated driver. AStyle format to all sources. Update realese notes. --- .gitignore | 1 + docs/RELEASES.md | 13 + src/CMakeLists.txt | 3 + src/app.cpp | 238 ++++++++++ src/app.h | 32 ++ src/codegen/c-main-generator.cpp | 705 ++++++++++++++---------------- src/codegen/c-main-generator.h | 14 +- src/codegen/c-sigprinter.cpp | 5 +- src/codegen/c-util-generator.cpp | 113 +++-- src/codegen/c-util-generator.h | 8 +- src/codegen/config-generator.cpp | 133 ++++++ src/codegen/config-generator.h | 11 + src/codegen/filewriter.cpp | 63 ++- src/codegen/filewriter.h | 12 +- src/codegen/fs-creator.cpp | 101 ++--- src/codegen/fs-creator.h | 27 +- src/codegen/mon-generator.cpp | 75 ++++ src/codegen/mon-generator.h | 15 + src/codegen/version.h | 2 +- src/helpers/formatter.h | 17 + src/maincli.cpp | 288 +----------- test/gencode/conf/testdb-config.h | 19 + test/gencode/lib/testdb-fmon.h | 34 +- test/gencode/lib/testdb.h | 24 + test/gencode/usr/testdb-fmon.c | 24 +- 25 files changed, 1161 insertions(+), 816 deletions(-) create mode 100644 src/app.cpp create mode 100644 src/app.h create mode 100644 src/codegen/config-generator.cpp create mode 100644 src/codegen/config-generator.h create mode 100644 src/codegen/mon-generator.cpp create mode 100644 src/codegen/mon-generator.h diff --git a/.gitignore b/.gitignore index c1d45a3..954b15b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ **/build* loc-test* +.vscode diff --git a/docs/RELEASES.md b/docs/RELEASES.md index 3aa26c7..fa233bc 100644 --- a/docs/RELEASES.md +++ b/docs/RELEASES.md @@ -1,5 +1,18 @@ # Changelog +## v2.3 19.07.2022 + +### Changed +- The gGeneration and the file configurations are splitted to different structs +- Specific generators moved to separated files (fmon, config) +- FileWriter API more simple + +### Added +- FMon driver can be configured for using MONO function approach or +dedicated function (how it was before) by setting _USE_MONO_FMON macro + +--- + ## v2.2 2022-05-07 ### Fixed diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 01fcc06..ba68034 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(coderdbc ${CMAKE_CURRENT_SOURCE_DIR}/codegen/c-main-generator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/codegen/mon-generator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/codegen/config-generator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/codegen/c-util-generator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/codegen/conditional-tree.cpp ${CMAKE_CURRENT_SOURCE_DIR}/codegen/c-sigprinter.cpp @@ -16,5 +18,6 @@ add_executable(coderdbc ${CMAKE_CURRENT_SOURCE_DIR}/helpers/formatter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/parser/dbclineparser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/parser/dbcscanner.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/app.cpp ${CMAKE_CURRENT_SOURCE_DIR}/maincli.cpp ) diff --git a/src/app.cpp b/src/app.cpp new file mode 100644 index 0000000..2f0ea41 --- /dev/null +++ b/src/app.cpp @@ -0,0 +1,238 @@ +#include "app.h" +#include +#include +#include +#include +#include +#include +#include "app.h" +#include "parser/dbcscanner.h" +#include "codegen/c-main-generator.h" +#include "codegen/c-util-generator.h" +#include "codegen/fs-creator.h" +#include "codegen/version.h" +#include +#include + +void CoderApp::Run() +{ + if (ParseParams()) + { + GenerateCode(); + } + else + { + PrintHelp(); + } +} + +bool CoderApp::ParseParams() +{ + for (size_t i = 0; i < Params.size(); i++) + { + if (Params[i].first.compare("-dbc") == 0) + { + dbc.value = Params[i].second; + dbc.ok = true; + } + else if (Params[i].first.compare("-out") == 0) + { + outdir.value = Params[i].second; + outdir.ok = true; + } + else if (Params[i].first.compare("-drvname") == 0) + { + drvname.value = make_c_name(Params[i].second); + drvname.ok = true; + + if (drvname.value.length() == 0) + { + drvname.ok = false; + } + } + else if (Params[i].first.compare("-rw") == 0) + { + rewrite_src = true; + } + else if (Params[i].first.compare("-nodeutils") == 0) + { + gen_nodeutils = true; + } + else if (Params[i].first.compare("-help") == 0) + { + return false; + } + } + + return (dbc.ok && outdir.ok && drvname.ok); +} + +void CoderApp::GenerateCode() +{ + auto scanner = std::make_unique(); + auto cigen = std::make_unique(); + auto ciugen = std::make_unique(); + auto fscreator = std::make_unique(); + + std::ifstream reader; + + std::cout << "dbc file : " << dbc.value << std::endl; + std::cout << "gen path : " << outdir.value << std::endl; + std::cout << "drv name : " << drvname.value << std::endl; + + if (std::filesystem::exists(dbc.value) == false) + { + std::cout << "DBC file is not exists!" << std::endl; + return; + } + + reader.open(dbc.value); + + std::istream& s = reader; + + scanner->TrimDbcText(s); + + std::string info(""); + + // create main destination directory + auto ret = fscreator->PrepareDirectory(drvname.value.c_str(), outdir.value.c_str(), rewrite_src, info); + + if (ret) + { + cigen->Generate(scanner->dblist, fscreator->FS); + } + else + { + std::cout << "One or both are invalid\n"; + } + + // check if option --node-utils is requested, when requested binutil generation + // wiil be performed on each node from DBC file in accordance to its RX / TX subscription + if (gen_nodeutils) + { + std::vector nodes; + + for (size_t num = 0; num < scanner->dblist.msgs.size(); num++) + { + // iterate all messages and collect All nodes assign to at least one message + auto m = scanner->dblist.msgs[num]; + + for (size_t txs = 0; txs < m->TranS.size(); txs++) + { + std::string tx_node_name = m->TranS[txs]; + + if (std::find(nodes.begin(), nodes.end(), tx_node_name) == nodes.end()) + { + // New node name. put it in the node collection + nodes.push_back(tx_node_name); + } + } + + for (size_t recs = 0; recs < m->RecS.size(); recs++) + { + std::string rx_node_name = m->RecS[recs]; + + // test all recs + if (std::find(nodes.begin(), nodes.end(), rx_node_name) == nodes.end()) + { + // New node name, put it in the node collection + nodes.push_back(rx_node_name); + } + } + } + + // for each node in collection perform specific bin-util generation + for (size_t node = 0; node < nodes.size(); node++) + { + std::string util_name = nodes[node] + "_" + drvname.value; + + // set new driver name for current node + fscreator->FS.gen.drvname = str_tolower(util_name); + fscreator->FS.gen.DRVNAME = str_toupper(fscreator->FS.gen.drvname); + fscreator->FS.file.util_c.dir = fscreator->FS.file.utildir; + fscreator->FS.file.util_h.dir = fscreator->FS.file.utildir; + + fscreator->FS.file.util_h.fname = str_tolower(fscreator->FS.gen.drvname + "-binutil.h"); + fscreator->FS.file.util_h.fpath = fscreator->FS.file.utildir + "/" + fscreator->FS.file.util_h.fname; + + fscreator->FS.file.util_c.fname = str_tolower(fscreator->FS.gen.drvname + "-binutil.c"); + fscreator->FS.file.util_c.fpath = fscreator->FS.file.utildir + "/" + fscreator->FS.file.util_c.fname; + + MsgsClassification groups; + + for (size_t i = 0; i < scanner->dblist.msgs.size(); i++) + { + auto m = scanner->dblist.msgs[i]; + + bool found = (std::find(m->TranS.begin(), m->TranS.end(), nodes[node]) != m->TranS.end()); + + if (found) + { + // Message is in Tx array of current node + groups.Tx.push_back(m->MsgID); + } + + found = (std::find(m->RecS.begin(), m->RecS.end(), nodes[node]) != m->RecS.end()); + + if (found) + { + // Message is in Rx array of current node + groups.Rx.push_back(m->MsgID); + } + } + + if (ret) + { + ciugen->Generate(scanner->dblist, fscreator->FS, groups, drvname.value); + } + } + } + else + { + MsgsClassification groups; + + for (size_t i = 0; i < scanner->dblist.msgs.size(); i++) + { + groups.Rx.push_back(scanner->dblist.msgs[i]->MsgID); + } + + if (ret) + { + ciugen->Generate(scanner->dblist, fscreator->FS, groups, drvname.value); + } + } +} + + +void CoderApp::PrintHelp() +{ + std::cout << "coderdbc v" << CODEGEN_LIB_VERSION_MAJ << "." << CODEGEN_LIB_VERSION_MIN << std::endl << std::endl; + std::cout << "project source code:\thttps://github.com/astand/c-coderdbc\t\t" << std::endl; + std::cout << "free web application:\thttps://coderdbc.com" << std::endl; + std::cout << std::endl; + std::cout << "required parameters:" << std::endl; + + std::cout << " -dbc\t\t path to dbc file" << std::endl; + std::cout << " -out\t\t directory for generated source files (must be pre-created)" << std::endl; + std::cout << " -drvname\t driver name - will be used for naming driver parts" << std::endl; + std::cout << std::endl; + std::cout << "optional parameters:" << std::endl; + std::cout << " -nodeutils\t will generate specific pairs of binutils drivers for each node" << std::endl; + std::cout << " -rw\t\t by default each new generation with previously used params" << std::endl; + std::cout << " \t\t will create new sud-directory with source files (000, 001, ... etc)" << std::endl; + std::cout << " \t\t '-rw' option enables rewriting: all source files previously generated" << std::endl; + std::cout << " \t\t will be replaced by new ones" << std::endl; + std::cout << std::endl; + + std::cout << "examples:" << std::endl; + std::cout << std::endl; + + std::cout << + "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb -nodeutils -rw" << std::endl; + + std::cout << + "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb -nodeutils" << std::endl; + + std::cout << "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb" << std::endl; + std::cout << std::endl; +} diff --git a/src/app.h b/src/app.h new file mode 100644 index 0000000..6557a37 --- /dev/null +++ b/src/app.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +class CoderApp { + public: + CoderApp(const std::vector>& params) : Params(params) {} + + void Run(); + + private: + bool ParseParams(); + void GenerateCode(); + void PrintHelp(); + + typedef struct app + { + std::string value; + bool ok{false}; + } StrParam_t; + + const std::vector>& Params; + + StrParam_t dbc{}; + StrParam_t outdir{}; + StrParam_t drvname{}; + + bool rewrite_src{false}; + bool gen_nodeutils{false}; +}; diff --git a/src/codegen/c-main-generator.cpp b/src/codegen/c-main-generator.cpp index 4906044..c01e7f6 100644 --- a/src/codegen/c-main-generator.cpp +++ b/src/codegen/c-main-generator.cpp @@ -8,6 +8,8 @@ #include #include #include "helpers/formatter.h" +#include "mon-generator.h" +#include "config-generator.h" #include "c-main-generator.h" @@ -26,15 +28,15 @@ const char* extend_func_body = "{\n" " ubitext_t const m = 1u << (bits - 1);\n" " return (val ^ m) - m;\n" - "}\n"; + "}\n\n"; CiMainGenerator::CiMainGenerator() { - sigprt = new CSigPrinter; - fwriter = new FileWriter; + sigprt = std::make_unique(); + fwriter = std::make_unique(); } -void CiMainGenerator::Generate(DbcMessageList_t& dlist, const FsDescriptor_t& fsd) +void CiMainGenerator::Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd) { p_dlist = &dlist; // Load income messages to sig printer @@ -75,26 +77,31 @@ void CiMainGenerator::Generate(DbcMessageList_t& dlist, const FsDescriptor_t& fs void CiMainGenerator::Gen_MainHeader() { // write comment start text - if (fdesc->start_info.size() > 0) + if (fdesc->gen.start_info.size() > 0) { // replace all '\n' on "\n //" for c code comment text - fwriter->AppendLine("// " + std::regex_replace(fdesc->start_info, std::regex("\n"), "\n// ")); + fwriter->Append("// " + std::regex_replace(fdesc->gen.start_info, std::regex("\n"), "\n// ")); } - fwriter->AppendLine("#pragma once", 2); - fwriter->AppendLine("#ifdef __cplusplus\nextern \"C\" {\n#endif", 2); - fwriter->AppendLine("#include ", 2); + fwriter->Append("#pragma once"); + fwriter->Append(); + fwriter->Append("#ifdef __cplusplus\nextern \"C\" {\n#endif"); + fwriter->Append(); + fwriter->Append("#include "); + fwriter->Append(); - fwriter->AppendLine("// DBC file version"); - fwriter->AppendLine(StrPrint("#define %s (%uU)", fdesc->verhigh_def.c_str(), p_dlist->ver.hi)); - fwriter->AppendLine(StrPrint("#define %s (%uU)", fdesc->verlow_def.c_str(), p_dlist->ver.low), 2); + fwriter->Append("// DBC file version"); + fwriter->Append("#define %s (%uU)", fdesc->gen.verhigh_def.c_str(), p_dlist->ver.hi); + fwriter->Append("#define %s (%uU)", fdesc->gen.verlow_def.c_str(), p_dlist->ver.low); + fwriter->Append(); - fwriter->AppendLine("// include current dbc-driver compilation config"); - fwriter->AppendLine(StrPrint("#include <%s-config.h>", fdesc->drvname.c_str()), 2); + fwriter->Append("// include current dbc-driver compilation config"); + fwriter->Append("#include <%s-config.h>", fdesc->gen.drvname.c_str()); + fwriter->Append(); - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usemon_def.c_str())); + fwriter->Append("#ifdef %s", fdesc->gen.usemon_def.c_str()); - fwriter->AppendText( + fwriter->Append( "// This file must define:\n" "// base monitor struct\n" "// function signature for HASH calculation: (@GetFrameHash)\n" @@ -103,7 +110,8 @@ void CiMainGenerator::Gen_MainHeader() "\n" ); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usemon_def.c_str()), 3); + fwriter->Append("#endif // %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(2); for (size_t num = 0; num < sigprt->sigs_expr.size(); num++) { @@ -113,17 +121,17 @@ void CiMainGenerator::Gen_MainHeader() if (m.CommentText.size() > 0) { // replace all '\n' on "\n //" for c code comment text - fwriter->AppendLine("// " + std::regex_replace(m.CommentText, std::regex("\n"), "\n// ")); + fwriter->Append("// " + std::regex_replace(m.CommentText, std::regex("\n"), "\n// ")); } - fwriter->AppendLine(StrPrint("// def @%s CAN Message (%-4d %#x)", m.Name.c_str(), m.MsgID, m.MsgID)); - fwriter->AppendLine(StrPrint("#define %s_IDE (%uU)", m.Name.c_str(), m.IsExt)); - fwriter->AppendLine(StrPrint("#define %s_DLC (%uU)", m.Name.c_str(), m.DLC)); - fwriter->AppendLine(StrPrint("#define %s_CANID (%#x)", m.Name.c_str(), m.MsgID)); + fwriter->Append("// def @%s CAN Message (%-4d %#x)", m.Name.c_str(), m.MsgID, m.MsgID); + fwriter->Append("#define %s_IDE (%uU)", m.Name.c_str(), m.IsExt); + fwriter->Append("#define %s_DLC (%uU)", m.Name.c_str(), m.DLC); + fwriter->Append("#define %s_CANID (%#x)", m.Name.c_str(), m.MsgID); if (m.Cycle > 0) { - fwriter->AppendLine(StrPrint("#define %s_CYC (%dU)", m.Name.c_str(), m.Cycle)); + fwriter->Append("#define %s_CYC (%dU)", m.Name.c_str(), m.Cycle); } size_t max_sig_name_len = 27; @@ -134,7 +142,7 @@ void CiMainGenerator::Gen_MainHeader() if (!s.IsSimpleSig) { - fwriter->AppendText(sigprt->PrintPhysicalToRaw(&s, fdesc->DRVNAME)); + fwriter->Append(sigprt->PrintPhysicalToRaw(&s, fdesc->gen.DRVNAME)); } if (s.Name.size() > max_sig_name_len) @@ -145,7 +153,8 @@ void CiMainGenerator::Gen_MainHeader() // For each signal in current message print value tables definitions if (s.ValDefs.vpairs.size() > 0) { - fwriter->AppendLine(StrPrint("\n// Value tables for @%s signal", s.Name.c_str()), 2); + fwriter->Append("\n// Value tables for @%s signal", s.Name.c_str()); + fwriter->Append(); for (auto i = 0; i < s.ValDefs.vpairs.size(); i++) { @@ -156,25 +165,25 @@ void CiMainGenerator::Gen_MainHeader() // @ifndef guard for the case when different values of table have // the same name (it is valid for DBC file format) // For this case only one of same named values will be available as macro - fwriter->AppendLine(StrPrint("#ifndef %s", defname.c_str())); + fwriter->Append("#ifndef %s", defname.c_str()); - fwriter->AppendLine(StrPrint("#define %s_%s_%s (%d)", - s.Name.c_str(), m.Name.c_str(), s.ValDefs.vpairs[i].first.c_str(), - s.ValDefs.vpairs[i].second)); + fwriter->Append("#define %s_%s_%s (%d)", + s.Name.c_str(), m.Name.c_str(), s.ValDefs.vpairs[i].first.c_str(), + s.ValDefs.vpairs[i].second); - fwriter->AppendLine(StrPrint("#endif"), 2); + fwriter->Append("#endif"); + fwriter->Append(); } } } - fwriter->AppendText("\n"); - - fwriter->AppendLine(StrPrint("typedef struct")); - - fwriter->AppendLine("{"); + fwriter->Append(); + fwriter->Append("typedef struct"); + fwriter->Append("{"); // Write section for bitfielded part - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usebits_def.c_str()), 2); + fwriter->Append("#ifdef %s", fdesc->gen.usebits_def.c_str()); + fwriter->Append(); SignalDescriptor_t rollsig; @@ -195,13 +204,16 @@ void CiMainGenerator::Gen_MainHeader() if (m.RollSig != nullptr) { - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->useroll_def.c_str()), 2); + fwriter->Append("#ifdef %s", fdesc->gen.useroll_def.c_str()); + fwriter->Append(); WriteSigStructField(rollsig, true, max_sig_name_len); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->useroll_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.useroll_def.c_str()); + fwriter->Append(); } // Write clean part - fwriter->AppendLine("#else", 2); + fwriter->Append("#else"); + fwriter->Append(); for (size_t signum = 0; signum < m.Signals.size(); signum++) { @@ -212,80 +224,93 @@ void CiMainGenerator::Gen_MainHeader() if (m.RollSig != nullptr) { - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->useroll_def.c_str()), 2); + fwriter->Append("#ifdef %s", fdesc->gen.useroll_def.c_str()); + fwriter->Append(); WriteSigStructField(rollsig, false, max_sig_name_len); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->useroll_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.useroll_def.c_str()); + fwriter->Append(); } - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usebits_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.usebits_def.c_str()); + fwriter->Append(); // start mon1 section - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usemon_def.c_str()), 2); - fwriter->AppendLine(" FrameMonitor_t mon1;", 2); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usemon_def.c_str()), 2); - fwriter->AppendLine(StrPrint("} %s_t;", m.Name.c_str()), 2); + fwriter->Append("#ifdef %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(); + fwriter->Append(" FrameMonitor_t mon1;"); + fwriter->Append(); + fwriter->Append("#endif // %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(); + fwriter->Append("} %s_t;", m.Name.c_str()); + fwriter->Append(); } - fwriter->AppendLine("// Function signatures", 2); + fwriter->Append("// Function signatures"); + fwriter->Append(); for (size_t num = 0; num < sigprt->sigs_expr.size(); num++) { // write message typedef s and additional expressions MessageDescriptor_t& m = sigprt->sigs_expr[num]->msg; - fwriter->AppendLine(StrPrint("uint32_t Unpack_%s_%s(%s_t* _m, const uint8_t* _d, uint8_t dlc_);", - m.Name.c_str(), fdesc->DrvName_orig.c_str(), m.Name.c_str())); + fwriter->Append("uint32_t Unpack_%s_%s(%s_t* _m, const uint8_t* _d, uint8_t dlc_);", + m.Name.c_str(), fdesc->gen.DrvName_orig.c_str(), m.Name.c_str()); - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usesruct_def.c_str())); + fwriter->Append("#ifdef %s", fdesc->gen.usesruct_def.c_str()); - fwriter->AppendLine(StrPrint("uint32_t Pack_%s_%s(%s_t* _m, __CoderDbcCanFrame_t__* cframe);", - m.Name.c_str(), fdesc->DrvName_orig.c_str(), m.Name.c_str())); + fwriter->Append("uint32_t Pack_%s_%s(%s_t* _m, __CoderDbcCanFrame_t__* cframe);", + m.Name.c_str(), fdesc->gen.DrvName_orig.c_str(), m.Name.c_str()); - fwriter->AppendLine("#else"); + fwriter->Append("#else"); - fwriter->AppendLine(StrPrint("uint32_t Pack_%s_%s(%s_t* _m, uint8_t* _d, uint8_t* _len, uint8_t* _ide);", - m.Name.c_str(), fdesc->DrvName_orig.c_str(), m.Name.c_str())); + fwriter->Append("uint32_t Pack_%s_%s(%s_t* _m, uint8_t* _d, uint8_t* _len, uint8_t* _ide);", + m.Name.c_str(), fdesc->gen.DrvName_orig.c_str(), m.Name.c_str()); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usesruct_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.usesruct_def.c_str()); + fwriter->Append(); } - fwriter->AppendLine("#ifdef __cplusplus\n}\n#endif"); + fwriter->Append("#ifdef __cplusplus\n}\n#endif"); // save fwrite cached text to file - fwriter->Flush(fdesc->core_h.fpath); + fwriter->Flush(fdesc->file.core_h.fpath); } void CiMainGenerator::Gen_MainSource() { - if (fdesc->start_info.size() > 0) + if (fdesc->gen.start_info.size() > 0) { // replace all '\n' on "\n //" for c code comment text - fwriter->AppendLine("// " + std::regex_replace(fdesc->start_info, std::regex("\n"), "\n// ")); + fwriter->Append("// " + std::regex_replace(fdesc->gen.start_info, std::regex("\n"), "\n// ")); } // include main header file - fwriter->AppendLine(StrPrint("#include \"%s\"", fdesc->core_h.fname.c_str()), 3); + fwriter->Append("#include \"%s\"", fdesc->file.core_h.fname.c_str()); + fwriter->Append(2); - fwriter->AppendLine("// DBC file version"); - fwriter->AppendLine(StrPrint("#if (%s != (%uU)) || (%s != (%uU))", - fdesc->verhigh_def.c_str(), p_dlist->ver.hi, fdesc->verlow_def.c_str(), p_dlist->ver.low)); + fwriter->Append("// DBC file version"); + fwriter->Append("#if (%s != (%uU)) || (%s != (%uU))", + fdesc->gen.verhigh_def.c_str(), p_dlist->ver.hi, fdesc->gen.verlow_def.c_str(), p_dlist->ver.low); - fwriter->AppendLine(StrPrint("#error The %s dbc source files have different versions", fdesc->DRVNAME.c_str())); - fwriter->AppendLine("#endif", 2); + fwriter->Append("#error The %s dbc source files have different versions", fdesc->gen.DRVNAME.c_str()); + fwriter->Append("#endif"); + fwriter->Append(); // put diagmonitor ifdef selection for including @drv-fmon header // with FMon_* signatures to call from unpack function - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usemon_def.c_str())); + fwriter->Append("#ifdef %s", fdesc->gen.usemon_def.c_str()); - fwriter->AppendText( + fwriter->Append( "// Function prototypes to be called each time CAN frame is unpacked\n" "// FMon function may detect RC, CRC or DLC violation\n"); - fwriter->AppendLine(StrPrint("#include <%s-fmon.h>", fdesc->drvname.c_str()), 2); + fwriter->Append("#include <%s-fmon.h>", fdesc->gen.drvname.c_str()); + fwriter->Append(); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usemon_def.c_str()), 3); + fwriter->Append("#endif // %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(2); - fwriter->AppendLine(StrPrint(extend_func_body, ext_sig_func_name), 1); + fwriter->Append(extend_func_body, ext_sig_func_name), 1; // for each message 3 functions must be defined - 1 unpack function, // 2: pack with raw signature @@ -296,337 +321,242 @@ void CiMainGenerator::Gen_MainSource() MessageDescriptor_t& m = sigprt->sigs_expr[num]->msg; // first function - fwriter->AppendLine(StrPrint("uint32_t Unpack_%s_%s(%s_t* _m, const uint8_t* _d, uint8_t dlc_)\n{", - m.Name.c_str(), fdesc->DrvName_orig.c_str(), m.Name.c_str())); + fwriter->Append("uint32_t Unpack_%s_%s(%s_t* _m, const uint8_t* _d, uint8_t dlc_)\n{", + m.Name.c_str(), fdesc->gen.DrvName_orig.c_str(), m.Name.c_str()); // put dirt trick to avoid warning about unusing parameter // (dlc) when monitora are disabled. trick is better than // selection different signatures because of external API consistency - fwriter->AppendLine(" (void)dlc_;"); + fwriter->Append(" (void)dlc_;"); WriteUnpackBody(sigprt->sigs_expr[num]); - fwriter->AppendLine("}", 2); + fwriter->Append("}"); + fwriter->Append(); // next one is the pack function for using with CANFrame struct - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usesruct_def.c_str()), 2); + fwriter->Append("#ifdef %s", fdesc->gen.usesruct_def.c_str()); + fwriter->Append(); // second function - fwriter->AppendLine(StrPrint("uint32_t Pack_%s_%s(%s_t* _m, __CoderDbcCanFrame_t__* cframe)", - m.Name.c_str(), fdesc->DrvName_orig.c_str(), m.Name.c_str())); + fwriter->Append("uint32_t Pack_%s_%s(%s_t* _m, __CoderDbcCanFrame_t__* cframe)", + m.Name.c_str(), fdesc->gen.DrvName_orig.c_str(), m.Name.c_str()); WritePackStructBody(sigprt->sigs_expr[num]); - fwriter->AppendLine("#else", 2); + fwriter->Append("#else"); + fwriter->Append(); // third function - fwriter->AppendLine(StrPrint("uint32_t Pack_%s_%s(%s_t* _m, uint8_t* _d, uint8_t* _len, uint8_t* _ide)", - m.Name.c_str(), fdesc->DrvName_orig.c_str(), m.Name.c_str())); + fwriter->Append("uint32_t Pack_%s_%s(%s_t* _m, uint8_t* _d, uint8_t* _len, uint8_t* _ide)", + m.Name.c_str(), fdesc->gen.DrvName_orig.c_str(), m.Name.c_str()); WritePackArrayBody(sigprt->sigs_expr[num]); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usesruct_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.usesruct_def.c_str()); + fwriter->Append(); } - fwriter->Flush(fdesc->core_c.fpath); + fwriter->Flush(fdesc->file.core_c.fpath); } void CiMainGenerator::Gen_ConfigHeader() { - if (fdesc->start_info.size() > 0) + if (fdesc->gen.start_info.size() > 0) { // replace all '\n' on "\n //" for c code comment text - fwriter->AppendLine("// " + std::regex_replace(fdesc->start_info, std::regex("\n"), "\n// ")); + fwriter->Append("// " + std::regex_replace(fdesc->gen.start_info, std::regex("\n"), "\n// ")); } - fwriter->AppendLine("#pragma once"); - fwriter->AppendLine(""); - fwriter->AppendLine("/* include common dbccode configurations */"); - fwriter->AppendLine("#include "); - fwriter->AppendLine(""); - fwriter->AppendLine(""); - fwriter->AppendLine("/* ------------------------------------------------------------------------- *"); - fwriter->AppendLine(" This define enables using CAN message structs with bit-fielded signals"); - fwriter->AppendLine(" layout."); - fwriter->AppendLine(""); - fwriter->AppendLine(" Note(!): bit-feild was not tested properly. */"); - fwriter->AppendLine(""); - fwriter->AppendLine(StrPrint("/* #define %s */", fdesc->usebits_def.c_str()), 3); - - fwriter->AppendLine("/* ------------------------------------------------------------------------- *"); - fwriter->AppendLine(" This macro enables using CAN message descriptive struct packing functions"); - fwriter->AppendLine(" (by default signature of pack function intakes a few simple typed params"); - fwriter->AppendLine(" for loading data, len, etc). To compile you need to define the struct"); - fwriter->AppendLine(" __CoderDbcCanFrame_t__ which must have fields:"); - fwriter->AppendLine(""); - fwriter->AppendLine(" u32 MsgId (CAN Frame message ID)"); - fwriter->AppendLine(" u8 DLC (CAN Frame payload length field)"); - fwriter->AppendLine(" u8 Data[8] (CAN Frame payload data)"); - fwriter->AppendLine(" u8 IDE (CAN Frame Extended (1) / Standard (0) ID type)"); - fwriter->AppendLine(""); - fwriter->AppendLine(" This struct definition have to be placed (or be included) in dbccodeconf.h */"); - fwriter->AppendLine(""); - fwriter->AppendLine(StrPrint("/* #define %s */", fdesc->usesruct_def.c_str()), 3); - - fwriter->AppendLine("/* ------------------------------------------------------------------------- *"); - fwriter->AppendLine(" All the signals which have values of factor != 1 or offset != 0"); - fwriter->AppendLine(" will be named in message struct with posfix '_ro'. Pack to payload"); - fwriter->AppendLine(" operations will be made on this signal value as well as unpack from payload."); - fwriter->AppendLine(""); - fwriter->AppendLine(" USE_SIGFLOAT macro makes some difference:"); - fwriter->AppendLine(""); - fwriter->AppendLine(" 1. All the '_ro' fields will have a pair field with '_phys' postfix."); - fwriter->AppendLine(" If only offset != 0 is true then the type of '_phys' signal is the same"); - fwriter->AppendLine(" as '_ro' signal. In other case the type will be @sigfloat_t which"); - fwriter->AppendLine(" have to be defined in user dbccodeconf.h"); - fwriter->AppendLine(""); - fwriter->AppendLine(" 2. In pack function '_ro' signal will be rewritten by '_phys' signal, which"); - fwriter->AppendLine(" requires from user to use ONLY '_phys' signal for packing frame"); - fwriter->AppendLine(""); - fwriter->AppendLine(" 3. In unpack function '_phys' signal will be written by '_ro' signal."); - fwriter->AppendLine(" User have to use '_phys' signal to read physical value. */"); - fwriter->AppendLine(""); - fwriter->AppendLine(StrPrint("/* #define %s */", fdesc->usesigfloat_def.c_str()), 3); - - fwriter->AppendLine("/* ------------------------------------------------------------------------- *"); - fwriter->AppendLine(" Note(!) that the \"canmonitorutil.h\" must be accessed in include path:"); - fwriter->AppendLine(""); - fwriter->AppendLine(" This macro adds:"); - fwriter->AppendLine(""); - fwriter->AppendLine(" - monitor field @mon1 to message struct"); - fwriter->AppendLine(""); - fwriter->AppendLine(" - capture system tick in unpack function and save value to mon1 field"); - fwriter->AppendLine(" to provide to user better missing frame detection code. For this case"); - fwriter->AppendLine(" user must provide function declared in canmonitorutil.h - GetSysTick()"); - fwriter->AppendLine(" which may return 1ms uptime."); - fwriter->AppendLine(""); - fwriter->AppendLine(" - calling function FMon_*** (from 'fmon' driver) inside unpack function"); - fwriter->AppendLine(" which is empty by default and have to be filled by user if"); - fwriter->AppendLine(" tests for DLC, rolling, checksum are necessary */"); - fwriter->AppendLine(""); - fwriter->AppendLine(StrPrint("/* #define %s */", fdesc->usemon_def.c_str()), 3); - - fwriter->AppendLine("/* ------------------------------------------------------------------------- *"); - fwriter->AppendLine(StrPrint(" When monitor using is enabled (%s) and define below", fdesc->usemon_def.c_str())); - fwriter->AppendLine(" uncommented, additional signal will be added to message struct. ***_expt:"); - fwriter->AppendLine(" expected rolling counter, to perform monitoring rolling counter sequence"); - fwriter->AppendLine(" automatically (result may be tested in dedicated Fmon_*** function) */"); - fwriter->AppendLine(""); - fwriter->AppendLine(StrPrint("/* #define %s */", fdesc->useroll_def.c_str()), 3); - - fwriter->AppendLine("/* ------------------------------------------------------------------------- *"); - fwriter->AppendLine(StrPrint(" When monitor using is enabled (%s) and define below", fdesc->usemon_def.c_str())); - fwriter->AppendLine(" uncommented, frame checksum signal may be handled automatically."); - fwriter->AppendLine(""); - fwriter->AppendLine(" The signal which may be marked as checksum signal must have substring"); - fwriter->AppendLine(" with next format:"); - fwriter->AppendLine(" "); - fwriter->AppendLine(""); - fwriter->AppendLine(" where:"); - fwriter->AppendLine(""); - fwriter->AppendLine(" - \"Checksum\": constant marker word"); - fwriter->AppendLine(""); - fwriter->AppendLine(" - \"XOR8\": type of method, this text will be passed to GetFrameHash"); - fwriter->AppendLine(" (canmonitorutil.h) function as is, the best use case is to define 'enum"); - fwriter->AppendLine(" DbcCanCrcMethods' in canmonitorutil.h file with all possible"); - fwriter->AppendLine(" checksum algorithms (e.g. XOR8, XOR4 etc)"); - fwriter->AppendLine(""); - fwriter->AppendLine(" - \"3\": optional value that will be passed to GetFrameHash as integer value"); - fwriter->AppendLine(""); - fwriter->AppendLine(" Function GetFrameHash have to be implemented by user"); - fwriter->AppendLine(""); - fwriter->AppendLine(" In pack function checksum signal will be calculated automatically"); - fwriter->AppendLine(" and loaded to payload"); - fwriter->AppendLine(""); - fwriter->AppendLine(" In unpack function checksum signal is checked with calculated."); - fwriter->AppendLine(" (result may be tested in dedicated Fmon_*** function). */"); - fwriter->AppendLine(""); - fwriter->AppendLine(StrPrint("/* #define %s */", fdesc->usecsm_def.c_str()), 2); - - fwriter->Flush(fdesc->confdir + '/' + fdesc->drvname + "-config.h"); + ConfigGenerator confgen; + confgen.FillHeader((*fwriter), fdesc->gen); + + fwriter->Flush(fdesc->file.confdir + '/' + fdesc->gen.drvname + "-config.h"); } void CiMainGenerator::Gen_FMonHeader() { - if (fdesc->start_info.size() > 0) + if (fdesc->gen.start_info.size() > 0) { // replace all '\n' on "\n //" for c code comment text - fwriter->AppendLine("// " + std::regex_replace(fdesc->start_info, std::regex("\n"), "\n// ")); + fwriter->Append("// " + std::regex_replace(fdesc->gen.start_info, std::regex("\n"), "\n// ")); } - fwriter->AppendLine("#pragma once", 2); + fwriter->Append("#pragma once"); + fwriter->Append(); - fwriter->AppendLine("#ifdef __cplusplus\nextern \"C\" {\n#endif", 2); + fwriter->Append("#ifdef __cplusplus\nextern \"C\" {\n#endif"); + fwriter->Append(); - fwriter->AppendLine("// DBC file version"); - fwriter->AppendLine(StrPrint("#define %s_FMON (%uU)", fdesc->verhigh_def.c_str(), p_dlist->ver.hi)); - fwriter->AppendLine(StrPrint("#define %s_FMON (%uU)", fdesc->verlow_def.c_str(), p_dlist->ver.low), 2); + fwriter->Append("// DBC file version"); + fwriter->Append("#define %s_FMON (%uU)", fdesc->gen.verhigh_def.c_str(), p_dlist->ver.hi); + fwriter->Append("#define %s_FMON (%uU)", fdesc->gen.verlow_def.c_str(), p_dlist->ver.low); + fwriter->Append(); - fwriter->AppendLine(StrPrint("#include <%s-config.h>", fdesc->drvname.c_str()), 2); + fwriter->Append("#include <%s-config.h>", fdesc->gen.drvname.c_str()); + fwriter->Append(); // put diagmonitor ifdef selection for including @drv-fmon header // with FMon_* signatures to call from unpack function - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usemon_def.c_str()), 2); - fwriter->AppendLine("#include "); - fwriter->AppendLine("/*\n\ + fwriter->Append("#ifdef %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(); + fwriter->Append("#include "); + fwriter->Append("/*\n\ This file contains the prototypes of all the functions that will be called\n\ from each Unpack_*name* function to detect DBC related errors\n\ It is the user responsibility to defined these functions in the\n\ -separated .c file. If it won't be done the linkage error will happen\n*/", 2); +separated .c file. If it won't be done the linkage error will happen\n*/"); + fwriter->Append(); - for (size_t num = 0; num < sigprt->sigs_expr.size(); num++) - { - auto msg = &(sigprt->sigs_expr[num]->msg); - fwriter->AppendLine(StrPrint("void FMon_%s_%s(FrameMonitor_t* _mon, uint32_t msgid);", - msg->Name.c_str(), fdesc->drvname.c_str())); - } + MonGenerator mongen; - fwriter->AppendLine(StrPrint("\n#endif // %s", fdesc->usemon_def.c_str()), 2); + mongen.FillHeader((*fwriter), sigprt->sigs_expr, fdesc->gen); - fwriter->AppendLine("#ifdef __cplusplus\n}\n#endif"); + fwriter->Append("#endif // %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(); - fwriter->Flush(fdesc->fmon_h.fpath); + fwriter->Append("#ifdef __cplusplus\n}\n#endif"); + + fwriter->Flush(fdesc->file.fmon_h.fpath); } void CiMainGenerator::Gen_FMonSource() { - if (fdesc->start_info.size() > 0) + if (fdesc->gen.start_info.size() > 0) { // replace all '\n' on "\n //" for c code comment text - fwriter->AppendLine("// " + std::regex_replace(fdesc->start_info, std::regex("\n"), "\n// ")); + fwriter->Append("// " + std::regex_replace(fdesc->gen.start_info, std::regex("\n"), "\n// ")); } - fwriter->AppendLine(StrPrint("#include <%s>", fdesc->fmon_h.fname.c_str()), 2); + fwriter->Append("#include <%s>", fdesc->file.fmon_h.fname.c_str()); + fwriter->Append(); // put diagmonitor ifdef selection for including @drv-fmon header -// with FMon_* signatures to call from unpack function - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usemon_def.c_str()), 2); + // with FMon_* signatures to call from unpack function + fwriter->Append("#ifdef %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(); - fwriter->AppendLine("/*\n\ + fwriter->Append("/*\n\ Put the monitor function content here, keep in mind -\n\ next generation will completely clear all manually added code (!)\n\ -*/\n"); +*/\n\n"); - for (size_t num = 0; num < sigprt->sigs_expr.size(); num++) - { - auto msg = &(sigprt->sigs_expr[num]->msg); - fwriter->AppendLine( - StrPrint("void FMon_%s_%s(FrameMonitor_t* _mon, uint32_t msgid)\n{\n (void)_mon;\n (void)msgid;\n}\n", - msg->Name.c_str(), fdesc->drvname.c_str())); - } + MonGenerator mongen; + + mongen.FillSource((*fwriter), sigprt->sigs_expr, fdesc->gen); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usemon_def.c_str())); + fwriter->Append("#endif // %s", fdesc->gen.usemon_def.c_str()); - fwriter->Flush(fdesc->fmon_c.fpath); + fwriter->Flush(fdesc->file.fmon_c.fpath); } void CiMainGenerator::Gen_CanMonUtil() { - fwriter->AppendLine("#pragma once"); - fwriter->AppendLine(""); - fwriter->AppendLine("#include "); - fwriter->AppendLine(""); - fwriter->AppendLine("#ifdef __cplusplus"); - fwriter->AppendLine("extern \"C\" {"); - fwriter->AppendLine("#endif"); - fwriter->AppendLine(""); - fwriter->AppendLine("// declare here all availible checksum algorithms"); - fwriter->AppendLine("typedef enum"); - fwriter->AppendLine("{"); - fwriter->AppendLine(" // XOR8 = 0,"); - fwriter->AppendLine(" // XOR4 = 1,"); - fwriter->AppendLine(" // etc"); - fwriter->AppendLine("} DbcCanCrcMethods;"); - fwriter->AppendLine(""); - fwriter->AppendLine("typedef struct"); - fwriter->AppendLine("{"); - fwriter->AppendLine(" // @last_cycle keeps tick-value when last frame was received"); - fwriter->AppendLine(" uint32_t last_cycle;"); - fwriter->AppendLine(""); - fwriter->AppendLine(" // @timeout_cycle keeps maximum timeout for frame, user responsibility"); - fwriter->AppendLine(" // to init this field and use it in missing frame monitoring function"); - fwriter->AppendLine(" uint32_t timeout_cycle;"); - fwriter->AppendLine(""); - fwriter->AppendLine(" // @frame_cnt keeps count of all the received frames"); - fwriter->AppendLine(" uint32_t frame_cnt;"); - fwriter->AppendLine(""); - fwriter->AppendLine(" // setting up @roll_error bit indicates roll counting fail."); - fwriter->AppendLine(" // Bit is not clearing automatically!"); - fwriter->AppendLine(" uint32_t roll_error : 1;"); - fwriter->AppendLine(""); - fwriter->AppendLine(" // setting up @checksum_error bit indicates checksum checking failure."); - fwriter->AppendLine(" // Bit is not clearing automatically!"); - fwriter->AppendLine(" uint32_t csm_error : 1;"); - fwriter->AppendLine(""); - fwriter->AppendLine(" // setting up @cycle_error bit indicates that time was overrunned."); - fwriter->AppendLine(" // Bit is not clearing automatically!"); - fwriter->AppendLine(" uint32_t cycle_error : 1;"); - fwriter->AppendLine(""); - fwriter->AppendLine(" // setting up @dlc_error bit indicates that the actual length of"); - fwriter->AppendLine(" // CAN frame is less then defined by CAN matrix!"); - fwriter->AppendLine(" uint32_t dlc_error : 1;"); - fwriter->AppendLine(""); - fwriter->AppendLine("} FrameMonitor_t;"); - fwriter->AppendLine(""); - fwriter->AppendLine("/* ----------------------------------------------------------------------------- */"); - fwriter->AppendLine("// @d - buff for hash calculation"); - fwriter->AppendLine("// @len - number of bytes for hash calculation"); - fwriter->AppendLine("// @method - hash algorythm."); - fwriter->AppendLine("// @op - optional value"); - fwriter->AppendLine("uint8_t GetFrameHash(const uint8_t* data_ptr, uint8_t len, uint32_t msgid, DbcCanCrcMethods type, uint32_t option);"); - fwriter->AppendLine(""); - fwriter->AppendLine("/* ----------------------------------------------------------------------------- */"); - fwriter->AppendLine("// this function will be called when unpacking is performing. Value will be saved"); - fwriter->AppendLine("// in @last_cycle variable"); - fwriter->AppendLine("uint32_t GetSystemTick(void);"); - fwriter->AppendLine(""); - fwriter->AppendLine(""); - fwriter->AppendLine("#ifdef __cplusplus"); - fwriter->AppendLine("}"); - fwriter->AppendLine("#endif"); - fwriter->AppendLine(""); - - fwriter->Flush(fdesc->incdir + '/' + "canmonitorutil.h"); + fwriter->Append("#pragma once"); + fwriter->Append(""); + fwriter->Append("#include "); + fwriter->Append(""); + fwriter->Append("#ifdef __cplusplus"); + fwriter->Append("extern \"C\" {"); + fwriter->Append("#endif"); + fwriter->Append(""); + fwriter->Append("// declare here all availible checksum algorithms"); + fwriter->Append("typedef enum"); + fwriter->Append("{"); + fwriter->Append(" // XOR8 = 0,"); + fwriter->Append(" // XOR4 = 1,"); + fwriter->Append(" // etc"); + fwriter->Append("} DbcCanCrcMethods;"); + fwriter->Append(""); + fwriter->Append("typedef struct"); + fwriter->Append("{"); + fwriter->Append(" // @last_cycle keeps tick-value when last frame was received"); + fwriter->Append(" uint32_t last_cycle;"); + fwriter->Append(""); + fwriter->Append(" // @timeout_cycle keeps maximum timeout for frame, user responsibility"); + fwriter->Append(" // to init this field and use it in missing frame monitoring function"); + fwriter->Append(" uint32_t timeout_cycle;"); + fwriter->Append(""); + fwriter->Append(" // @frame_cnt keeps count of all the received frames"); + fwriter->Append(" uint32_t frame_cnt;"); + fwriter->Append(""); + fwriter->Append(" // setting up @roll_error bit indicates roll counting fail."); + fwriter->Append(" // Bit is not clearing automatically!"); + fwriter->Append(" uint32_t roll_error : 1;"); + fwriter->Append(""); + fwriter->Append(" // setting up @checksum_error bit indicates checksum checking failure."); + fwriter->Append(" // Bit is not clearing automatically!"); + fwriter->Append(" uint32_t csm_error : 1;"); + fwriter->Append(""); + fwriter->Append(" // setting up @cycle_error bit indicates that time was overrunned."); + fwriter->Append(" // Bit is not clearing automatically!"); + fwriter->Append(" uint32_t cycle_error : 1;"); + fwriter->Append(""); + fwriter->Append(" // setting up @dlc_error bit indicates that the actual length of"); + fwriter->Append(" // CAN frame is less then defined by CAN matrix!"); + fwriter->Append(" uint32_t dlc_error : 1;"); + fwriter->Append(""); + fwriter->Append("} FrameMonitor_t;"); + fwriter->Append(""); + fwriter->Append("/* ----------------------------------------------------------------------------- */"); + fwriter->Append("// @d - buff for hash calculation"); + fwriter->Append("// @len - number of bytes for hash calculation"); + fwriter->Append("// @method - hash algorythm."); + fwriter->Append("// @op - optional value"); + fwriter->Append("uint8_t GetFrameHash(const uint8_t* data_ptr, uint8_t len, uint32_t msgid, DbcCanCrcMethods type, uint32_t option);"); + fwriter->Append(""); + fwriter->Append("/* ----------------------------------------------------------------------------- */"); + fwriter->Append("// this function will be called when unpacking is performing. Value will be saved"); + fwriter->Append("// in @last_cycle variable"); + fwriter->Append("uint32_t GetSystemTick(void);"); + fwriter->Append(""); + fwriter->Append(""); + fwriter->Append("#ifdef __cplusplus"); + fwriter->Append("}"); + fwriter->Append("#endif"); + fwriter->Append(""); + + fwriter->Flush(fdesc->file.incdir + '/' + "canmonitorutil.h"); } void CiMainGenerator::Gen_DbcCodeConf() { - fwriter->AppendLine("#pragma once"); - fwriter->AppendLine(""); - fwriter->AppendLine("#include "); - fwriter->AppendLine(""); - fwriter->AppendLine("// when USE_SIGFLOAT enabed the sigfloat_t must be defined"); - fwriter->AppendLine("// typedef double sigfloat_t;"); - fwriter->AppendLine(""); - fwriter->AppendLine("// when USE_CANSTRUCT enabled __CoderDbcCanFrame_t__ must be defined"); - fwriter->AppendLine("// #include \"{header_with_can_struct}\""); - fwriter->AppendLine("// typedef {can_struct} __CoderDbcCanFrame_t__;"); - fwriter->AppendLine(""); - fwriter->AppendLine("// if you need to allocate rx and tx messages structs put the allocation macro here"); - fwriter->AppendLine("// #define __DEF_{your_driver_name}__"); - fwriter->AppendLine(""); - - fwriter->Flush(fdesc->confdir + '/' + "dbccodeconf.h"); + fwriter->Append("#pragma once"); + fwriter->Append(""); + fwriter->Append("#include "); + fwriter->Append(""); + fwriter->Append("// when USE_SIGFLOAT enabed the sigfloat_t must be defined"); + fwriter->Append("// typedef double sigfloat_t;"); + fwriter->Append(""); + fwriter->Append("// when USE_CANSTRUCT enabled __CoderDbcCanFrame_t__ must be defined"); + fwriter->Append("// #include \"{header_with_can_struct}\""); + fwriter->Append("// typedef {can_struct} __CoderDbcCanFrame_t__;"); + fwriter->Append(""); + fwriter->Append("// if you need to allocate rx and tx messages structs put the allocation macro here"); + fwriter->Append("// #define __DEF_{your_driver_name}__"); + fwriter->Append(""); + + fwriter->Flush(fdesc->file.confdir + '/' + "dbccodeconf.h"); } void CiMainGenerator::WriteSigStructField(const SignalDescriptor_t& sig, bool bits, size_t padwidth) { if (sig.CommentText.size() > 0) { - fwriter->AppendLine(" // " + std::regex_replace(sig.CommentText, std::regex("\n"), "\n // ")); + fwriter->Append(" // " + std::regex_replace(sig.CommentText, std::regex("\n"), "\n // ")); } if (sig.ValueText.size() > 0) { - fwriter->AppendLine(" // " + std::regex_replace(sig.ValueText, std::regex("\n"), "\n // ")); + fwriter->Append(" // " + std::regex_replace(sig.ValueText, std::regex("\n"), "\n // ")); } if (sig.Multiplex == MultiplexType::kMulValue) { - fwriter->AppendLine(" // multiplex variable"); + fwriter->Append(" // multiplex variable"); } else if (sig.Multiplex == MultiplexType::kMaster) { - fwriter->AppendLine(" // MULTIPLEX master signal"); + fwriter->Append(" // MULTIPLEX master signal"); } std::string dtype = ""; @@ -651,7 +581,7 @@ void CiMainGenerator::WriteSigStructField(const SignalDescriptor_t& sig, bool bi fwriter->AppendText(pad); - fwriter->AppendText(StrPrint(" Bits=%2d", sig.LengthBit)); + fwriter->AppendText(" Bits=%2d", sig.LengthBit); size_t offset = 0; std::string infocmnt{}; @@ -698,7 +628,8 @@ void CiMainGenerator::WriteSigStructField(const SignalDescriptor_t& sig, bool bi fwriter->AppendText(infocmnt); - fwriter->AppendLine("", 2); + fwriter->Append(""); + fwriter->Append(); if (!sig.IsSimpleSig) { @@ -712,18 +643,19 @@ void CiMainGenerator::WriteSigStructField(const SignalDescriptor_t& sig, bool bi // own 'shadow' (_phys) copies, the problem with intermediate type (not simpe and // not double) is that the x = ***_toS(x) takes place in each Pack_* call // the signals which are not changing from Pack_* to Pack_* will change its values (!) - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usesigfloat_def.c_str())); + fwriter->Append("#ifdef %s", fdesc->gen.usesigfloat_def.c_str()); if (sig.IsDoubleSig) { - fwriter->AppendLine(StrPrint(" sigfloat_t %s;", sig.NameFloat.c_str())); + fwriter->Append(" sigfloat_t %s;", sig.NameFloat.c_str()); } else { - fwriter->AppendLine(StrPrint(" %s %s;", PrintType((int)sig.TypePhys).c_str(), sig.NameFloat.c_str())); + fwriter->Append(" %s %s;", PrintType((int)sig.TypePhys).c_str(), sig.NameFloat.c_str()); } - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usesigfloat_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.usesigfloat_def.c_str()); + fwriter->Append(); } } @@ -738,97 +670,103 @@ void CiMainGenerator::WriteUnpackBody(const CiExpr_t* sgs) if (sgs->msg.Signals[num].Signed) { - fwriter->AppendLine(StrPrint(" _m->%s = %s(( %s ), %d);", - sname, ext_sig_func_name, expr.c_str(), (int32_t)sgs->msg.Signals[num].LengthBit)); + fwriter->Append(" _m->%s = %s(( %s ), %d);", + sname, ext_sig_func_name, expr.c_str(), (int32_t)sgs->msg.Signals[num].LengthBit); } else { - fwriter->AppendLine(StrPrint(" _m->%s = %s;", sname, expr.c_str())); + fwriter->Append(" _m->%s = %s;", sname, expr.c_str()); } // print sigfloat conversion if (!sgs->msg.Signals[num].IsSimpleSig) { - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usesigfloat_def.c_str())); + fwriter->Append("#ifdef %s", fdesc->gen.usesigfloat_def.c_str()); if (sgs->msg.Signals[num].IsDoubleSig) { // for double signals (sigfloat_t) type cast - fwriter->AppendLine(StrPrint(" _m->%s = (sigfloat_t)(%s_%s_fromS(_m->%s));", - sgs->msg.Signals[num].NameFloat.c_str(), fdesc->DRVNAME.c_str(), sname, sname)); + fwriter->Append(" _m->%s = (sigfloat_t)(%s_%s_fromS(_m->%s));", + sgs->msg.Signals[num].NameFloat.c_str(), fdesc->gen.DRVNAME.c_str(), sname, sname); } else { - fwriter->AppendLine(StrPrint(" _m->%s = %s_%s_fromS(_m->%s);", - sgs->msg.Signals[num].NameFloat.c_str(), fdesc->DRVNAME.c_str(), sname, sname)); + fwriter->Append(" _m->%s = %s_%s_fromS(_m->%s);", + sgs->msg.Signals[num].NameFloat.c_str(), fdesc->gen.DRVNAME.c_str(), sname, sname); } - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usesigfloat_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.usesigfloat_def.c_str()); + fwriter->Append(); } else if (num + 1 == sgs->to_signals.size()) { // last signal without phys part, put \n manually - fwriter->AppendLine(""); + fwriter->Append(""); } } - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usemon_def.c_str())); - fwriter->AppendLine(StrPrint(" _m->mon1.dlc_error = (dlc_ < %s_DLC);", sgs->msg.Name.c_str())); - fwriter->AppendLine(" _m->mon1.last_cycle = GetSystemTick();"); - fwriter->AppendLine(" _m->mon1.frame_cnt++;", 2); + fwriter->Append("#ifdef %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(" _m->mon1.dlc_error = (dlc_ < %s_DLC);", sgs->msg.Name.c_str()); + fwriter->Append(" _m->mon1.last_cycle = GetSystemTick();"); + fwriter->Append(" _m->mon1.frame_cnt++;"); + fwriter->Append(); if (sgs->msg.RollSig != nullptr) { // Put rolling monitor here - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->useroll_def.c_str())); - fwriter->AppendLine(StrPrint(" _m->mon1.roll_error = (_m->%s != _m->%s_expt);", - sgs->msg.RollSig->Name.c_str(), sgs->msg.RollSig->Name.c_str())); - fwriter->AppendLine(StrPrint(" _m->%s_expt = (_m->%s + 1) & (0x%02XU);", sgs->msg.RollSig->Name.c_str(), - sgs->msg.RollSig->Name.c_str(), (1 << sgs->msg.RollSig->LengthBit) - 1)); + fwriter->Append("#ifdef %s", fdesc->gen.useroll_def.c_str()); + fwriter->Append(" _m->mon1.roll_error = (_m->%s != _m->%s_expt);", + sgs->msg.RollSig->Name.c_str(), sgs->msg.RollSig->Name.c_str()); + fwriter->Append(" _m->%s_expt = (_m->%s + 1) & (0x%02XU);", sgs->msg.RollSig->Name.c_str(), + sgs->msg.RollSig->Name.c_str(), (1 << sgs->msg.RollSig->LengthBit) - 1); // Put rolling monitor here - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->useroll_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.useroll_def.c_str()); + fwriter->Append(); } if (sgs->msg.CsmSig != nullptr) { // Put checksum check function call here - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usecsm_def.c_str())); - fwriter->AppendLine( - StrPrint(" _m->mon1.csm_error = (((uint8_t)GetFrameHash(_d, %s_DLC, %s_CANID, %s, %d)) != (_m->%s));", - sgs->msg.Name.c_str(), sgs->msg.Name.c_str(), sgs->msg.CsmMethod.c_str(), - sgs->msg.CsmOp, sgs->msg.CsmSig->Name.c_str())); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usecsm_def.c_str()), 2); + fwriter->Append("#ifdef %s", fdesc->gen.usecsm_def.c_str()); + fwriter->Append(" _m->mon1.csm_error = (((uint8_t)GetFrameHash(_d, %s_DLC, %s_CANID, %s, %d)) != (_m->%s));", + sgs->msg.Name.c_str(), sgs->msg.Name.c_str(), sgs->msg.CsmMethod.c_str(), + sgs->msg.CsmOp, sgs->msg.CsmSig->Name.c_str()); + fwriter->Append("#endif // %s", fdesc->gen.usecsm_def.c_str()); + fwriter->Append(); } - auto Fmon_func = "FMon_" + sgs->msg.Name + "_" + fdesc->drvname; + auto Fmon_func = "FMon_" + sgs->msg.Name + "_" + fdesc->gen.drvname; - fwriter->AppendLine(StrPrint(" %s(&_m->mon1, %s_CANID);", Fmon_func.c_str(), sgs->msg.Name.c_str())); + fwriter->Append(" %s(&_m->mon1, %s_CANID);", Fmon_func.c_str(), sgs->msg.Name.c_str()); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usemon_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.usemon_def.c_str()); + fwriter->Append(); - fwriter->AppendLine(StrPrint(" return %s_CANID;", sgs->msg.Name.c_str())); + fwriter->Append(" return %s_CANID;", sgs->msg.Name.c_str()); } void CiMainGenerator::WritePackStructBody(const CiExpr_t* sgs) { - fwriter->AppendLine("{"); + fwriter->Append("{"); PrintPackCommonText("cframe->Data", sgs); - fwriter->AppendLine(StrPrint(" cframe->MsgId = %s_CANID;", sgs->msg.Name.c_str())); - fwriter->AppendLine(StrPrint(" cframe->DLC = %s_DLC;", sgs->msg.Name.c_str())); - fwriter->AppendLine(StrPrint(" cframe->IDE = %s_IDE;", sgs->msg.Name.c_str(), 2)); - fwriter->AppendLine(StrPrint(" return %s_CANID;", sgs->msg.Name.c_str())); - fwriter->AppendLine("}", 2); + fwriter->Append(" cframe->MsgId = %s_CANID;", sgs->msg.Name.c_str()); + fwriter->Append(" cframe->DLC = %s_DLC;", sgs->msg.Name.c_str()); + fwriter->Append(" cframe->IDE = %s_IDE;", sgs->msg.Name.c_str()); + fwriter->Append(" return %s_CANID;", sgs->msg.Name.c_str()); + fwriter->Append("}"); + fwriter->Append(); } void CiMainGenerator::WritePackArrayBody(const CiExpr_t* sgs) { - fwriter->AppendLine("{"); + fwriter->Append("{"); PrintPackCommonText("_d", sgs); - fwriter->AppendLine(StrPrint(" *_len = %s_DLC;", sgs->msg.Name.c_str())); - fwriter->AppendLine(StrPrint(" *_ide = %s_IDE;", sgs->msg.Name.c_str(), 2)); - fwriter->AppendLine(StrPrint(" return %s_CANID;", sgs->msg.Name.c_str())); - fwriter->AppendLine("}", 2); + fwriter->Append(" *_len = %s_DLC;", sgs->msg.Name.c_str()); + fwriter->Append(" *_ide = %s_IDE;", sgs->msg.Name.c_str()); + fwriter->Append(" return %s_CANID;", sgs->msg.Name.c_str()); + fwriter->Append("}"); + fwriter->Append(); } void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExpr_t* sgs) @@ -837,43 +775,47 @@ void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExp // which is differs only by arra var name // pring array content clearin loop - fwriter->AppendLine(StrPrint(" uint8_t i; for (i = 0; (i < %s_DLC) && (i < 8); %s[i++] = 0);", - sgs->msg.Name.c_str(), arrtxt.c_str()), 2); + fwriter->Append(" uint8_t i; for (i = 0; (i < %s_DLC) && (i < 8); %s[i++] = 0);", + sgs->msg.Name.c_str(), arrtxt.c_str()); + fwriter->Append(); if (sgs->msg.RollSig != nullptr) { - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->useroll_def.c_str())); - fwriter->AppendLine(StrPrint(" _m->%s = (_m->%s + 1) & (0x%02XU);", sgs->msg.RollSig->Name.c_str(), - sgs->msg.RollSig->Name.c_str(), (1 << sgs->msg.RollSig->LengthBit) - 1)); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->useroll_def.c_str()), 2); + fwriter->Append("#ifdef %s", fdesc->gen.useroll_def.c_str()); + fwriter->Append(" _m->%s = (_m->%s + 1) & (0x%02XU);", sgs->msg.RollSig->Name.c_str(), + sgs->msg.RollSig->Name.c_str(), (1 << sgs->msg.RollSig->LengthBit) - 1); + fwriter->Append("#endif // %s", fdesc->gen.useroll_def.c_str()); + fwriter->Append(); } if (sgs->msg.CsmSig != nullptr) { // code for clearing checksum - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usecsm_def.c_str())); - fwriter->AppendLine(StrPrint(" _m->%s = 0U;", sgs->msg.CsmSig->Name.c_str())); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usecsm_def.c_str()), 2); + fwriter->Append("#ifdef %s", fdesc->gen.usecsm_def.c_str()); + fwriter->Append(" _m->%s = 0U;", sgs->msg.CsmSig->Name.c_str()); + fwriter->Append("#endif // %s", fdesc->gen.usecsm_def.c_str()); + fwriter->Append(); } if (sgs->msg.hasPhys) { // first step is to put code for sigfloat conversion, before // sigint packing to bytes. - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usesigfloat_def.c_str())); + fwriter->Append("#ifdef %s", fdesc->gen.usesigfloat_def.c_str()); for (size_t n = 0; n < sgs->to_signals.size(); n++) { if (sgs->msg.Signals[n].IsSimpleSig == false) { // print toS from *_phys to original named sigint (integer duplicate of signal) - fwriter->AppendLine(StrPrint(" _m->%s = %s_%s_toS(_m->%s);", - sgs->msg.Signals[n].Name.c_str(), fdesc->DRVNAME.c_str(), - sgs->msg.Signals[n].Name.c_str(), sgs->msg.Signals[n].NameFloat.c_str())); + fwriter->Append(" _m->%s = %s_%s_toS(_m->%s);", + sgs->msg.Signals[n].Name.c_str(), fdesc->gen.DRVNAME.c_str(), + sgs->msg.Signals[n].Name.c_str(), sgs->msg.Signals[n].NameFloat.c_str()); } } - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usesigfloat_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.usesigfloat_def.c_str()); + fwriter->Append(); } for (size_t i = 0; i < sgs->to_bytes.size(); i++) @@ -883,23 +825,24 @@ void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExp continue; } - fwriter->AppendLine(StrPrint(" %s[%d] |= %s;", arrtxt.c_str(), i, sgs->to_bytes[i].c_str())); + fwriter->Append(" %s[%d] |= %s;", arrtxt.c_str(), i, sgs->to_bytes[i].c_str()); } - fwriter->AppendLine(""); + fwriter->Append(""); if (sgs->msg.CsmSig != nullptr) { // code for getting checksum value and putting it in array - fwriter->AppendLine(StrPrint("#ifdef %s", fdesc->usecsm_def.c_str())); + fwriter->Append("#ifdef %s", fdesc->gen.usecsm_def.c_str()); - fwriter->AppendLine(StrPrint(" _m->%s = ((uint8_t)GetFrameHash(%s, %s_DLC, %s_CANID, %s, %d));", - sgs->msg.CsmSig->Name.c_str(), arrtxt.c_str(), sgs->msg.Name.c_str(), - sgs->msg.Name.c_str(), sgs->msg.CsmMethod.c_str(), sgs->msg.CsmOp)); + fwriter->Append(" _m->%s = ((uint8_t)GetFrameHash(%s, %s_DLC, %s_CANID, %s, %d));", + sgs->msg.CsmSig->Name.c_str(), arrtxt.c_str(), sgs->msg.Name.c_str(), + sgs->msg.Name.c_str(), sgs->msg.CsmMethod.c_str(), sgs->msg.CsmOp); - fwriter->AppendLine(StrPrint(" %s[%d] |= %s;", arrtxt.c_str(), sgs->msg.CsmByteNum, sgs->msg.CsmToByteExpr.c_str())); + fwriter->Append(" %s[%d] |= %s;", arrtxt.c_str(), sgs->msg.CsmByteNum, sgs->msg.CsmToByteExpr.c_str()); - fwriter->AppendLine(StrPrint("#endif // %s", fdesc->usecsm_def.c_str()), 2); + fwriter->Append("#endif // %s", fdesc->gen.usecsm_def.c_str()); + fwriter->Append(); } } diff --git a/src/codegen/c-main-generator.h b/src/codegen/c-main-generator.h index 9d47881..c6b9406 100644 --- a/src/codegen/c-main-generator.h +++ b/src/codegen/c-main-generator.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "c-sigprinter.h" #include "filewriter.h" #include "../types/message.h" @@ -11,7 +12,7 @@ class CiMainGenerator { public: CiMainGenerator(); - void Generate(DbcMessageList_t& dlist, const FsDescriptor_t& fsd); + void Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd); private: @@ -31,13 +32,8 @@ class CiMainGenerator { void PrintPackCommonText(const std::string& arrtxt, const CiExpr_t* sgs); private: - std::vector tmpvect; - - CSigPrinter* sigprt; - - FileWriter* fwriter; - - const FsDescriptor_t* fdesc; - + std::unique_ptr sigprt; + std::unique_ptr fwriter; + const AppSettings_t* fdesc; const DbcMessageList_t* p_dlist; }; diff --git a/src/codegen/c-sigprinter.cpp b/src/codegen/c-sigprinter.cpp index 4e44a29..82cda5c 100644 --- a/src/codegen/c-sigprinter.cpp +++ b/src/codegen/c-sigprinter.cpp @@ -1,4 +1,5 @@ #include +#include #include "c-sigprinter.h" #include "helpers/formatter.h" @@ -28,9 +29,9 @@ void CSigPrinter::LoadMessages(const std::vector message) { sigs_expr.clear(); - for (size_t i = 0; i < message.size(); i++) + for (auto it = message.cbegin(); it != message.cend(); ++it) { - LoadMessage(*(message[i])); + LoadMessage(*(*it)); } } diff --git a/src/codegen/c-util-generator.cpp b/src/codegen/c-util-generator.cpp index 0e20bab..7ff459f 100644 --- a/src/codegen/c-util-generator.cpp +++ b/src/codegen/c-util-generator.cpp @@ -14,8 +14,8 @@ static const std::string closeguard = "#ifdef __cplusplus\n\ CiUtilGenerator::CiUtilGenerator() { Clear(); - tof = new FileWriter; - condtree = new ConditionalTree; + tof = std::make_unique(); + condtree = std::make_unique(); } void CiUtilGenerator::Clear() @@ -27,7 +27,7 @@ void CiUtilGenerator::Clear() } -void CiUtilGenerator::Generate(DbcMessageList_t& dlist, const FsDescriptor_t& fsd, +void CiUtilGenerator::Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd, const MsgsClassification& groups, const std::string& drvname) { Clear(); @@ -84,7 +84,8 @@ void CiUtilGenerator::Generate(DbcMessageList_t& dlist, const FsDescriptor_t& fs return a->MsgID < b->MsgID; }); - fdesc = &fsd; + fdesc = &fsd.file; + gdesc = &fsd.gen; // print header for util code PrintHeader(); @@ -97,119 +98,138 @@ void CiUtilGenerator::PrintHeader() { tof->Flush(); - if (fdesc->start_info.size() > 0) + if (gdesc->start_info.size() > 0) { - tof->AppendLine("// " + std::regex_replace(fdesc->start_info, std::regex("\n"), "\n// ")); + tof->Append("// " + std::regex_replace(gdesc->start_info, std::regex("\n"), "\n// ")); } - tof->AppendLine("#pragma once", 2); + tof->Append("#pragma once"); + tof->Append(); - tof->AppendLine(openguard.c_str(), 2); + tof->Append(openguard); + tof->Append(); // include common dbc code config header - tof->AppendLine("#include ", 2); + tof->Append("#include "); + tof->Append(); // include c-main driver header - tof->AppendLine(StrPrint("#include <%s.h>", file_drvname.c_str()), 2); + tof->Append("#include <%s.h>", file_drvname.c_str()); + tof->Append(); if (rx.size() == 0) { - tof->AppendLine("// There is no any RX mapped massage.", 2); + tof->Append("// There is no any RX mapped massage."); + tof->Append(); } else { // print the typedef - tof->AppendLine("typedef struct\n{"); + tof->Append("typedef struct\n{"); for (auto m : rx) { - tof->AppendLine(StrPrint(" %s_t %s;", m->Name.c_str(), m->Name.c_str())); + tof->Append(" %s_t %s;", m->Name.c_str(), m->Name.c_str()); } - tof->AppendLine(StrPrint("} %s_rx_t;", fdesc->drvname.c_str()), 2); + tof->Append("} %s_rx_t;", gdesc->drvname.c_str()); + tof->Append(); } if (tx.size() == 0) { - tof->AppendLine("// There is no any TX mapped massage.", 2); + tof->Append("// There is no any TX mapped massage."); + tof->Append(); } else { // print the typedef - tof->AppendLine("typedef struct\n{"); + tof->Append("typedef struct\n{"); for (auto m : tx) { - tof->AppendLine(StrPrint(" %s_t %s;", m->Name.c_str(), m->Name.c_str())); + tof->Append(" %s_t %s;", m->Name.c_str(), m->Name.c_str()); } - tof->AppendLine(StrPrint("} %s_tx_t;", fdesc->drvname.c_str()), 2); + tof->Append("} %s_tx_t;", gdesc->drvname.c_str()); + tof->Append(); } if (rx.size() > 0) { // receive function necessary only when more than 0 rx messages were mapped - tof->AppendLine(StrPrint("uint32_t %s_Receive(%s_rx_t* m, const uint8_t* d, uint32_t msgid, uint8_t dlc);", - fdesc->drvname.c_str(), fdesc->drvname.c_str()), 2); + tof->Append("uint32_t %s_Receive(%s_rx_t* m, const uint8_t* d, uint32_t msgid, uint8_t dlc);", + gdesc->drvname.c_str(), gdesc->drvname.c_str()); + tof->Append(); } // print extern for super structs if (rx.size() > 0 || tx.size() > 0) { - tof->AppendLine(StrPrint("#ifdef __DEF_%s__", fdesc->DRVNAME.c_str()), 2); + tof->Append("#ifdef __DEF_%s__", gdesc->DRVNAME.c_str()); + tof->Append(); if (rx.size() > 0) { - tof->AppendLine(StrPrint("extern %s_rx_t %s_rx;", fdesc->drvname.c_str(), fdesc->drvname.c_str()), 2); + tof->Append("extern %s_rx_t %s_rx;", gdesc->drvname.c_str(), gdesc->drvname.c_str()); + tof->Append(); } if (tx.size() > 0) { - tof->AppendLine(StrPrint("extern %s_tx_t %s_tx;", fdesc->drvname.c_str(), fdesc->drvname.c_str()), 2); + tof->Append("extern %s_tx_t %s_tx;", gdesc->drvname.c_str(), gdesc->drvname.c_str()); + tof->Append(); } - tof->AppendLine(StrPrint("#endif // __DEF_%s__", fdesc->DRVNAME.c_str()), 2); + tof->Append("#endif // __DEF_%s__", gdesc->DRVNAME.c_str()); + tof->Append(); } - tof->AppendLine(closeguard.c_str()); + tof->Append(closeguard); tof->Flush(fdesc->util_h.fpath); } void CiUtilGenerator::PrintSource() { - if (fdesc->start_info.size() > 0) + if (gdesc->start_info.size() > 0) { - tof->AppendLine("// " + std::regex_replace(fdesc->start_info, std::regex("\n"), "\n// ")); + tof->Append("// " + std::regex_replace(gdesc->start_info, std::regex("\n"), "\n// ")); } - tof->AppendLine(StrPrint("#include \"%s\"", fdesc->util_h.fname.c_str()), 2); + tof->Append("#include \"%s\"", fdesc->util_h.fname.c_str()); + tof->Append(); - tof->AppendLine("// DBC file version"); - tof->AppendLine(StrPrint("#if (%s != (%uU)) || (%s != (%uU))", - fdesc->verhigh_def.c_str(), p_dlist->ver.hi, fdesc->verlow_def.c_str(), p_dlist->ver.low)); + tof->Append("// DBC file version"); + tof->Append("#if (%s != (%uU)) || (%s != (%uU))", + gdesc->verhigh_def.c_str(), p_dlist->ver.hi, gdesc->verlow_def.c_str(), p_dlist->ver.low); - tof->AppendLine(StrPrint("#error The %s binutil source file has inconsistency with core dbc lib!", - fdesc->DRVNAME.c_str())); - tof->AppendLine("#endif", 2); + tof->Append("#error The %s binutil source file has inconsistency with core dbc lib!", + gdesc->DRVNAME.c_str()); + tof->Append("#endif"); + tof->Append(); // optional RX and TX struct allocations if (rx.size() > 0 || tx.size() > 0) { - tof->AppendLine(StrPrint("#ifdef __DEF_%s__", fdesc->DRVNAME.c_str()), 2); + tof->Append("#ifdef __DEF_%s__", gdesc->DRVNAME.c_str()); + tof->Append(); if (rx.size() > 0) { - tof->AppendLine(StrPrint("%s_rx_t %s_rx;", fdesc->drvname.c_str(), fdesc->drvname.c_str()), 2); + tof->Append("%s_rx_t %s_rx;", gdesc->drvname.c_str(), gdesc->drvname.c_str()); + tof->Append(); } if (tx.size() > 0) { - tof->AppendLine(StrPrint("%s_tx_t %s_tx;", fdesc->drvname.c_str(), fdesc->drvname.c_str()), 2); + tof->Append("%s_tx_t %s_tx;", gdesc->drvname.c_str(), gdesc->drvname.c_str()); + tof->Append(); } - tof->AppendLine(StrPrint("#endif // __DEF_%s__", fdesc->DRVNAME.c_str()), 2); + tof->Append("#endif // __DEF_%s__", gdesc->DRVNAME.c_str()); + tof->Append(); } if (rx.size() > 0) @@ -220,19 +240,20 @@ void CiUtilGenerator::PrintSource() // binary search on FrameID for selecting unpacking function auto tree = FillTreeLevel(rx, 0, static_cast(rx.size())); - tof->AppendLine(StrPrint("uint32_t %s_Receive(%s_rx_t* _m, const uint8_t* _d, uint32_t _id, uint8_t dlc_)", - fdesc->drvname.c_str(), fdesc->drvname.c_str())); + tof->Append("uint32_t %s_Receive(%s_rx_t* _m, const uint8_t* _d, uint32_t _id, uint8_t dlc_)", + gdesc->drvname.c_str(), gdesc->drvname.c_str()); - tof->AppendLine("{"); - tof->AppendLine(" uint32_t recid = 0;"); + tof->Append("{"); + tof->Append(" uint32_t recid = 0;"); // put tree-view struct on code (in treestr variable) std::string treestr; condtree->Clear(); - tof->AppendLine(condtree->WriteCode(tree, treestr, 1)); - - tof->AppendLine(" return recid;"); - tof->AppendLine("}", 2); + tof->Append(condtree->WriteCode(tree, treestr, 1)); + tof->Append(); + tof->Append(" return recid;"); + tof->Append("}"); + tof->Append(); // clear tree after using condtree->DeleteTree(tree); diff --git a/src/codegen/c-util-generator.h b/src/codegen/c-util-generator.h index 07b10f9..15156ce 100644 --- a/src/codegen/c-util-generator.h +++ b/src/codegen/c-util-generator.h @@ -1,5 +1,6 @@ #pragma once +#include #include "types/message.h" #include "fs-creator.h" #include "filewriter.h" @@ -20,7 +21,7 @@ class CiUtilGenerator { // - function to Unpack incoming frame to dedicated RX message struct field // - optional (through define in global "dbccodeconf.h") variable allocation in source files // - void Generate(DbcMessageList_t& dlist, const FsDescriptor_t& fsd, + void Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd, const MsgsClassification& groups, const std::string& drvname); private: @@ -36,13 +37,14 @@ class CiUtilGenerator { std::vector both; // to file writer - FileWriter* tof; + std::unique_ptr tof; + std::unique_ptr condtree; std::string code_drvname; std::string file_drvname; const FsDescriptor_t* fdesc; - ConditionalTree* condtree; + const GenDescriptor_t* gdesc; const DbcMessageList_t* p_dlist; bool treestarted; diff --git a/src/codegen/config-generator.cpp b/src/codegen/config-generator.cpp new file mode 100644 index 0000000..015fb9a --- /dev/null +++ b/src/codegen/config-generator.cpp @@ -0,0 +1,133 @@ +#include "config-generator.h" + +void ConfigGenerator::FillHeader(FileWriter& wr, const GenDescriptor_t& gsett) +{ + wr.Append("#pragma once"); + wr.Append(""); + wr.Append("/* include common dbccode configurations */"); + wr.Append("#include "); + wr.Append(""); + wr.Append(""); + wr.Append("/* ------------------------------------------------------------------------- *"); + wr.Append(" This define enables using CAN message structs with bit-fielded signals"); + wr.Append(" layout."); + wr.Append(""); + wr.Append(" Note(!): bit-feild was not tested properly. */"); + wr.Append(""); + wr.Append("/* #define %s */", gsett.usebits_def.c_str()); + wr.Append(2); + + wr.Append("/* ------------------------------------------------------------------------- *"); + wr.Append(" This macro enables using CAN message descriptive struct packing functions"); + wr.Append(" (by default signature of pack function intakes a few simple typed params"); + wr.Append(" for loading data, len, etc). To compile you need to define the struct"); + wr.Append(" __CoderDbcCanFrame_t__ which must have fields:"); + wr.Append(""); + wr.Append(" u32 MsgId (CAN Frame message ID)"); + wr.Append(" u8 DLC (CAN Frame payload length field)"); + wr.Append(" u8 Data[8] (CAN Frame payload data)"); + wr.Append(" u8 IDE (CAN Frame Extended (1) / Standard (0) ID type)"); + wr.Append(""); + wr.Append(" This struct definition have to be placed (or be included) in dbccodeconf.h */"); + wr.Append(""); + wr.Append("/* #define %s */", gsett.usesruct_def.c_str()); + wr.Append(2); + + wr.Append("/* ------------------------------------------------------------------------- *"); + wr.Append(" All the signals which have values of factor != 1 or offset != 0"); + wr.Append(" will be named in message struct with posfix '_ro'. Pack to payload"); + wr.Append(" operations will be made on this signal value as well as unpack from payload."); + wr.Append(""); + wr.Append(" USE_SIGFLOAT macro makes some difference:"); + wr.Append(""); + wr.Append(" 1. All the '_ro' fields will have a pair field with '_phys' postfix."); + wr.Append(" If only offset != 0 is true then the type of '_phys' signal is the same"); + wr.Append(" as '_ro' signal. In other case the type will be @sigfloat_t which"); + wr.Append(" have to be defined in user dbccodeconf.h"); + wr.Append(""); + wr.Append(" 2. In pack function '_ro' signal will be rewritten by '_phys' signal, which"); + wr.Append(" requires from user to use ONLY '_phys' signal for packing frame"); + wr.Append(""); + wr.Append(" 3. In unpack function '_phys' signal will be written by '_ro' signal."); + wr.Append(" User have to use '_phys' signal to read physical value. */"); + wr.Append(""); + wr.Append("/* #define %s */", gsett.usesigfloat_def.c_str()); + wr.Append(2); + + wr.Append("/* ------------------------------------------------------------------------- *"); + wr.Append(" Note(!) that the \"canmonitorutil.h\" must be accessed in include path:"); + wr.Append(""); + wr.Append(" This macro adds:"); + wr.Append(""); + wr.Append(" - monitor field @mon1 to message struct"); + wr.Append(""); + wr.Append(" - capture system tick in unpack function and save value to mon1 field"); + wr.Append(" to provide to user better missing frame detection code. For this case"); + wr.Append(" user must provide function declared in canmonitorutil.h - GetSysTick()"); + wr.Append(" which may return 1ms uptime."); + wr.Append(""); + wr.Append(" - calling function FMon_*** (from 'fmon' driver) inside unpack function"); + wr.Append(" which is empty by default and have to be filled by user if"); + wr.Append(" tests for DLC, rolling, checksum are necessary */"); + wr.Append(""); + wr.Append("/* #define %s */", gsett.usemon_def.c_str()); + wr.Append(2); + + wr.Append("/* ------------------------------------------------------------------------- *"); + wr.Append(" When monitor using is enabled (%s) and define below", gsett.usemon_def.c_str()); + wr.Append(" uncommented, additional signal will be added to message struct. ***_expt:"); + wr.Append(" expected rolling counter, to perform monitoring rolling counter sequence"); + wr.Append(" automatically (result may be tested in dedicated Fmon_*** function) */"); + wr.Append(""); + wr.Append("/* #define %s */", gsett.useroll_def.c_str()); + wr.Append(2); + + wr.Append("/* ------------------------------------------------------------------------- *"); + wr.Append(" When monitor using is enabled (%s) and define below", gsett.usemon_def.c_str()); + wr.Append(" uncommented, frame checksum signal may be handled automatically."); + wr.Append(""); + wr.Append(" The signal which may be marked as checksum signal must have substring"); + wr.Append(" with next format:"); + wr.Append(" "); + wr.Append(""); + wr.Append(" where:"); + wr.Append(""); + wr.Append(" - \"Checksum\": constant marker word"); + wr.Append(""); + wr.Append(" - \"XOR8\": type of method, this text will be passed to GetFrameHash"); + wr.Append(" (canmonitorutil.h) function as is, the best use case is to define 'enum"); + wr.Append(" DbcCanCrcMethods' in canmonitorutil.h file with all possible"); + wr.Append(" checksum algorithms (e.g. XOR8, XOR4 etc)"); + wr.Append(""); + wr.Append(" - \"3\": optional value that will be passed to GetFrameHash as integer value"); + wr.Append(""); + wr.Append(" Function GetFrameHash have to be implemented by user"); + wr.Append(""); + wr.Append(" In pack function checksum signal will be calculated automatically"); + wr.Append(" and loaded to payload"); + wr.Append(""); + wr.Append(" In unpack function checksum signal is checked with calculated."); + wr.Append(" (result may be tested in dedicated Fmon_*** function). */"); + wr.Append(""); + wr.Append("/* #define %s */", gsett.usecsm_def.c_str()); + wr.Append(2); + wr.Append("/* ------------------------------------------------------------------------- *"); + wr.Append(" FMon handling model can be build in two ways: "); + wr.Append(""); + wr.Append(" 1 - Default. In this case when specific frame unpack is called the "); + wr.Append(" specific FMon_{Frame name}_{driver name} functoin will be called."); + wr.Append(" User's code scope has to define each of these functions. Each function is"); + wr.Append(" responsible for the error handling of one frame"); + wr.Append(""); + wr.Append(" 2 - MONO. In this case there is only one function to perform any frame "); + wr.Append(" monitoring. This function has to be implemented in the user's code scope."); + wr.Append(" This function is named as FMon_MONO_{driver name}. It takes frame id"); + wr.Append(" which can be used for selection of the logic for a frame monitoring."); + wr.Append(" This mode costs a bit more in runtime but when you often edit you DBC and you "); + wr.Append(" have more than one project it could be more maintanable (there is"); + wr.Append(" no necessity to replace source code)"); + wr.Append(""); + wr.Append(" For using MONO way uncomment line below */"); + wr.Append("/* #define %s */", gsett.usemonofmon_def.c_str()); + +} diff --git a/src/codegen/config-generator.h b/src/codegen/config-generator.h new file mode 100644 index 0000000..e78ba81 --- /dev/null +++ b/src/codegen/config-generator.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include "filewriter.h" +#include "c-sigprinter.h" +#include "fs-creator.h" + +class ConfigGenerator { + public: + void FillHeader(FileWriter& wr, const GenDescriptor_t& gsett); +}; diff --git a/src/codegen/filewriter.cpp b/src/codegen/filewriter.cpp index bb43904..5ceef2b 100644 --- a/src/codegen/filewriter.cpp +++ b/src/codegen/filewriter.cpp @@ -1,14 +1,20 @@ #include #include +#include +#include +#include #include "filewriter.h" - -FileWriter::FileWriter() +template +std::string __print_loc__(const char* format, va_list args) { -} + // TODO: make N sanitizing here to prevent memory errors + char work_buff[N] = {0}; + auto ret = vsnprintf(work_buff, N, format, args); -FileWriter::~FileWriter() -{ + assert(ret < N); + // make string from local array + return work_buff; } void FileWriter::Flush() @@ -19,41 +25,54 @@ void FileWriter::Flush() void FileWriter::Flush(const std::string& fpath) { std::ofstream wfile; - wfile.open(fpath, std::ios::out); - wfile << strm.rdbuf(); - wfile.close(); - Flush(); } -void FileWriter::AppendText(const char* text) +void FileWriter::Append(const char* frmt, ...) { - std::string str = text; - AppendText(str); + va_list args; + va_start(args, frmt); + auto ret = __print_loc__(frmt, args); + va_end(args); + Append(ret); } -void FileWriter::AppendLine(const char* text, int32_t post_empty_lines) +void FileWriter::AppendText(const char* frmt, ...) { - AppendText(text); - - for (int32_t i = 0; i < post_empty_lines; i++) - { - AppendText("\n"); - } + va_list args; + va_start(args, frmt); + auto ret = __print_loc__(frmt, args); + va_end(args); + AppendText(ret); } - void FileWriter::AppendText(const std::string& str) { strm << str; } -void FileWriter::AppendLine(const std::string& str) +void FileWriter::Append(const std::string& str) { AppendText(str); - AppendText("\n"); + NewLine(str.back()); +} + +void FileWriter::Append(size_t empty_lines) +{ + for (auto i = empty_lines; i != 0; --i) + { + NewLine(); + } +} + +void FileWriter::NewLine(const char c) +{ + if (c != '\n') + { + strm << '\n'; + } } diff --git a/src/codegen/filewriter.h b/src/codegen/filewriter.h index 080a537..90ab3b0 100644 --- a/src/codegen/filewriter.h +++ b/src/codegen/filewriter.h @@ -8,21 +8,21 @@ class FileWriter { public: - FileWriter(); - ~FileWriter(); - void Flush(); void Flush(const std::string& filename); - void AppendText(const char* text); - void AppendLine(const char* text, int32_t post_empty_lines = 1); + void Append(const char* frmt, ...); + void Append(const std::string& str); + void AppendText(const char* frmt, ...); void AppendText(const std::string& str); - void AppendLine(const std::string& str); + void Append(size_t empty_lines = 1); private: + void NewLine(const char c = ' '); + std::stringstream strm; }; diff --git a/src/codegen/fs-creator.cpp b/src/codegen/fs-creator.cpp index 04eb5d4..b22c754 100644 --- a/src/codegen/fs-creator.cpp +++ b/src/codegen/fs-creator.cpp @@ -73,37 +73,37 @@ bool FsCreator::PrepareDirectory(std::string drvname, std::string basepath, bool } } - FS.libdir = work_dir_path + kLibDir; + FS.file.libdir = work_dir_path + kLibDir; - if (std::filesystem::create_directory(FS.libdir)) + if (std::filesystem::create_directory(FS.file.libdir)) { // ret = false; } - FS.usrdir = work_dir_path + kUsrDir; + FS.file.usrdir = work_dir_path + kUsrDir; - if (std::filesystem::create_directory(FS.usrdir)) + if (std::filesystem::create_directory(FS.file.usrdir)) { // ret = false; } - FS.incdir = work_dir_path + kIncDir; + FS.file.incdir = work_dir_path + kIncDir; - if (std::filesystem::create_directory(FS.incdir)) + if (std::filesystem::create_directory(FS.file.incdir)) { // ret = false; } - FS.confdir = work_dir_path + kConfDir; + FS.file.confdir = work_dir_path + kConfDir; - if (std::filesystem::create_directory(FS.confdir)) + if (std::filesystem::create_directory(FS.file.confdir)) { // ret = false; } - FS.utildir = work_dir_path + kUtilDir; + FS.file.utildir = work_dir_path + kUtilDir; - if (std::filesystem::create_directory(FS.utildir)) + if (std::filesystem::create_directory(FS.file.utildir)) { // ret = false; } @@ -111,64 +111,67 @@ bool FsCreator::PrepareDirectory(std::string drvname, std::string basepath, bool if (true) { // directory valid and exists, set all the values - FS.DrvName_orig = drvname; - FS.DRVNAME = str_toupper(drvname); - FS.drvname = str_tolower(drvname); + FS.gen.DrvName_orig = drvname; + FS.gen.DRVNAME = str_toupper(drvname); + FS.gen.drvname = str_tolower(drvname); - FS.core_h.dir = work_dir_path; - FS.core_h.fname = FS.drvname + ".h"; - FS.core_h.fpath = FS.libdir + "/" + FS.core_h.fname; + FS.file.core_h.dir = work_dir_path; + FS.file.core_h.fname = FS.gen.drvname + ".h"; + FS.file.core_h.fpath = FS.file.libdir + "/" + FS.file.core_h.fname; - FS.core_c.dir = work_dir_path; - FS.core_c.fname = FS.drvname + ".c"; - FS.core_c.fpath = FS.libdir + "/" + FS.core_c.fname; + FS.file.core_c.dir = work_dir_path; + FS.file.core_c.fname = FS.gen.drvname + ".c"; + FS.file.core_c.fpath = FS.file.libdir + "/" + FS.file.core_c.fname; - FS.util_h.dir = work_dir_path; - FS.util_h.fname = FS.drvname + "-binutil" + ".h"; - FS.util_h.fpath = FS.utildir + "/" + FS.util_h.fname; + FS.file.util_h.dir = work_dir_path; + FS.file.util_h.fname = FS.gen.drvname + "-binutil" + ".h"; + FS.file.util_h.fpath = FS.file.utildir + "/" + FS.file.util_h.fname; - FS.util_c.dir = work_dir_path; - FS.util_c.fname = FS.drvname + "-binutil" + ".c"; - FS.util_c.fpath = FS.utildir + "/" + FS.util_c.fname; + FS.file.util_c.dir = work_dir_path; + FS.file.util_c.fname = FS.gen.drvname + "-binutil" + ".c"; + FS.file.util_c.fpath = FS.file.utildir + "/" + FS.file.util_c.fname; - FS.fmon_h.dir = work_dir_path; - FS.fmon_h.fname = FS.drvname + "-fmon.h"; - FS.fmon_h.fpath = FS.libdir + "/" + FS.fmon_h.fname; + FS.file.fmon_h.dir = work_dir_path; + FS.file.fmon_h.fname = FS.gen.drvname + "-fmon.h"; + FS.file.fmon_h.fpath = FS.file.libdir + "/" + FS.file.fmon_h.fname; - FS.fmon_c.dir = work_dir_path; - FS.fmon_c.fname = FS.drvname + "-fmon.c"; - FS.fmon_c.fpath = FS.usrdir + "/" + FS.fmon_c.fname; + FS.file.fmon_c.dir = work_dir_path; + FS.file.fmon_c.fname = FS.gen.drvname + "-fmon.c"; + FS.file.fmon_c.fpath = FS.file.usrdir + "/" + FS.file.fmon_c.fname; - snprintf(_tmpb, kTmpLen, "%s_USE_BITS_SIGNAL", FS.DRVNAME.c_str()); - FS.usebits_def = _tmpb; + snprintf(_tmpb, kTmpLen, "%s_USE_BITS_SIGNAL", FS.gen.DRVNAME.c_str()); + FS.gen.usebits_def = _tmpb; - snprintf(_tmpb, kTmpLen, "%s_USE_DIAG_MONITORS", FS.DRVNAME.c_str()); - FS.usemon_def = _tmpb; + snprintf(_tmpb, kTmpLen, "%s_USE_DIAG_MONITORS", FS.gen.DRVNAME.c_str()); + FS.gen.usemon_def = _tmpb; - snprintf(_tmpb, kTmpLen, "%s_USE_SIGFLOAT", FS.DRVNAME.c_str()); - FS.usesigfloat_def = _tmpb; + snprintf(_tmpb, kTmpLen, "%s_USE_MONO_FMON", FS.gen.DRVNAME.c_str()); + FS.gen.usemonofmon_def = _tmpb; - snprintf(_tmpb, kTmpLen, "%s_USE_CANSTRUCT", FS.DRVNAME.c_str()); - FS.usesruct_def = _tmpb; + snprintf(_tmpb, kTmpLen, "%s_USE_SIGFLOAT", FS.gen.DRVNAME.c_str()); + FS.gen.usesigfloat_def = _tmpb; - snprintf(_tmpb, kTmpLen, "%s_AUTO_ROLL", FS.DRVNAME.c_str()); - FS.useroll_def = _tmpb; + snprintf(_tmpb, kTmpLen, "%s_USE_CANSTRUCT", FS.gen.DRVNAME.c_str()); + FS.gen.usesruct_def = _tmpb; - snprintf(_tmpb, kTmpLen, "%s_AUTO_CSM", FS.DRVNAME.c_str()); - FS.usecsm_def = _tmpb; + snprintf(_tmpb, kTmpLen, "%s_AUTO_ROLL", FS.gen.DRVNAME.c_str()); + FS.gen.useroll_def = _tmpb; - snprintf(_tmpb, kTmpLen, "VER_%s_MAJ", FS.DRVNAME.c_str()); - FS.verhigh_def = _tmpb; + snprintf(_tmpb, kTmpLen, "%s_AUTO_CSM", FS.gen.DRVNAME.c_str()); + FS.gen.usecsm_def = _tmpb; - snprintf(_tmpb, kTmpLen, "VER_%s_MIN", FS.DRVNAME.c_str()); - FS.verlow_def = _tmpb; + snprintf(_tmpb, kTmpLen, "VER_%s_MAJ", FS.gen.DRVNAME.c_str()); + FS.gen.verhigh_def = _tmpb; + + snprintf(_tmpb, kTmpLen, "VER_%s_MIN", FS.gen.DRVNAME.c_str()); + FS.gen.verlow_def = _tmpb; // load start info to fdescriptor - FS.start_info.clear(); + FS.gen.start_info.clear(); if (strinfo.size() > 0) { - FS.start_info = strinfo; + FS.gen.start_info = strinfo; } } diff --git a/src/codegen/fs-creator.h b/src/codegen/fs-creator.h index d470ae4..6fa0e5b 100644 --- a/src/codegen/fs-creator.h +++ b/src/codegen/fs-creator.h @@ -6,13 +6,6 @@ typedef struct { - // original driver name view - std::string DrvName_orig; - // low case driver name - std::string drvname; - // up case driver name - std::string DRVNAME; - std::string libdir; std::string usrdir; std::string incdir; @@ -27,10 +20,21 @@ typedef struct OutFileDescriptor_t fmon_h; OutFileDescriptor_t fmon_c; +} FsDescriptor_t; + +typedef struct +{ + // original driver name view + std::string DrvName_orig; + // low case driver name + std::string drvname; + // up case driver name + std::string DRVNAME; std::string usebits_def; std::string usesruct_def; std::string usemon_def; + std::string usemonofmon_def; std::string usesigfloat_def; std::string useroll_def; std::string usecsm_def; @@ -41,8 +45,13 @@ typedef struct // inforamtion to be placed at the start of each source file std::string start_info; +} GenDescriptor_t; -} FsDescriptor_t; +typedef struct +{ + FsDescriptor_t file; + GenDescriptor_t gen; +} AppSettings_t; // This class is used to build all neccessary string -ed // value that will be required during code generation @@ -57,7 +66,7 @@ class FsCreator { std::string CreateSubDir(std::string basepath, std::string subdir, bool rm = true); - FsDescriptor_t FS; + AppSettings_t FS; }; diff --git a/src/codegen/mon-generator.cpp b/src/codegen/mon-generator.cpp new file mode 100644 index 0000000..7ba4b3c --- /dev/null +++ b/src/codegen/mon-generator.cpp @@ -0,0 +1,75 @@ +#include "mon-generator.h" +#include "helpers/formatter.h" + +uint32_t MonGenerator::FillHeader(FileWriter& wr, std::vector& sigs, + const GenDescriptor_t& gsett) +{ + wr.Append("#ifdef %s_USE_MONO_FMON", gsett.DRVNAME.c_str()); + wr.Append(); + + wr.Append("void _FMon_MONO_%s(FrameMonitor_t* _mon, uint32_t msgid);", gsett.drvname.c_str()); + wr.Append(); + + for (auto it = sigs.begin(); it != sigs.end(); ++it) + { + + auto msg = &((*it)->msg); + wr.Append("#define FMon_%s_%s(x, y) _FMon_MONO_%s((x), (y))", msg->Name.c_str(), + gsett.drvname.c_str(), + gsett.drvname.c_str()); + } + + wr.Append(); + wr.Append("#else"); + wr.Append(); + + for (auto it = sigs.begin(); it != sigs.end(); ++it) + { + auto msg = &((*it)->msg); + wr.Append("void _FMon_%s_%s(FrameMonitor_t* _mon, uint32_t msgid);", + msg->Name.c_str(), gsett.drvname.c_str()); + } + + wr.Append(); + + for (auto it = sigs.begin(); it != sigs.end(); ++it) + { + auto msg = &((*it)->msg); + wr.Append("#define FMon_%s_%s(x, y) _FMon_%s_%s((x), (y))", + msg->Name.c_str(), gsett.drvname.c_str(), + msg->Name.c_str(), gsett.drvname.c_str()); + } + + wr.Append(); + wr.Append("#endif"); + wr.Append(); + + return 0; +} + +uint32_t MonGenerator::FillSource(FileWriter& wr, std::vector& sigs, + const GenDescriptor_t& gsett) +{ + wr.Append("#ifdef %s_USE_MONO_FMON", gsett.DRVNAME.c_str()); + wr.Append(); + wr.Append("void _FMon_MONO_%s(FrameMonitor_t* _mon, uint32_t msgid)", gsett.drvname.c_str()); + wr.Append("{"); + wr.Append(" (void)_mon;"); + wr.Append(" (void)msgid;"); + wr.Append("}"); + wr.Append(); + wr.Append("#else"); + wr.Append(); + + for (auto it = sigs.begin(); it != sigs.end(); ++it) + { + auto msg = &((*it)->msg); + wr.Append("void _FMon_%s_%s(FrameMonitor_t* _mon, uint32_t msgid)\n{\n (void)_mon;\n (void)msgid;\n}\n\n", + msg->Name.c_str(), gsett.drvname.c_str()); + } + + wr.Append("#endif // %s_USE_MONO_FMON", gsett.DRVNAME.c_str()); + wr.Append(); + + return 0; +} diff --git a/src/codegen/mon-generator.h b/src/codegen/mon-generator.h new file mode 100644 index 0000000..004a77e --- /dev/null +++ b/src/codegen/mon-generator.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include "filewriter.h" +#include "c-sigprinter.h" +#include "fs-creator.h" + +class MonGenerator { + public: + + MonGenerator() = default; + + uint32_t FillHeader(FileWriter& wr, std::vector& sigs, const GenDescriptor_t& gsett); + uint32_t FillSource(FileWriter& wr, std::vector& sigs, const GenDescriptor_t& gsett); +}; diff --git a/src/codegen/version.h b/src/codegen/version.h index aea8d00..b5b6298 100644 --- a/src/codegen/version.h +++ b/src/codegen/version.h @@ -3,4 +3,4 @@ #include #define CODEGEN_LIB_VERSION_MAJ (2) -#define CODEGEN_LIB_VERSION_MIN (2) +#define CODEGEN_LIB_VERSION_MIN (3) diff --git a/src/helpers/formatter.h b/src/helpers/formatter.h index d9f5599..333fa69 100644 --- a/src/helpers/formatter.h +++ b/src/helpers/formatter.h @@ -24,3 +24,20 @@ std::string str_trim(std::string s); * @return std::string */ std::string make_c_name(const std::string& s); + +template +std::string StrPrintLoc(const char* format, ...) +{ + va_list args; + va_start(args, format); + + // TODO: make N sanitizing here to prevent memory errors + char work_buff[N] = {0}; + + vsnprintf(work_buff, N, format, args); + + va_end(args); + + // make string from local array + return work_buff; +} diff --git a/src/maincli.cpp b/src/maincli.cpp index 4d8c5c2..3226a2c 100644 --- a/src/maincli.cpp +++ b/src/maincli.cpp @@ -1,45 +1,13 @@ -#include -#include -#include -#include #include -#include -#include "parser/dbcscanner.h" -#include "codegen/c-main-generator.h" -#include "codegen/c-util-generator.h" -#include "codegen/fs-creator.h" -#include "codegen/version.h" +#include +#include "app.h" -#define GEN_UTIL_CODE - -#define MIN_ARGC_NUM 4 -#define MAX_ARGC_NUM 5 - -char verstr[128] = {0}; - -DbcScanner* scanner; -CiMainGenerator* cigen; -CiUtilGenerator* ciugen; -FsCreator* fscreator; - -std::string source_files_out_path; -std::string dbc_file_path; -std::string dbc_driver_name; - -typedef struct -{ - std::string arg; - std::string param; -} ParamPair_t; - -void PrintUsage(); - -std::vector getoptions(int argc, char** argv) +std::vector> getoptions(int argc, char** argv) { - std::vector ret; + std::vector> ret{}; - ParamPair_t pair; + std::pair pair{}; if (argc <= 0) { @@ -51,13 +19,13 @@ std::vector getoptions(int argc, char** argv) // key found (must start with '-' (e.g. '-dbc')) if (argv[i][0] == '-') { - pair.arg = std::string(argv[i]); - pair.param.clear(); + pair.first = std::string(argv[i]); + pair.second.clear(); - if (i + 1 < argc && argv[i + 1][0] != '-') + if ((i + 1) < argc && argv[i + 1][0] != '-') { // key param - pair.param = std::string(argv[i + 1]); + pair.second = std::string(argv[i + 1]); // unlooped i incremention ++i; } @@ -71,239 +39,7 @@ std::vector getoptions(int argc, char** argv) int main(int argc, char* argv[]) { - bool err = false; - bool dbc_ok = false; - bool path_ok = false; - bool drvname_ok = false; - bool rewrite_src = false; - bool gen_nodeutils = false; - bool help = false; - - std::vector opts = getoptions(argc, argv); - - for (size_t i = 0; i < opts.size(); i++) - { - if (opts[i].arg == "-dbc") - { - dbc_file_path = opts[i].param; - dbc_ok = true; - } - else if (opts[i].arg == "-out") - { - source_files_out_path = opts[i].param; - path_ok = true; - } - else if (opts[i].arg == "-drvname") - { - dbc_driver_name = opts[i].param; - drvname_ok = true; - } - else if (opts[i].arg == "-rw") - { - rewrite_src = true; - } - else if (opts[i].arg == "-nodeutils") - { - gen_nodeutils = true; - } - else if (opts[i].arg == "-help") - { - help = true; - } - } - - if (help) - { - PrintUsage(); - return 0; - } - - if (drvname_ok) - { - dbc_driver_name = make_c_name(dbc_driver_name); - - if (dbc_driver_name.length() == 0) - { - drvname_ok = false; - } - } - - if (drvname_ok && path_ok && dbc_ok) - { - - scanner = new DbcScanner; - cigen = new CiMainGenerator; - ciugen = new CiUtilGenerator; - fscreator = new FsCreator; - - std::ifstream reader; - - std::cout << "dbc file : " << dbc_file_path << std::endl; - std::cout << "gen path : " << source_files_out_path << std::endl; - std::cout << "drv name : " << dbc_driver_name << std::endl; - - if (std::filesystem::exists(dbc_file_path) == false) - { - std::cout << "DBC file is not exists!" << std::endl; - return -1; - } - - reader.open(dbc_file_path); - - std::istream& s = reader; - - scanner->TrimDbcText(s); - - std::string info(""); - - // create main destination directory - auto ret = fscreator->PrepareDirectory(dbc_driver_name.c_str(), source_files_out_path.c_str(), rewrite_src, info); - - if (ret) - { - cigen->Generate(scanner->dblist, fscreator->FS); - } - else - { - std::cout << "One or both are invalid\n"; - } - -#if defined (GEN_UTIL_CODE) - - // check if option --node-utils is requested, when requested binutil generation - // wiil be performed on each node from DBC file in accordance to its RX / TX subscription - if (gen_nodeutils) - { - std::vector nodes; - - for (size_t num = 0; num < scanner->dblist.msgs.size(); num++) - { - // iterate all messages and collect All nodes assign to at least one message - auto m = scanner->dblist.msgs[num]; - - for (size_t txs = 0; txs < m->TranS.size(); txs++) - { - std::string tx_node_name = m->TranS[txs]; - - if (std::find(nodes.begin(), nodes.end(), tx_node_name) == nodes.end()) - { - // New node name. put it in the node collection - nodes.push_back(tx_node_name); - } - } - - for (size_t recs = 0; recs < m->RecS.size(); recs++) - { - std::string rx_node_name = m->RecS[recs]; - - // test all recs - if (std::find(nodes.begin(), nodes.end(), rx_node_name) == nodes.end()) - { - // New node name, put it in the node collection - nodes.push_back(rx_node_name); - } - } - } - - // for each node in collection perform specific bin-util generation - for (size_t node = 0; node < nodes.size(); node++) - { - std::string util_name = nodes[node] + "_" + dbc_driver_name; - - // set new driver name for current node - fscreator->FS.drvname = str_tolower(util_name); - fscreator->FS.DRVNAME = str_toupper(fscreator->FS.drvname); - fscreator->FS.util_c.dir = fscreator->FS.utildir; - fscreator->FS.util_h.dir = fscreator->FS.utildir; - - fscreator->FS.util_h.fname = str_tolower(fscreator->FS.drvname + "-binutil.h"); - fscreator->FS.util_h.fpath = fscreator->FS.utildir + "/" + fscreator->FS.util_h.fname; - - fscreator->FS.util_c.fname = str_tolower(fscreator->FS.drvname + "-binutil.c"); - fscreator->FS.util_c.fpath = fscreator->FS.utildir + "/" + fscreator->FS.util_c.fname; - - MsgsClassification groups; - - for (size_t i = 0; i < scanner->dblist.msgs.size(); i++) - { - auto m = scanner->dblist.msgs[i]; - - bool found = (std::find(m->TranS.begin(), m->TranS.end(), nodes[node]) != m->TranS.end()); - - if (found) - { - // Message is in Tx array of current node - groups.Tx.push_back(m->MsgID); - } - - found = (std::find(m->RecS.begin(), m->RecS.end(), nodes[node]) != m->RecS.end()); - - if (found) - { - // Message is in Rx array of current node - groups.Rx.push_back(m->MsgID); - } - } - - if (ret) - { - ciugen->Generate(scanner->dblist, fscreator->FS, groups, dbc_driver_name); - } - } - } - else - { - MsgsClassification groups; - - for (size_t i = 0; i < scanner->dblist.msgs.size(); i++) - { - groups.Rx.push_back(scanner->dblist.msgs[i]->MsgID); - } - - if (ret) - { - ciugen->Generate(scanner->dblist, fscreator->FS, groups, dbc_driver_name); - } - } - -#endif - - } - else - { - PrintUsage(); - } -} - -void PrintUsage() -{ - std::cout << "coderdbc v" << CODEGEN_LIB_VERSION_MAJ << "." << CODEGEN_LIB_VERSION_MIN << std::endl << std::endl; - std::cout << "project source code:\thttps://github.com/astand/c-coderdbc\t\t" << std::endl; - std::cout << "free web application:\thttps://coderdbc.com" << std::endl; - std::cout << std::endl; - std::cout << "required parameters:" << std::endl; - - std::cout << " -dbc\t\t path to dbc file" << std::endl; - std::cout << " -out\t\t directory for generated source files (must be pre-created)" << std::endl; - std::cout << " -drvname\t driver name - will be used for naming driver parts" << std::endl; - std::cout << std::endl; - std::cout << "optional parameters:" << std::endl; - std::cout << " -nodeutils\t will generate specific pairs of binutils drivers for each node" << std::endl; - std::cout << " -rw\t\t by default each new generation with previously used params" << std::endl; - std::cout << " \t\t will create new sud-directory with source files (000, 001, ... etc)" << std::endl; - std::cout << " \t\t '-rw' option enables rewriting: all source files previously generated" << std::endl; - std::cout << " \t\t will be replaced by new ones" << std::endl; - std::cout << std::endl; - - std::cout << "examples:" << std::endl; - std::cout << std::endl; - - std::cout << - "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb -nodeutils -rw" << std::endl; - - std::cout << - "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb -nodeutils" << std::endl; - - std::cout << "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb" << std::endl; - std::cout << std::endl; + auto opts = getoptions(argc, argv); + auto app = std::make_unique(opts); + app->Run(); } diff --git a/test/gencode/conf/testdb-config.h b/test/gencode/conf/testdb-config.h index d273328..32485f6 100644 --- a/test/gencode/conf/testdb-config.h +++ b/test/gencode/conf/testdb-config.h @@ -107,3 +107,22 @@ /* #define TESTDB_AUTO_CSM */ + +/* ------------------------------------------------------------------------- * + FMon handling model can be build in two ways: + + 1 - Default. In this case when specific frame unpack is called the + specific FMon_{Frame name}_{driver name} functoin will be called. + User's code scope has to define each of these functions. Each function is + responsible for the error handling of one frame + + 2 - MONO. In this case there is only one function to perform any frame + monitoring. This function has to be implemented in the user's code scope. + This function is named as FMon_MONO_{driver name}. It takes frame id + which can be used for selection of the logic for a frame monitoring. + This mode costs a bit more in runtime but when you often edit you DBC and you + have more than one project it could be more maintanable (there is + no necessity to replace source code) + + For using MONO way uncomment line below */ +/* #define TESTDB_USE_MONO_FMON */ diff --git a/test/gencode/lib/testdb-fmon.h b/test/gencode/lib/testdb-fmon.h index c056e9e..9c54c3c 100644 --- a/test/gencode/lib/testdb-fmon.h +++ b/test/gencode/lib/testdb-fmon.h @@ -20,12 +20,34 @@ It is the user responsibility to defined these functions in the separated .c file. If it won't be done the linkage error will happen */ -void FMon_UTEST_2_testdb(FrameMonitor_t* _mon, uint32_t msgid); -void FMon_EMPTY_0_testdb(FrameMonitor_t* _mon, uint32_t msgid); -void FMon_UTEST_3_testdb(FrameMonitor_t* _mon, uint32_t msgid); -void FMon_FLT_TEST_1_testdb(FrameMonitor_t* _mon, uint32_t msgid); -void FMon_SIG_TEST_1_testdb(FrameMonitor_t* _mon, uint32_t msgid); -void FMon_EMPTY_EXT_ID_testdb(FrameMonitor_t* _mon, uint32_t msgid); +#ifdef TESTDB_USE_MONO_FMON + +void _FMon_MONO_testdb(FrameMonitor_t* _mon, uint32_t msgid); + +#define FMon_UTEST_2_testdb(x, y) _FMon_MONO_testdb((x), (y)) +#define FMon_EMPTY_0_testdb(x, y) _FMon_MONO_testdb((x), (y)) +#define FMon_UTEST_3_testdb(x, y) _FMon_MONO_testdb((x), (y)) +#define FMon_FLT_TEST_1_testdb(x, y) _FMon_MONO_testdb((x), (y)) +#define FMon_SIG_TEST_1_testdb(x, y) _FMon_MONO_testdb((x), (y)) +#define FMon_EMPTY_EXT_ID_testdb(x, y) _FMon_MONO_testdb((x), (y)) + +#else + +void _FMon_UTEST_2_testdb(FrameMonitor_t* _mon, uint32_t msgid); +void _FMon_EMPTY_0_testdb(FrameMonitor_t* _mon, uint32_t msgid); +void _FMon_UTEST_3_testdb(FrameMonitor_t* _mon, uint32_t msgid); +void _FMon_FLT_TEST_1_testdb(FrameMonitor_t* _mon, uint32_t msgid); +void _FMon_SIG_TEST_1_testdb(FrameMonitor_t* _mon, uint32_t msgid); +void _FMon_EMPTY_EXT_ID_testdb(FrameMonitor_t* _mon, uint32_t msgid); + +#define FMon_UTEST_2_testdb(x, y) _FMon_UTEST_2_testdb((x), (y)) +#define FMon_EMPTY_0_testdb(x, y) _FMon_EMPTY_0_testdb((x), (y)) +#define FMon_UTEST_3_testdb(x, y) _FMon_UTEST_3_testdb((x), (y)) +#define FMon_FLT_TEST_1_testdb(x, y) _FMon_FLT_TEST_1_testdb((x), (y)) +#define FMon_SIG_TEST_1_testdb(x, y) _FMon_SIG_TEST_1_testdb((x), (y)) +#define FMon_EMPTY_EXT_ID_testdb(x, y) _FMon_EMPTY_EXT_ID_testdb((x), (y)) + +#endif #endif // TESTDB_USE_DIAG_MONITORS diff --git a/test/gencode/lib/testdb.h b/test/gencode/lib/testdb.h index 076099a..0e4a1b9 100644 --- a/test/gencode/lib/testdb.h +++ b/test/gencode/lib/testdb.h @@ -58,6 +58,12 @@ typedef struct uint32_t U28_TEST_1; // Bits=28 // This is test signal for Value Table + // + // + // + // + // + // // 3 : "Unsupported" // 2 : "Fail" // 1 : "OK" @@ -77,6 +83,12 @@ typedef struct uint32_t U28_TEST_1; // Bits=28 // This is test signal for Value Table + // + // + // + // + // + // // 3 : "Unsupported" // 2 : "Fail" // 1 : "OK" @@ -544,6 +556,12 @@ typedef struct #ifdef TESTDB_USE_BITS_SIGNAL // This is test signal for Value Table + // + // + // + // + // + // // 3 : "Unsupported" // 2 : "Fail" // 1 : "OK" @@ -556,6 +574,12 @@ typedef struct #else // This is test signal for Value Table + // + // + // + // + // + // // 3 : "Unsupported" // 2 : "Fail" // 1 : "OK" diff --git a/test/gencode/usr/testdb-fmon.c b/test/gencode/usr/testdb-fmon.c index 053af3b..9d33445 100644 --- a/test/gencode/usr/testdb-fmon.c +++ b/test/gencode/usr/testdb-fmon.c @@ -7,40 +7,52 @@ Put the monitor function content here, keep in mind - next generation will completely clear all manually added code (!) */ -void FMon_UTEST_2_testdb(FrameMonitor_t* _mon, uint32_t msgid) +#ifdef TESTDB_USE_MONO_FMON + +void _FMon_MONO_testdb(FrameMonitor_t* _mon, uint32_t msgid) +{ + (void)_mon; + (void)msgid; +} + +#else + +void _FMon_UTEST_2_testdb(FrameMonitor_t* _mon, uint32_t msgid) { (void)_mon; (void)msgid; } -void FMon_EMPTY_0_testdb(FrameMonitor_t* _mon, uint32_t msgid) +void _FMon_EMPTY_0_testdb(FrameMonitor_t* _mon, uint32_t msgid) { (void)_mon; (void)msgid; } -void FMon_UTEST_3_testdb(FrameMonitor_t* _mon, uint32_t msgid) +void _FMon_UTEST_3_testdb(FrameMonitor_t* _mon, uint32_t msgid) { (void)_mon; (void)msgid; } -void FMon_FLT_TEST_1_testdb(FrameMonitor_t* _mon, uint32_t msgid) +void _FMon_FLT_TEST_1_testdb(FrameMonitor_t* _mon, uint32_t msgid) { (void)_mon; (void)msgid; } -void FMon_SIG_TEST_1_testdb(FrameMonitor_t* _mon, uint32_t msgid) +void _FMon_SIG_TEST_1_testdb(FrameMonitor_t* _mon, uint32_t msgid) { (void)_mon; (void)msgid; } -void FMon_EMPTY_EXT_ID_testdb(FrameMonitor_t* _mon, uint32_t msgid) +void _FMon_EMPTY_EXT_ID_testdb(FrameMonitor_t* _mon, uint32_t msgid) { (void)_mon; (void)msgid; } +#endif // TESTDB_USE_MONO_FMON + #endif // TESTDB_USE_DIAG_MONITORS pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy