LCOV - code coverage report
Current view: top level - oksdalgen/apps - oksdalgen.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 664 0
Test Date: 2026-07-12 15:23:06 Functions: 0.0 % 12 0

            Line data    Source code
       1              : //
       2              : // DUNE DAQ modification notice:
       3              : // This file has been modified from the original ATLAS genconfig source for the DUNE DAQ project.
       4              : // Fork baseline commit: genconfig-03-10-00 (2021-04-26).
       5              : // Renamed since fork: yes (from src/genconfig.cpp to apps/oksdalgen.cxx).
       6              : //
       7              : 
       8              : 
       9              : #include "class_info.hpp"
      10              : 
      11              : #include "oks/kernel.hpp"
      12              : #include "oks/class.hpp"
      13              : #include "oks/attribute.hpp"
      14              : #include "oks/relationship.hpp"
      15              : #include "oks/method.hpp"
      16              : 
      17              : #include <stdlib.h>
      18              : #include <ctype.h>
      19              : 
      20              : #include <algorithm>
      21              : #include <string>
      22              : #include <list>
      23              : #include <set>
      24              : #include <iostream>
      25              : 
      26              : using namespace dunedaq;
      27              : using namespace dunedaq::oksdalgen;
      28              : 
      29              :   // declare external functions
      30              : 
      31              : extern std::string alnum_name(const std::string& in);
      32              : extern std::string capitalize_name(const std::string& in);
      33              : extern void print_description(std::ostream& s, const std::string& text, const char * dx);
      34              : extern void print_indented(std::ostream& s, const std::string& text, const char * dx);
      35              : extern std::string get_type(oks::OksData::Type oks_type, bool is_cpp);
      36              : extern void gen_dump_application(std::ostream& s, std::list<std::string>& class_names, const std::string& cpp_ns_name, const std::string& cpp_hdr_dir, const char * conf_header, const char * conf_name, const char * headres_prologue, const char * main_function_prologue);
      37              : extern void write_info_file(std::ostream& s, const std::string& cpp_namespace, const std::string& cpp_header_dir, const std::set<const oks::OksClass *, std::less<const oks::OksClass *> >& class_names);
      38              : extern std::string get_full_cpp_class_name(const oks::OksClass * c, const ClassInfo::Map& cl_info, const std::string & cpp_ns_name);
      39              : extern std::string get_include_dir(const oks::OksClass * c, const ClassInfo::Map& cl_info, const std::string& cpp_hdr_dir);
      40              : // extern const std::string& get_package_name(const oks::OksClass * c, const ClassInfo::Map& cl_info, const std::string& java_p_name);
      41              : extern void parse_arguments(int argc, char *argv[], std::list<std::string>& class_names, std::list<std::string>& file_names, std::list<std::string>& include_dirs, std::list<std::string>& user_classes, std::string& cpp_dir_name, std::string& cpp_ns_name, std::string& cpp_hdr_dir, std::string& info_file_name, bool& verbose);
      42              : extern bool process_external_class(ClassInfo::Map& cl_info, const oks::OksClass * c, const std::list<std::string>& include_dirs, const std::list<std::string>& user_classes, bool verbose);
      43              : extern std::string int2dx(int level);
      44              : extern int open_cpp_namespace(std::ostream& s, const std::string& value);
      45              : extern void close_cpp_namespace(std::ostream& s, int level);
      46              : extern std::string get_method_header_prologue(oks::OksMethodImplementation *);
      47              : extern std::string get_method_header_epilogue(oks::OksMethodImplementation *);
      48              : extern std::string get_public_section(oks::OksMethodImplementation * mi);
      49              : extern std::string get_private_section(oks::OksMethodImplementation * mi);
      50              : extern std::string get_member_initializer_list(oks::OksMethodImplementation * mi);
      51              : extern std::string get_method_implementation_body(oks::OksMethodImplementation * mi);
      52              : extern bool get_add_algo_1(oks::OksMethodImplementation * mi);
      53              : extern bool get_add_algo_n(oks::OksMethodImplementation * mi);
      54              : extern oks::OksMethodImplementation * find_cpp_method_implementation(const oks::OksMethod * method);
      55              : 
      56              : 
      57              :   /**
      58              :    *  The function has_superclass returns true if 'tested' class
      59              :    *  has class 'c' as a superclass
      60              :    */
      61              : 
      62              : static bool
      63            0 : has_superclass(const oks::OksClass * tested, const oks::OksClass * c)
      64              : {
      65            0 :   if (const oks::OksClass::FList * sclasses = tested->all_super_classes())
      66              :     {
      67            0 :       for (const auto& i : *sclasses)
      68              :         {
      69            0 :           if (i == c)
      70              :             {
      71            0 :               return true;
      72              :             }
      73              :         }
      74              :     }
      75              : 
      76              :   return false;
      77              : }
      78              : 
      79              : const std::string WHITESPACE = " \n\r\t\f\v";
      80              :  
      81            0 : std::string ltrim(const std::string &s)
      82              : {
      83            0 :     size_t start = s.find_first_not_of(WHITESPACE);
      84            0 :     return (start == std::string::npos) ? "" : s.substr(start);
      85              : }
      86              :  
      87            0 : std::string rtrim(const std::string &s)
      88              : {
      89            0 :     size_t end = s.find_last_not_of(WHITESPACE);
      90            0 :     return (end == std::string::npos) ? "" : s.substr(0, end + 1);
      91              : }
      92              :  
      93            0 : std::string trim(const std::string &s) {
      94            0 :     return rtrim(ltrim(s));
      95              : }
      96              : 
      97              : const std::vector<std::string> cpp_method_virtual_specifiers = {
      98              :     "virtual",
      99              :     "override",
     100              :     "final"
     101              : };
     102              : 
     103              : static void
     104            0 : gen_header(const oks::OksClass *cl,
     105              :            std::ostream& cpp_file,
     106              :            const std::string& cpp_ns_name,
     107              :            const std::string& cpp_hdr_dir,
     108              :            const ClassInfo::Map& cl_info)
     109              : {
     110            0 :   const std::string name(alnum_name(cl->get_name()));
     111              : 
     112              : 
     113              :     // get includes for super classes if necessary
     114              : 
     115            0 :   if (const std::list<std::string*> * super_list = cl->direct_super_classes())
     116              :     {
     117            0 :       cpp_file << "  // include files for classes used in inheritance hierarchy\n\n";
     118              : 
     119            0 :       for (const auto& i : *super_list)
     120              :         {
     121            0 :           oks::OksClass * c = cl->get_kernel()->find_class(*i);
     122            0 :           cpp_file << "#include \"" << get_include_dir(c, cl_info, cpp_hdr_dir) << ".hpp\"\n";
     123              :         }
     124              :     }
     125              : 
     126            0 :   cpp_file << std::endl;
     127              : 
     128              : 
     129              :     // generate forward declarations if necessary
     130            0 :     {
     131              :       // create set of classes to avoid multiple forward declarations of the same class
     132            0 :       std::set<oks::OksClass*> rclasses;
     133              : 
     134              :       // check direct relationships (c++)
     135            0 :       if (cl->direct_relationships() && !cl->direct_relationships()->empty())
     136            0 :         for (const auto &i : *cl->direct_relationships())
     137            0 :           rclasses.insert(i->get_class_type());
     138              : 
     139              :       // check methods
     140            0 :       if (const std::list<oks::OksMethod*> *mlist = cl->direct_methods())
     141              :         {
     142            0 :           for (const auto &i : *mlist)
     143              :             {
     144            0 :               if (oks::OksMethodImplementation *mi = find_cpp_method_implementation(i))
     145              :                 {
     146            0 :                   const std::string mp(mi->get_prototype());
     147            0 :                   for (const auto &j : cl->get_kernel()->classes())
     148              :                     {
     149            0 :                       const std::string s(j.second->get_name());
     150            0 :                       std::string::size_type idx = mp.find(s);
     151            0 :                       if (idx != std::string::npos && (idx == 0 || !isalnum(mp[idx - 1])) && !isalnum(mp[idx + s.size()]))
     152            0 :                         rclasses.insert(j.second);
     153            0 :                     }
     154            0 :                 }
     155              :             }
     156              :         }
     157              : 
     158            0 :       NameSpaceInfo ns_info;
     159              : 
     160            0 :       for (const auto &c : rclasses)
     161              :         {
     162              :           // check if the class' header is not already included
     163            0 :           if (has_superclass(cl, c) || cl == c)
     164            0 :             continue;
     165              : 
     166            0 :           ClassInfo::Map::const_iterator idx = cl_info.find(c);
     167            0 :           ns_info.add((idx != cl_info.end() ? (*idx).second.get_namespace() : cpp_ns_name), alnum_name(c->get_name()));
     168              :         }
     169              : 
     170            0 :       if (!ns_info.empty())
     171              :         {
     172            0 :           cpp_file << "  // forward declaration for classes used in relationships and algorithms\n\n";
     173            0 :           ns_info.print(cpp_file, 0);
     174            0 :           cpp_file << "\n\n";
     175              :         }
     176            0 :     }
     177              : 
     178              :     // generate methods prologues if necessary
     179              : 
     180            0 :   if (const std::list<oks::OksMethod*> *mlist = cl->direct_methods())
     181            0 :     for (const auto &i : *mlist)
     182            0 :       if (oks::OksMethodImplementation *mi = find_cpp_method_implementation(i))
     183            0 :         if (!get_method_header_prologue(mi).empty())
     184              :           {
     185            0 :             cpp_file << "  // prologue of method " << cl->get_name() << "::" << i->get_name() << "()\n";
     186            0 :             cpp_file << get_method_header_prologue(mi) << std::endl;
     187              :           }
     188              : 
     189              : 
     190              :     // open namespace
     191              : 
     192            0 :   int ns_level = open_cpp_namespace(cpp_file, cpp_ns_name);
     193            0 :   std::string ns_dx = int2dx(ns_level);
     194            0 :   std::string ns_dx2 = ns_dx + "    ";
     195              :   
     196            0 :   const char * dx  = ns_dx.c_str();    // are used for alignment
     197            0 :   const char * dx2 = ns_dx2.c_str();
     198              : 
     199              : 
     200              :     // generate description
     201              : 
     202            0 :   {
     203            0 :     std::string txt("Declares methods to get and put values of attributes / relationships, to print and to destroy object.\n");
     204              : 
     205            0 :     txt +=
     206              :       "<p>\n"
     207              :       "The methods can throw several exceptions:\n"
     208              :       "<ul>\n"
     209              :       " <li><code>conffwk.NotFoundException</code> - in case of wrong attribute or relationship name (e.g. in case of database schema modification)\n"
     210              :       " <li><code>conffwk.SystemException</code> - in case of system problems (communication or implementation database failure, schema modification, object destruction, etc.)\n"
     211              :       "</ul>\n"
     212              :       "<p>\n"
     213              :       "In addition the methods modifying database (set value, destroy object) can throw <code>conffwk.NotAllowedException</code> "
     214            0 :       "exception in case, if there are no write access rights or database is already locked by other process.\n";
     215              : 
     216            0 :     if (!cl->get_description().empty())
     217              :       {
     218            0 :         txt += "\n<p>\n";
     219            0 :         txt += cl->get_description();
     220            0 :         txt += "\n";
     221              :       }
     222              :  
     223            0 :     txt += "@author oksdalgen\n";
     224              : 
     225            0 :     cpp_file << std::endl;
     226            0 :     print_description(cpp_file, cl->get_description(), dx);
     227            0 :   }
     228              : 
     229              :     // generate class declaration itself
     230              : 
     231            0 :   cpp_file << dx << "class " << name << " : ";
     232              : 
     233              :     // generate inheritance list
     234              : 
     235            0 :   if (const std::list<std::string*> * super_list = cl->direct_super_classes())
     236              :     {
     237            0 :       for (std::list<std::string*>::const_iterator i = super_list->begin(); i != super_list->end();)
     238              :         {
     239            0 :           const oks::OksClass * c = cl->get_kernel()->find_class(**i);
     240            0 :           cpp_file << "public " << get_full_cpp_class_name(c, cl_info, cpp_ns_name);
     241            0 :           if (++i != super_list->end())
     242            0 :             cpp_file << ", ";
     243              :         }
     244              :     }
     245              :   else
     246              :     {
     247            0 :       cpp_file << "public virtual dunedaq::conffwk::DalObject";
     248              :     }
     249              : 
     250            0 :   cpp_file << " {\n\n";
     251              : 
     252              :     // generate standard methods
     253              : 
     254            0 :   cpp_file
     255              :     << dx << "  friend class conffwk::Configuration;\n"
     256              :     << dx << "  friend class conffwk::DalObject;\n"
     257              :     << dx << "  friend class conffwk::DalFactory;\n"
     258              :     << dx << "  friend class conffwk::DalRegistry;\n\n"
     259              :     << dx << "  protected:\n\n"
     260              :     << dx << "    " << name << "(conffwk::DalRegistry& db, const conffwk::ConfigObject& obj) noexcept;\n"
     261              :     << dx << "    virtual ~" << name << "() noexcept;\n"
     262              :     << dx << "    virtual void init(bool init_children);\n\n"
     263              :     << dx << "  public:\n\n"
     264              :     << dx << "      /** The name of the configuration class. */\n\n"
     265              :     << dx << "    static const std::string& s_class_name;\n\n\n"
     266              :     << dx << "      /**\n"
     267              :     << dx << "       * \\brief Print details of the " << name << " object.\n"
     268              :     << dx << "       *\n"
     269              :     << dx << "       * Parameters are:\n"
     270              :     << dx << "       *   \\param offset        number of spaces to shift object right (useful to print nested objects)\n"
     271              :     << dx << "       *   \\param print_header  if false, do not print object header (to print attributes of base classes)\n"
     272              :     << dx << "       *   \\param s             output stream\n"
     273              :     << dx << "       */\n\n"
     274              :     << dx << "    virtual void print(unsigned int offset, bool print_header, std::ostream& s) const;\n\n\n"
     275              :     << dx << "      /**\n"
     276              :     << dx << "       * \\brief Get values of relationships and results of some algorithms as a vector of dunedaq::conffwk::DalObject pointers.\n"
     277              :     << dx << "       *\n"
     278              :     << dx << "       * Parameters are:\n"
     279              :     << dx << "       *   \\param name          name of the relationship or algorithm\n"
     280              :     << dx << "       *   \\return              value of relationship or result of algorithm\n"
     281              :     << dx << "       *   \\throw               std::exception if there is no relationship or algorithm with such name in this and base classes\n"
     282              :     << dx << "       */\n\n"
     283              :     << dx << "    virtual std::vector<const dunedaq::conffwk::DalObject *> get(const std::string& name, bool upcast_unregistered = true) const;\n\n\n"
     284              :     << dx << "  protected:\n\n"
     285            0 :     << dx << "    bool get(const std::string& name, std::vector<const dunedaq::conffwk::DalObject *>& vec, bool upcast_unregistered, bool first_call) const;\n\n\n";
     286              : 
     287              : 
     288              :     // generate class attributes and relationships in accordance with
     289              :     // database schema
     290              : 
     291            0 :   if (cl->direct_attributes() || cl->direct_relationships() || cl->direct_methods())
     292              :     {
     293            0 :       cpp_file << dx << "  private:\n\n";
     294              : 
     295              :       // generate attributes:
     296              :       //  - for single attributes this is a normal member variable.
     297              :       //  - for multiple values this is a std::vector<T>.
     298              : 
     299            0 :       if (const std::list<oks::OksAttribute*> * alist = cl->direct_attributes())
     300              :         {
     301            0 :           for (const auto& i : *alist)
     302              :             {
     303            0 :               const std::string aname(alnum_name(i->get_name()));
     304            0 :               std::string cpp_type = get_type(i->get_data_type(), true);
     305              : 
     306            0 :               if (i->get_is_multi_values())
     307            0 :                 cpp_file << dx << "    std::vector<" << cpp_type << "> m_" << aname << ";\n";
     308              :               else
     309            0 :                 cpp_file << dx << "    " << cpp_type << " m_" << aname << ";\n";
     310            0 :             }
     311              :         }
     312              : 
     313              : 
     314              :       // generate relationships:
     315              :       //  - for single values this is just a pointer.
     316              :       //  - for multiple values this is a vector of pointers.
     317              : 
     318            0 :       if (const std::list<oks::OksRelationship*> *rlist = cl->direct_relationships())
     319              :         {
     320            0 :           for (const auto& i : *rlist)
     321              :             {
     322            0 :               const std::string rname(alnum_name(i->get_name()));
     323            0 :               const std::string full_class_name(get_full_cpp_class_name(i->get_class_type(), cl_info, cpp_ns_name));
     324            0 :               if (i->get_high_cardinality_constraint() == oks::OksRelationship::Many)
     325            0 :                 cpp_file << dx << "    std::vector<const " << full_class_name << "*> m_" << rname << ";\n";
     326              :               else
     327            0 :                 cpp_file << dx << "    const " << full_class_name << "* m_" << rname << ";\n";
     328            0 :             }
     329              :         }
     330              : 
     331              : 
     332              :       // generate methods extension if any
     333              : 
     334            0 :       if (const std::list<oks::OksMethod*> * mlist = cl->direct_methods())
     335              :         {
     336            0 :           for (const auto& i : *mlist)
     337              :             {
     338            0 :               if (oks::OksMethodImplementation * mi = find_cpp_method_implementation(i))
     339              :                 {
     340            0 :                   std::string method_extension = get_private_section(mi);
     341            0 :                   if (!method_extension.empty())
     342              :                     {
     343            0 :                       cpp_file << "\n" << dx << "      // extension of method " << cl->get_name() << "::" << i->get_name() << "()\n";
     344            0 :                       print_indented(cpp_file, method_extension, dx2);
     345              :                     }
     346            0 :                 }
     347              :             }
     348              :         }
     349              : 
     350              : 
     351            0 :       cpp_file << std::endl << std::endl << dx << "  public:\n\n";
     352              : 
     353              : 
     354              :       // generate attribute accessors:
     355              :       //  1. for each attribute generate static std::string with it's name
     356              :       //  2a. for single values this is just:
     357              :       //     - attribute_type attribute_name() const { return m_attribute; }
     358              :       //  2b. for multiple values this is:
     359              :       //     - const std::vector<attribute_type>& attribute_name() const { return m_attribute; }
     360              : 
     361            0 :       if (const std::list<oks::OksAttribute*> *alist = cl->direct_attributes())
     362              :         {
     363              : 
     364            0 :           cpp_file << dx << "      // attribute names\n\n";
     365              : 
     366            0 :           for (const auto& i : *alist)
     367              :             {
     368            0 :               const std::string& aname(i->get_name());
     369            0 :               cpp_file << dx << "    inline static const std::string s_" << alnum_name(aname) << " = \"" << aname << "\";\n";
     370              :             }
     371              : 
     372            0 :           cpp_file << "\n";
     373              : 
     374            0 :           for (const auto& i : *alist)
     375              :             {
     376            0 :               const std::string& cpp_aname(alnum_name(i->get_name()));
     377            0 :               cpp_file << dx << "    static const std::string& __get_" << cpp_aname << "_str() noexcept { return s_" << cpp_aname << "; }\n";
     378            0 :             }
     379              : 
     380            0 :           cpp_file << std::endl << std::endl;
     381              : 
     382            0 :           for (const auto& i : *alist)
     383              :             {
     384            0 :               const std::string aname(alnum_name(i->get_name()));
     385              : 
     386              :               // generate enum values
     387              : 
     388            0 :               if (i->get_data_type() == oks::OksData::enum_type && !i->get_range().empty())
     389              :                 {
     390            0 :                   std::string description("Valid enumeration values to compare with value returned by get_");
     391            0 :                   description += aname;
     392            0 :                   description += "() and to pass value to set_";
     393            0 :                   description += aname;
     394            0 :                   description += "() methods.";
     395              : 
     396            0 :                   print_description(cpp_file, description, dx2);
     397              : 
     398            0 :                   description += "\nUse toString() method to compare and to pass the values. Do not use name() method.";
     399              : 
     400            0 :                   cpp_file << dx << "    struct " << capitalize_name(aname) << " {\n";
     401              : 
     402            0 :                   oks::Oks::Tokenizer t(i->get_range(), ",");
     403            0 :                   std::string token;
     404            0 :                   while (!(token = t.next()).empty())
     405              :                     {
     406            0 :                       cpp_file << dx << "      inline static const std::string " << capitalize_name(alnum_name(token)) << " = \"" << token << "\";\n";
     407              :                     }
     408              : 
     409            0 :                   cpp_file << dx << "    };\n\n";
     410            0 :                 }
     411              : 
     412              :               // generate get method description
     413              : 
     414            0 :                 {
     415              : 
     416            0 :                   std::string description("Get \"");
     417            0 :                   description += i->get_name();
     418            0 :                   description += "\" attribute value.\n\n";
     419            0 :                   description += i->get_description();
     420              : 
     421            0 :                   std::string description2("\\brief ");
     422            0 :                   description2 += description;
     423            0 :                   description2 += "\n\\return the attribute value\n";
     424            0 :                   description2 += "\\throw dunedaq::conffwk::Generic, dunedaq::conffwk::DeletedObject\n";
     425              : 
     426            0 :                   print_description(cpp_file, description2, dx2);
     427            0 :                 }
     428              : 
     429              :               // generate method body
     430              : 
     431            0 :               cpp_file << dx << "    ";
     432              : 
     433            0 :               std::string cpp_type = get_type(i->get_data_type(), true);
     434              : 
     435            0 :               if (i->get_is_multi_values())
     436              :                 {
     437            0 :                   cpp_file << "const std::vector<" << cpp_type << ">&";
     438              :                 }
     439              :               else
     440              :                 {
     441            0 :                   if (cpp_type == "std::string")
     442            0 :                     cpp_file << "const std::string&";
     443              :                   else
     444            0 :                     cpp_file << cpp_type;
     445              :                 }
     446              : 
     447            0 :               cpp_file << '\n'
     448              :                   << dx << "    get_" << aname << "() const\n"
     449              :                   << dx << "      {\n"
     450              :                   << dx << "        std::lock_guard scoped_lock(m_mutex);\n"
     451              :                   << dx << "        check();\n"
     452              :                   << dx << "        check_init();\n"
     453              :                   << dx << "        return m_" << aname << ";\n"
     454            0 :                   << dx << "      }\n\n";
     455              : 
     456              :               // generate set method description
     457              : 
     458            0 :                 {
     459            0 :                   std::string description("Set \"");
     460            0 :                   description += i->get_name();
     461            0 :                   description += "\" attribute value.\n\n";
     462            0 :                   description += i->get_description();
     463              : 
     464            0 :                   std::string description2("\\brief ");
     465            0 :                   description2 += description;
     466            0 :                   description2 += "\n\\param value  new attribute value\n";
     467            0 :                   description2 += "\\throw dunedaq::conffwk::Generic, dunedaq::conffwk::DeletedObject\n";
     468              : 
     469            0 :                   print_description(cpp_file, description2, dx2);
     470            0 :                 }
     471              : 
     472              :               // generate set method
     473              : 
     474            0 :               cpp_file << dx << "    void\n" << dx << "    set_" << aname << '(';
     475              : 
     476            0 :               if (i->get_is_multi_values())
     477              :                 {
     478            0 :                   cpp_file << "const std::vector<" << cpp_type << ">&";
     479              :                 }
     480              :               else
     481              :                 {
     482            0 :                   if (cpp_type == "std::string")
     483              :                     {
     484            0 :                       cpp_file << "const std::string&";
     485              :                     }
     486              :                   else
     487              :                     {
     488            0 :                       cpp_file << cpp_type;
     489              :                     }
     490              :                 }
     491              : 
     492            0 :               cpp_file << " value)\n"
     493              :                 << dx << "      {\n"
     494              :                 << dx << "        std::lock_guard scoped_lock(m_mutex);\n"
     495              :                 << dx << "        check();\n"
     496              :                 << dx << "        clear();\n"
     497            0 :                 << dx << "        p_obj.";
     498              : 
     499            0 :               if (i->get_data_type() == oks::OksData::string_type && i->get_is_multi_values() == false)
     500              :                 {
     501            0 :                   cpp_file << "set_by_ref";
     502              :                 }
     503            0 :               else if (i->get_data_type() == oks::OksData::enum_type)
     504              :                 {
     505            0 :                   cpp_file << "set_enum";
     506              :                 }
     507            0 :               else if (i->get_data_type() == oks::OksData::class_type)
     508              :                 {
     509            0 :                   cpp_file << "set_class";
     510              :                 }
     511            0 :               else if (i->get_data_type() == oks::OksData::date_type)
     512              :                 {
     513            0 :                   cpp_file << "set_date";
     514              :                 }
     515            0 :               else if (i->get_data_type() == oks::OksData::time_type)
     516              :                 {
     517            0 :                   cpp_file << "set_time";
     518              :                 }
     519              :               else
     520              :                 {
     521            0 :                   cpp_file << "set_by_val";
     522              :                 }
     523              : 
     524            0 :               cpp_file << "(s_" << aname << ", value);\n"
     525            0 :                   << dx << "      }\n\n\n";
     526            0 :             }
     527              :         }
     528              : 
     529              : 
     530              :       // generate relationship accessors.
     531              :       //  1. for each relationship generate static std::string with it's name
     532              :       //  2a. for single values this is just:
     533              :       //      - const relation_type * relation() const { return m_relation; }
     534              :       //  2b. for multiple values this is:
     535              :       //      - const std::vector<const relation_type*>& relation() const { return m_relation; }
     536              : 
     537            0 :       if (const std::list<oks::OksRelationship*> *rlist = cl->direct_relationships())
     538              :         {
     539              : 
     540            0 :           cpp_file << dx << "      // relationship names\n\n";
     541              : 
     542            0 :           for (const auto& i : *rlist)
     543              :             {
     544            0 :               const std::string& rname(i->get_name());
     545            0 :               cpp_file << dx << "    inline static const std::string s_" << alnum_name(rname) << " = \"" << rname << "\";\n";
     546              :             }
     547              : 
     548            0 :           cpp_file << "\n";
     549              : 
     550            0 :           for (const auto& i : *rlist)
     551              :             {
     552            0 :               const std::string& cpp_rname(alnum_name(i->get_name()));
     553            0 :               cpp_file << dx << "    static const std::string& __get_" << cpp_rname << "_str() noexcept { return s_" << cpp_rname << "; }\n";
     554            0 :             }
     555              : 
     556            0 :           cpp_file << std::endl << std::endl;
     557              : 
     558            0 :           for (const auto& i : *rlist)
     559              :             {
     560              : 
     561              :               // generate description
     562              : 
     563            0 :                 {
     564            0 :                   std::string description("Get \"");
     565            0 :                   description += i->get_name();
     566            0 :                   description += "\" relationship value.\n\n";
     567            0 :                   description += i->get_description();
     568              : 
     569            0 :                   std::string description2("\\brief ");
     570            0 :                   description2 += description;
     571            0 :                   description2 += "\n\\return the relationship value\n";
     572            0 :                   description2 += "\\throw dunedaq::conffwk::Generic, dunedaq::conffwk::DeletedObject\n";
     573              : 
     574            0 :                   print_description(cpp_file, description2, dx2);
     575            0 :                 }
     576              : 
     577              :               // generate method body
     578              : 
     579            0 :               cpp_file << dx << "    const ";
     580              : 
     581            0 :               const std::string rname(alnum_name(i->get_name()));
     582            0 :               std::string full_cpp_class_name = get_full_cpp_class_name(i->get_class_type(), cl_info, cpp_ns_name);
     583              : 
     584            0 :               if (i->get_high_cardinality_constraint() == oks::OksRelationship::Many)
     585              :                 {
     586            0 :                   cpp_file << "std::vector<const " << full_cpp_class_name << "*>&";
     587              :                 }
     588              :               else
     589              :                 {
     590            0 :                   cpp_file << full_cpp_class_name << " *";
     591              :                 }
     592              : 
     593            0 :               cpp_file << "\n"
     594              :                   << dx << "    get_" << rname << "() const\n"
     595              :                   << dx << "    {\n"
     596              :                   << dx << "      std::lock_guard scoped_lock(m_mutex);\n"
     597              :                   << dx << "      check();\n"
     598            0 :                   << dx << "      check_init();\n";
     599              : 
     600            0 :               if (i->get_low_cardinality_constraint() == oks::OksRelationship::One)
     601              :                 {
     602            0 :                   if (i->get_high_cardinality_constraint() == oks::OksRelationship::One)
     603              :                     {
     604            0 :                       cpp_file
     605              :                           << dx << "      if (!m_" << rname << ")\n"
     606              :                           << dx << "        {\n"
     607              :                           << dx << "          std::ostringstream text;\n"
     608              :                           << dx << "          text << \"relationship \\\"\" << s_" << rname << " << \"\\\" of object \" << this << \" is not set\";\n"
     609              :                           << dx << "          throw dunedaq::conffwk::Generic(ERS_HERE, text.str().c_str());\n"
     610            0 :                           << dx << "        }\n";
     611              :                     }
     612              :                   else
     613              :                     {
     614            0 :                       cpp_file
     615              :                           << dx << "      if (m_" << rname << ".empty())\n"
     616              :                           << dx << "        {\n"
     617              :                           << dx << "          std::ostringstream text;\n"
     618              :                           << dx << "          text << \"relationship \\\"\" << s_" << rname << " << \"\\\" of object \" << this << \" is empty\";\n"
     619              :                           << dx << "          throw dunedaq::conffwk::Generic(ERS_HERE, text.str().c_str());\n"
     620            0 :                           << dx << "        }\n";
     621              :                     }
     622              :                 }
     623              : 
     624            0 :               cpp_file
     625              :                   << dx << "      return m_" << rname << ";\n"
     626            0 :                   << dx << "    }\n\n\n";
     627              : 
     628              :               // generate set method
     629              : 
     630            0 :                 {
     631            0 :                   std::string description("Set \"");
     632            0 :                   description += i->get_name();
     633            0 :                   description += "\" relationship value.\n\n";
     634            0 :                   description += i->get_description();
     635              : 
     636            0 :                   std::string description2("\\brief ");
     637            0 :                   description2 += description;
     638            0 :                   description2 += "\n\\param value  new relationship value\n";
     639            0 :                   description2 += "\\throw dunedaq::conffwk::Generic, dunedaq::conffwk::DeletedObject\n";
     640              : 
     641            0 :                   print_description(cpp_file, description2, dx2);
     642            0 :                 }
     643              : 
     644            0 :               cpp_file << dx << "    void\n" << dx << "    set_" << rname << "(const ";
     645              : 
     646            0 :               if (i->get_high_cardinality_constraint() == oks::OksRelationship::Many)
     647              :                 {
     648            0 :                   cpp_file << "std::vector<const " << full_cpp_class_name << "*>&";
     649              :                 }
     650              :               else
     651              :                 {
     652            0 :                   cpp_file << full_cpp_class_name << " *";
     653              :                 }
     654              : 
     655            0 :               cpp_file << " value);\n\n";
     656            0 :             }
     657              :         }
     658              :     }
     659              : 
     660              : 
     661              :     // generate methods
     662              : 
     663            0 :   if (const std::list<oks::OksMethod*> *mlist = cl->direct_methods())
     664              :     {
     665            0 :       bool cpp_comment_is_printed = false;
     666              : 
     667            0 :       for (const auto& i : *mlist)
     668              :         {
     669              : 
     670              :           // C++ algorithms
     671              : 
     672            0 :           if (oks::OksMethodImplementation * mi = find_cpp_method_implementation(i))
     673              :             {
     674            0 :               if (cpp_comment_is_printed == false)
     675              :                 {
     676            0 :                   cpp_file << std::endl << dx << "  public:\n\n" << dx << "      // user-defined algorithms\n\n";
     677              :                   cpp_comment_is_printed = true;
     678              :                 }
     679              :               else
     680              :                 {
     681            0 :                   cpp_file << "\n\n";
     682              :                 }
     683              : 
     684              :               // generate description
     685              : 
     686            0 :               print_description(cpp_file, i->get_description(), dx2);
     687              : 
     688              :               // generate prototype
     689              : 
     690            0 :               cpp_file << dx << "    " << mi->get_prototype() << ";\n";
     691              : 
     692              : 
     693              :               // generate public section extension
     694              : 
     695            0 :               std::string public_method_extension = get_public_section(mi);
     696            0 :               if (!public_method_extension.empty())
     697              :                 {
     698            0 :                   cpp_file << "\n" << "      // extension of method " << cl->get_name() << "::" << i->get_name() << "()\n";
     699            0 :                   print_indented(cpp_file, public_method_extension, "    ");
     700              :                 }
     701            0 :             }
     702              : 
     703              :         }
     704              :     }
     705              : 
     706              : 
     707              :     // class finished
     708              : 
     709            0 :   cpp_file << dx << "};\n\n";
     710              : 
     711              : 
     712              :     // generate ostream operators and typedef for iterator
     713              : 
     714            0 :   cpp_file
     715              :     << dx << "  // out stream operator\n\n"
     716              :     << dx << "inline std::ostream& operator<<(std::ostream& s, const " << name << "& obj)\n"
     717              :     << dx << "  {\n"
     718              :     << dx << "    return obj.print_object(s);\n"
     719              :     << dx << "  }\n\n"
     720            0 :     << dx << "typedef std::vector<const " << name << "*>::const_iterator " << name << "Iterator;\n\n";
     721              : 
     722              : 
     723              :     // close namespace
     724              : 
     725            0 :   close_cpp_namespace(cpp_file, ns_level);
     726              : 
     727              : 
     728              :     // generate methods epilogues if necessary
     729              : 
     730            0 :   if (const std::list<oks::OksMethod*> * mlist = cl->direct_methods())
     731              :     {
     732            0 :       for (const auto & i : *mlist)
     733              :         {
     734            0 :           oks::OksMethodImplementation * mi = find_cpp_method_implementation(i);
     735            0 :           if (mi && !get_method_header_epilogue(mi).empty())
     736              :             {
     737            0 :               cpp_file << "  // epilogue of method " << cl->get_name() << "::" << i->get_name() << "()\n";
     738            0 :               cpp_file << get_method_header_epilogue(mi) << std::endl;
     739              :             }
     740              :         }
     741              :     }
     742              : 
     743            0 : }
     744              : 
     745              : 
     746              : static void
     747              : set2out(std::ostream& out, const std::set<std::string>& data, bool& is_first)
     748              : {
     749              :   for (const auto& x : data)
     750              :     {
     751              :       if (is_first)
     752              :         is_first = false;
     753              :       else
     754              :         out << ',';
     755              :       out << '\"' << x << "()\"";
     756              :     }
     757              : }
     758              : 
     759              : 
     760              : static void
     761            0 : gen_cpp_body(const oks::OksClass *cl, std::ostream& cpp_s, const std::string& cpp_ns_name, const std::string& cpp_hdr_dir, const ClassInfo::Map& cl_info)
     762              : {
     763            0 :   cpp_s << "#include \"logging/Logging.hpp\"\n\n";
     764              : 
     765            0 :   const std::string name(alnum_name(cl->get_name()));
     766              : 
     767            0 :   std::set<oks::OksClass *> rclasses;
     768              : 
     769              :     // for each relationship, include the header file
     770              : 
     771            0 :   if (const std::list<oks::OksRelationship*> * rlist = cl->direct_relationships())
     772              :     {
     773            0 :       for (const auto& i : *rlist)
     774              :         {
     775            0 :           oks::OksClass * c = i->get_class_type();
     776            0 :           if (has_superclass(cl, c) == false && cl != c)
     777              :             {
     778            0 :               rclasses.insert(c);
     779              :             }
     780              :         }
     781              :     }
     782              : 
     783            0 :   if (const std::list<oks::OksMethod*> * mlist = cl->direct_methods())
     784              :     {
     785            0 :       for (const auto& i : *mlist)
     786              :         {
     787            0 :           if (oks::OksMethodImplementation * mi = find_cpp_method_implementation(i))
     788              :             {
     789            0 :               std::string prototype(mi->get_prototype());
     790            0 :               std::string::size_type idx = prototype.find('(');
     791              : 
     792            0 :               if (get_add_algo_n(mi) || get_add_algo_1(mi))
     793              :                 {
     794              : 
     795            0 :                   if (idx != std::string::npos)
     796              :                     {
     797            0 :                       idx--;
     798              : 
     799              :                       // skip spaces between method name and ()
     800            0 :                       while (isspace(prototype[idx]) && idx > 0)
     801            0 :                         idx--;
     802              : 
     803              :                       // find beginning of the method name
     804            0 :                       while (!isspace(prototype[idx]) && idx > 0)
     805            0 :                         idx--;
     806              : 
     807              :                       // remove method name and arguments
     808            0 :                       prototype.erase(idx + 1);
     809              : 
     810              :                       // remove spaces
     811            0 :                       prototype.erase(std::remove_if(prototype.begin(), prototype.end(), [](unsigned char x)
     812            0 :                         { return std::isspace(x);}), prototype.end());
     813              : 
     814            0 :                       if (prototype.empty() == false)
     815              :                         {
     816            0 :                           idx = prototype.find('*');
     817            0 :                           prototype.erase(idx--);
     818              : 
     819            0 :                           if (idx != std::string::npos)
     820              :                             {
     821            0 :                               while (isalnum(prototype[idx]) && idx > 0)
     822            0 :                                 idx--;
     823              : 
     824            0 :                               if(idx == 0 && get_add_algo_1(mi) && prototype.find("const") == 0)
     825            0 :                                 prototype.erase(0, 5);
     826              :                               else
     827            0 :                                 prototype.erase(0, idx+1);
     828              : 
     829            0 :                               if (oks::OksClass * c = cl->get_kernel()->find_class(prototype))
     830            0 :                                 rclasses.insert(c);
     831              :                             }
     832              :                         }
     833              :                     }
     834              :                 }
     835            0 :             }
     836              :         }
     837              :     }
     838              : 
     839            0 :   if (!rclasses.empty())
     840              :     {
     841            0 :       cpp_s << "  // include files for classes used in relationships and algorithms\n\n";
     842              : 
     843            0 :       for (const auto& j : rclasses)
     844              :         {
     845            0 :           cpp_s << "#include \"" << get_include_dir(j, cl_info, cpp_hdr_dir) << ".hpp\"\n";
     846              :         }
     847              : 
     848            0 :       cpp_s << std::endl << std::endl;
     849              :     }
     850              : 
     851              : 
     852              :     // open namespace
     853              : 
     854            0 :   int ns_level = open_cpp_namespace(cpp_s, cpp_ns_name);
     855            0 :   std::string ns_dx = int2dx(ns_level);
     856            0 :   std::string ns_dx2 = ns_dx + "    ";
     857              : 
     858            0 :   const char * dx  = ns_dx.c_str();    // are used for alignment
     859            0 :   const char * dx2 = ns_dx2.c_str();
     860              : 
     861              : 
     862              :     // static objects
     863              : 
     864            0 :   cpp_s << dx << "const std::string& " << name << "::s_class_name(dunedaq::conffwk::DalFactory::instance().get_known_class_name_ref(\"" << name << "\"));\n\n";
     865              : 
     866            0 :   std::set<std::string> algo_n_set, algo_1_set;
     867              : 
     868            0 :   if (const std::list<oks::OksMethod*> * mlist = cl->direct_methods())
     869              :     {
     870            0 :       for (const auto& i : *mlist)
     871              :         {
     872            0 :           if(oks::OksMethodImplementation * mi = find_cpp_method_implementation(i))
     873              :             {
     874            0 :               std::string prototype(mi->get_prototype());
     875            0 :               std::string::size_type idx = prototype.find('(');
     876              : 
     877            0 :               if (idx != std::string::npos)
     878              :                 {
     879            0 :                   idx--;
     880              : 
     881              :                   // skip spaces between method name and ()
     882            0 :                   while (isspace(prototype[idx]) && idx > 0)
     883            0 :                     idx--;
     884              : 
     885              :                   // remove method arguments
     886            0 :                   prototype.erase(idx+1);
     887              : 
     888              :                   // find beginning of the method name
     889            0 :                   while (!isspace(prototype[idx]) && idx > 0)
     890            0 :                     idx--;
     891              : 
     892            0 :                   if (idx > 0)
     893              :                     {
     894            0 :                       prototype.erase(0, idx+1);
     895              : 
     896            0 :                       if (get_add_algo_n(mi))
     897              :                         {
     898            0 :                           algo_n_set.insert(prototype);
     899              :                         }
     900            0 :                       else if (get_add_algo_1(mi))
     901              :                         {
     902            0 :                           algo_1_set.insert(prototype);
     903              :                         }
     904              :                     }
     905              :                 }
     906            0 :             }
     907              :         }
     908              :     }
     909              : 
     910              : 
     911            0 :   if ( !cl->get_is_abstract() ) {
     912            0 :   cpp_s
     913              :     << dx << "  // the factory initializer\n\n"
     914              :     << dx << "static struct __" << name << "_Registrator\n"
     915              :     << dx << "  {\n"
     916              :     << dx << "    __" << name << "_Registrator()\n"
     917              :     << dx << "      {\n"
     918            0 :     << dx << "        dunedaq::conffwk::DalFactory::instance().register_dal_class<" << name << ">(\"" << cl->get_name() << "\");\n"
     919              :     << dx << "      }\n"
     920            0 :     << dx << "  } registrator;\n\n\n";
     921              :   }
     922              : 
     923              :     // the constructor
     924              : 
     925            0 :   cpp_s
     926              :     << dx << "  // the constructor\n\n"
     927              :     << dx << name << "::" << name << "(conffwk::DalRegistry& db, const conffwk::ConfigObject& o) noexcept :\n"
     928            0 :     << dx << "  " << "dunedaq::conffwk::DalObject(db, o)";
     929              : 
     930              : 
     931              :     // fill member initializer list, if any
     932              : 
     933            0 :   std::list<std::string> initializer_list;
     934              : 
     935            0 :   if(const std::list<std::string*> * slist = cl->direct_super_classes())
     936              :     {
     937            0 :       for(auto & i : *slist)
     938              :         {
     939            0 :           initializer_list.push_back(get_full_cpp_class_name(cl->get_kernel()->find_class(*i), cl_info, "") + "(db, o)");
     940              :         }
     941              :     }
     942              : 
     943            0 :   if (const std::list<oks::OksRelationship *> *rlist = cl->direct_relationships())
     944              :     {
     945            0 :       for (std::list<oks::OksRelationship*>::const_iterator i = rlist->begin(); i != rlist->end(); ++i)
     946              :         {
     947            0 :           if ((*i)->get_high_cardinality_constraint() != oks::OksRelationship::Many)
     948              :             {
     949            0 :               initializer_list.push_back(std::string("m_") + alnum_name((*i)->get_name()) + " (nullptr)");
     950              :             }
     951              :         }
     952              :     }
     953              : 
     954              : 
     955            0 :   if(const std::list<oks::OksMethod*> * mlist = cl->direct_methods())
     956              :     {
     957            0 :       for (std::list<oks::OksMethod*>::const_iterator i = mlist->begin(); i != mlist->end(); ++i)
     958              :         {
     959            0 :           if (oks::OksMethodImplementation * mi = find_cpp_method_implementation(*i))
     960              :             {
     961            0 :               std::string member_initializer = get_member_initializer_list(mi);
     962            0 :               member_initializer.erase(remove(member_initializer.begin(), member_initializer.end(), '\n'), member_initializer.end());
     963              : 
     964            0 :               if (!member_initializer.empty())
     965              :                 {
     966            0 :                   initializer_list.push_back(member_initializer);
     967              :                 }
     968            0 :             }
     969              :         }
     970              :     }
     971              : 
     972            0 :   if (initializer_list.empty() == false)
     973              :     {
     974            0 :       for (auto & i : initializer_list)
     975              :         {
     976            0 :           cpp_s << ",\n" << dx << "  " << i;
     977              :         }
     978              : 
     979            0 :       cpp_s << std::endl;
     980              :     }
     981              : 
     982            0 :   cpp_s << "\n"
     983              :     << dx << "{\n"
     984              :     << dx << "  ;\n"
     985            0 :     << dx << "}\n\n\n";
     986              : 
     987              : 
     988              :     // print method
     989              :  
     990            0 :   cpp_s
     991              :     << dx << "void " << name << "::print(unsigned int indent, bool print_header, std::ostream& s) const\n"
     992              :     << dx << "{\n"
     993              :     << dx << "  check_init();\n\n"
     994            0 :     << dx << "  try {\n";
     995              : 
     996            0 :   if (cl->direct_attributes() || cl->direct_relationships())
     997            0 :     cpp_s << dx << "    const std::string str(indent+2, ' ');\n";
     998              : 
     999            0 :   cpp_s
    1000              :     << '\n'
    1001              :     << dx << "    if (print_header)\n"
    1002            0 :     << dx << "      p_hdr(s, indent, s_class_name";
    1003              : 
    1004            0 :   if(!cpp_ns_name.empty()) {
    1005            0 :     cpp_s << ", \"" << cpp_ns_name << '\"';
    1006              :   }
    1007              : 
    1008            0 :   cpp_s << ");\n";
    1009              : 
    1010              : 
    1011            0 :   if (const std::list<std::string*> * slist = cl->direct_super_classes())
    1012              :     {
    1013            0 :       cpp_s << "\n\n" << dx << "      // print direct super-classes\n\n";
    1014              : 
    1015            0 :       for (const auto& i : *slist)
    1016            0 :         cpp_s << dx << "    " << get_full_cpp_class_name(cl->get_kernel()->find_class(*i), cl_info, cpp_ns_name) << "::print(indent, false, s);\n";
    1017              :     }
    1018              : 
    1019            0 :   if(const std::list<oks::OksAttribute*> * alist = cl->direct_attributes()) {
    1020            0 :     cpp_s << "\n\n" << dx << "      // print direct attributes\n\n";
    1021              : 
    1022            0 :     for(const auto& i : *alist) {
    1023            0 :       const std::string aname(alnum_name(i->get_name()));
    1024            0 :       std::string abase = (i->get_format() == oks::OksAttribute::Hex) ? "<dunedaq::conffwk::hex>" : (i->get_format() == oks::OksAttribute::Oct) ? "<dunedaq::conffwk::oct>" : "";
    1025              : 
    1026            0 :       if (i->get_is_multi_values())
    1027            0 :         cpp_s << dx << "    dunedaq::conffwk::p_mv_attr" << abase << "(s, str, s_" << aname << ", m_" << aname << ");\n";
    1028              :       else
    1029            0 :         cpp_s << dx << "    dunedaq::conffwk::p_sv_attr" << abase << "(s, str, s_" << aname << ", m_" << aname << ");\n";
    1030            0 :     }
    1031              :   }
    1032              : 
    1033            0 :   if (const std::list<oks::OksRelationship*> * rlist = cl->direct_relationships())
    1034              :     {
    1035            0 :       cpp_s << "\n\n" << dx << "      // print direct relationships\n\n";
    1036              : 
    1037            0 :       for (const auto& i : *rlist)
    1038              :         {
    1039            0 :           const std::string rname(alnum_name(i->get_name()));
    1040              : 
    1041            0 :           if (i->get_high_cardinality_constraint() == oks::OksRelationship::Many)
    1042              :             {
    1043            0 :               if (i->get_is_composite())
    1044            0 :                 cpp_s << dx << "    dunedaq::conffwk::p_mv_rel(s, str, indent, s_" << rname << ", m_" << rname << ");\n";
    1045              :               else
    1046            0 :                 cpp_s << dx << "    dunedaq::conffwk::p_mv_rel(s, str, s_" << rname << ", m_" << rname << ");\n";
    1047              :             }
    1048              :           else
    1049              :             {
    1050            0 :               if (i->get_is_composite())
    1051            0 :                 cpp_s << dx <<"    dunedaq::conffwk::p_sv_rel(s, str, indent, s_" << rname << ", m_" << rname << ");\n";
    1052              :               else
    1053            0 :                 cpp_s << dx <<"    dunedaq::conffwk::p_sv_rel(s, str, s_" << rname << ", m_" << rname << ");\n";
    1054              :             }
    1055            0 :         }
    1056              :     }
    1057              : 
    1058            0 :   cpp_s << dx << "  }\n"
    1059              :         << dx << "  catch (dunedaq::conffwk::Exception & ex) {\n"
    1060              :         << dx << "    dunedaq::conffwk::DalObject::p_error(s, ex);\n"
    1061              :         << dx << "  }\n"
    1062            0 :         << dx << "}\n\n\n";
    1063              : 
    1064              : 
    1065              :    // init method
    1066              : 
    1067            0 :   {
    1068            0 :     const char * ic_value = (
    1069            0 :       ( cl->direct_relationships() && cl->direct_relationships()->size() ) ||
    1070            0 :       ( cl->direct_super_classes() && cl->direct_super_classes()->size() )
    1071            0 :         ? "init_children"
    1072              :         : "/* init_children */"
    1073            0 :     );
    1074              : 
    1075            0 :     cpp_s
    1076              :       << dx << "void " << name << "::init(bool " << ic_value << ")\n"
    1077            0 :       << dx << "{\n";
    1078              :   }
    1079              : 
    1080            0 :   if (cl->direct_super_classes() == nullptr)
    1081              :     {
    1082            0 :       cpp_s
    1083              :         << dx << "  p_was_read = true;\n"
    1084            0 :         << dx << "  increment_read();\n";
    1085              :     }
    1086              : 
    1087              :     // generate initialization for super classes    
    1088              : 
    1089            0 :   if (const std::list<std::string*> * slist = cl->direct_super_classes())
    1090              :     {
    1091            0 :       for (const auto& i : *slist)
    1092              :         {
    1093            0 :           cpp_s << dx << "  " << alnum_name(*i) << "::init(init_children);\n";
    1094              :         }
    1095            0 :       if (!slist->empty())
    1096            0 :         cpp_s << std::endl;
    1097              :     }
    1098              : 
    1099            0 :   cpp_s << dx << "  TLOG_DEBUG(5) << \"read object \" << this << \" (class \" << s_class_name << \')\';\n";
    1100              : 
    1101              :     // put try / catch only if there are attributes or relationships to be initialized
    1102            0 :   const std::list<oks::OksAttribute*> *alist = cl->direct_attributes();
    1103            0 :   const std::list<oks::OksRelationship*> *rlist = cl->direct_relationships();
    1104              : 
    1105            0 :   if ((alist && !alist->empty()) || (rlist && !rlist->empty()))
    1106              :     {
    1107            0 :       cpp_s << std::endl << dx << "  try {\n";
    1108              : 
    1109              : 
    1110              :       // generate initialization for attributes
    1111            0 :       if (alist)
    1112              :         {
    1113            0 :           for (const auto& i : *alist)
    1114              :             {
    1115            0 :               const std::string cpp_name = alnum_name(i->get_name());
    1116            0 :               cpp_s << dx << "    p_obj.get(s_" << cpp_name << ", m_" << cpp_name << ");\n";
    1117            0 :             }
    1118              :         }
    1119              : 
    1120              : 
    1121              :       // generate initialization for relationships
    1122            0 :       if (rlist)
    1123              :         {
    1124            0 :           for (const auto& i : *rlist)
    1125              :             {
    1126            0 :               const std::string& rname = i->get_name();
    1127            0 :               std::string cpp_name = alnum_name(rname);
    1128            0 :               std::string rcname = get_full_cpp_class_name(i->get_class_type(), cl_info, cpp_ns_name);
    1129            0 :               if (i->get_high_cardinality_constraint() == oks::OksRelationship::Many)
    1130              :                 {
    1131            0 :                   cpp_s << dx << "    p_registry._ref<" << rcname << ">(p_obj, s_" << cpp_name << ", " << "m_" << cpp_name << ", init_children);\n";
    1132              :                 }
    1133              :               else
    1134              :                 {
    1135            0 :                   cpp_s << dx << "    m_" << cpp_name << " = p_registry._ref<" << rcname << ">(p_obj, s_" << cpp_name << ", init_children);\n";
    1136              :                 }
    1137            0 :             }
    1138              :         }
    1139              : 
    1140            0 :       cpp_s
    1141              :         << dx << "  }\n"
    1142              :         << dx << "  catch (dunedaq::conffwk::Exception & ex) {\n"
    1143              :         << dx << "    throw_init_ex(ex);\n"
    1144            0 :         << dx << "  }\n";
    1145              : 
    1146              :     }
    1147              : 
    1148            0 :   cpp_s << dx << "}\n\n";
    1149              : 
    1150              : 
    1151              :     // destructor
    1152              : 
    1153            0 :   cpp_s
    1154              :     << dx << name << "::~" << name << "() noexcept\n"
    1155              :     << dx << "{\n"
    1156            0 :     << dx << "}\n\n";
    1157              : 
    1158            0 :   cpp_s
    1159              :     << dx << "std::vector<const dunedaq::conffwk::DalObject *> " << name << "::get(const std::string& name, bool upcast_unregistered) const\n"
    1160              :     << dx << "{\n"
    1161              :     << dx << "  std::vector<const dunedaq::conffwk::DalObject *> vec;\n\n"
    1162              :     << dx << "  if (!get(name, vec, upcast_unregistered, true))\n"
    1163              :     << dx << "    throw_get_ex(name, s_class_name, this);\n\n"
    1164              :     << dx << "  return vec;\n"
    1165            0 :     << dx << "}\n\n";
    1166              : 
    1167            0 :   cpp_s
    1168              :     << dx << "bool " << name << "::get(const std::string& name, std::vector<const dunedaq::conffwk::DalObject *>& vec, bool upcast_unregistered, bool first_call) const\n"
    1169              :     << dx << "{\n"
    1170              :     << dx << "  if (first_call)\n"
    1171              :     << dx << "    {\n"
    1172              :     << dx << "      std::lock_guard scoped_lock(m_mutex);\n\n"
    1173              :     << dx << "      check();\n"
    1174              :     << dx << "      check_init();\n\n"
    1175              :     << dx << "      if (get_rel_objects(name, upcast_unregistered, vec))\n"
    1176              :     << dx << "        return true;\n"
    1177            0 :     << dx << "    }\n\n";
    1178              : 
    1179              : 
    1180            0 :   for (const auto &prototype : algo_n_set)
    1181            0 :     cpp_s
    1182              :       << dx << "  if (name == \"" << prototype << "()\")\n"
    1183              :       << dx << "    {\n"
    1184              :       << dx << "      p_registry.downcast_dal_objects(" << prototype << "(), upcast_unregistered, vec);\n"
    1185              :       << dx << "      return true;\n"
    1186            0 :       << dx << "    }\n\n";
    1187              : 
    1188            0 :   for (const auto &prototype : algo_1_set)
    1189            0 :     cpp_s
    1190              :       << dx << "  if (name == \"" << prototype << "()\")\n"
    1191              :       << dx << "    {\n"
    1192              :       << dx << "      p_registry.downcast_dal_object(" << prototype << "(), upcast_unregistered, vec);\n"
    1193              :       << dx << "      return true;\n"
    1194            0 :       << dx << "    }\n\n";
    1195              : 
    1196              : 
    1197            0 :   if (const std::list<std::string*> * slist = cl->direct_super_classes())
    1198              :     {
    1199            0 :       for (const auto& i : *slist)
    1200              :         {
    1201            0 :           cpp_s << dx << "  if (" << alnum_name(*i) << "::get(name, vec, upcast_unregistered, false)) return true;\n";
    1202              :         }
    1203              : 
    1204            0 :       cpp_s << "\n";
    1205              :     }
    1206              : 
    1207            0 :   cpp_s
    1208              :     << dx << "  if (first_call)\n"
    1209              :     << dx << "    return get_algo_objects(name, vec);\n\n"
    1210              :     << dx << "  return false;\n"
    1211            0 :     << dx << "}\n\n";
    1212              : 
    1213              : 
    1214              :       // generate relationship set methods
    1215              : 
    1216            0 :   if (const std::list<oks::OksRelationship*> *rlist = cl->direct_relationships())
    1217              :     {
    1218            0 :       for (const auto& i : *rlist)
    1219              :         {
    1220            0 :           const std::string rname(alnum_name(i->get_name()));
    1221            0 :           std::string full_cpp_class_name = get_full_cpp_class_name(i->get_class_type(), cl_info, cpp_ns_name);
    1222              : 
    1223            0 :           cpp_s << dx << "void " << name << "::set_" << rname << "(const ";
    1224              : 
    1225            0 :           if (i->get_high_cardinality_constraint() == oks::OksRelationship::Many)
    1226              :             {
    1227            0 :               cpp_s
    1228              :                 << "std::vector<const " << full_cpp_class_name << "*>& value)\n"
    1229              :                 << dx << "{\n"
    1230              :                 << dx << "  _set_objects(s_" << rname << ", value);\n"
    1231            0 :                 << dx << "}\n\n";
    1232              :             }
    1233              :           else
    1234              :             {
    1235            0 :               cpp_s
    1236              :                 << full_cpp_class_name << " * value)\n"
    1237              :                 << dx << "{\n"
    1238              :                 << dx << "  _set_object(s_" << rname << ", value);\n"
    1239            0 :                 << dx << "}\n\n";
    1240              :             }
    1241            0 :         }
    1242              :     }
    1243              : 
    1244              : 
    1245              :     // generate methods for c++
    1246              : 
    1247            0 :   if (const std::list<oks::OksMethod*> * mlist = cl->direct_methods())
    1248              :     {
    1249            0 :       bool comment_is_printed = false;
    1250            0 :       for (const auto& i : *mlist)
    1251              :         {
    1252            0 :           oks::OksMethodImplementation * mi = find_cpp_method_implementation(i);
    1253              : 
    1254            0 :           if (mi && !get_method_implementation_body(mi).empty())
    1255              :             {
    1256            0 :               if (comment_is_printed == false)
    1257              :                 {
    1258            0 :                   cpp_s << dx << "    // user-defined algorithms\n\n";
    1259              :                   comment_is_printed = true;
    1260              :                 }
    1261              : 
    1262              :               // generate description
    1263              : 
    1264            0 :               print_description(cpp_s, i->get_description(), dx2);
    1265              : 
    1266              :               // generate prototype
    1267              : 
    1268            0 :               std::string prototype(mi->get_prototype());
    1269            0 :               std::string::size_type idx = prototype.find('(');
    1270              : 
    1271            0 :               if (idx != std::string::npos)
    1272              :                 {
    1273            0 :                   idx--;
    1274              : 
    1275              :                   // skip spaces between method name and ()
    1276              : 
    1277            0 :                   while (isspace(prototype[idx]) && idx > 0)
    1278            0 :                     idx--;
    1279              : 
    1280              :                   // find beginning of the method name
    1281              : 
    1282            0 :                   while ((isalnum(prototype[idx]) || prototype[idx] == '_') && idx > 0)
    1283            0 :                     idx--;
    1284              : 
    1285            0 :                   prototype[idx] = '\n';
    1286            0 :                   std::string s(dx);
    1287            0 :                   s += alnum_name(name);
    1288            0 :                   s += "::";
    1289            0 :                   prototype.insert(idx + 1, s);
    1290            0 :                 }
    1291              : 
    1292              :               // Second pass
    1293            0 :               std::string::size_type idx_open_bracket = prototype.find('(');
    1294            0 :               std::string::size_type idx_space = prototype.rfind(' ', idx_open_bracket);
    1295            0 :               std::string::size_type idx_close_bracket = prototype.rfind(')');
    1296              :             
    1297            0 :               auto prototype_attrs = prototype.substr(0,idx_space+1);
    1298            0 :               auto prototype_head = prototype.substr(idx_space+1,idx_close_bracket-idx_space);
    1299            0 :               auto prototype_specs = prototype.substr(idx_close_bracket+1);
    1300              : 
    1301            0 :               for ( const auto& spec : cpp_method_virtual_specifiers ) {
    1302            0 :                   idx = prototype_attrs.find(spec);
    1303            0 :                   if ( idx != std::string::npos) {
    1304            0 :                       prototype_attrs.erase(idx,spec.size());
    1305              :                   }
    1306            0 :                   prototype_attrs = trim(prototype_attrs);
    1307              :                                     
    1308            0 :                   idx = prototype_specs.find(spec);
    1309            0 :                   if ( idx != std::string::npos) {
    1310            0 :                       prototype_specs.erase(idx,spec.size());
    1311              :                   }
    1312            0 :                   prototype_specs = trim(prototype_specs);
    1313              :               }
    1314              : 
    1315            0 :               prototype = prototype_attrs + ' ' + prototype_head + ' ' + prototype_specs;
    1316              : 
    1317            0 :               cpp_s
    1318            0 :                 << dx << prototype << std::endl
    1319              :                 << dx << "{\n"
    1320            0 :                 << get_method_implementation_body(mi) << std::endl
    1321            0 :                 << dx << "}\n\n";
    1322            0 :             }
    1323              :         }
    1324              :     }
    1325              : 
    1326              : 
    1327              :     // close namespace
    1328              : 
    1329            0 :   close_cpp_namespace(cpp_s, ns_level);
    1330            0 : }
    1331              : 
    1332              : static void
    1333            0 : load_schemas(oks::OksKernel& kernel, const std::list<std::string>& file_names, std::set<oks::OksFile *, std::less<oks::OksFile *> >& file_hs)
    1334              : {
    1335            0 :   for (const auto& i : file_names)
    1336              :     {
    1337            0 :       if (oks::OksFile * fh = kernel.load_schema(i))
    1338              :         {
    1339            0 :           file_hs.insert(fh);
    1340              :         }
    1341              :       else
    1342              :         {
    1343            0 :           std::cerr << "ERROR: can not load schema file \"" << i << "\"\n";
    1344            0 :           exit(EXIT_FAILURE);
    1345              :         }
    1346              :     }
    1347            0 : }
    1348              : 
    1349              : static void
    1350            0 : gen_cpp_header_prologue(const std::string& file_name,
    1351              :                         std::ostream& s,
    1352              :                         const std::string& cpp_ns_name,
    1353              :                         const std::string& cpp_hdr_dir)
    1354              : {
    1355            0 :   s <<
    1356              :     "// *** this file is generated by oksdalgen, do not modify it ***\n\n"
    1357              : 
    1358            0 :     "#ifndef _" << alnum_name(file_name) << "_0_" << alnum_name(cpp_ns_name) << "_0_" << alnum_name(cpp_hdr_dir) << "_H_\n"
    1359            0 :     "#define _" << alnum_name(file_name) << "_0_" << alnum_name(cpp_ns_name) << "_0_" << alnum_name(cpp_hdr_dir) << "_H_\n\n"
    1360              : 
    1361              :     "#include <stdint.h>   // to define 64 bits types\n"
    1362              :     "#include <iostream>\n"
    1363              :     "#include <sstream>\n"
    1364              :     "#include <string>\n"
    1365              :     "#include <map>\n"
    1366              :     "#include <vector>\n\n"
    1367              : 
    1368              :     "#include \"conffwk/Configuration.hpp\"\n"
    1369            0 :     "#include \"conffwk/DalObject.hpp\"\n\n";
    1370            0 : }
    1371              : 
    1372              : 
    1373              : static void
    1374            0 : gen_cpp_header_epilogue(std::ostream& s)
    1375              : {
    1376            0 :   s << "\n#endif\n";
    1377            0 : }
    1378              : 
    1379              : 
    1380              : static void
    1381            0 : gen_cpp_body_prologue(const std::string& file_name,
    1382              :                       std::ostream& src,
    1383              :                       const std::string& cpp_hdr_dir)
    1384              : {
    1385            0 :   src <<
    1386              :     "#include \"conffwk/ConfigObject.hpp\"\n"
    1387              :     "#include \"conffwk/DalFactory.hpp\"\n"
    1388              :     "#include \"conffwk/DalObjectPrint.hpp\"\n"
    1389              :     "#include \"conffwk/Errors.hpp\"\n"
    1390            0 :     "#include \"";
    1391            0 :     if(cpp_hdr_dir != "") {
    1392            0 :       src <<  cpp_hdr_dir << "/";
    1393              :     }
    1394            0 :     src << file_name << ".hpp\"\n\n";
    1395            0 : }
    1396              : 
    1397              : 
    1398              : int
    1399            0 : main(int argc, char *argv[])
    1400              : {
    1401            0 :   std::list<std::string> class_names;
    1402            0 :   std::list<std::string> file_names;
    1403            0 :   std::list<std::string> include_dirs;
    1404            0 :   std::list<std::string> user_classes;
    1405              : 
    1406            0 :   std::string cpp_dir_name = ".";                // directory for c++ implementation files
    1407            0 :   std::string cpp_hdr_dir = "";                  // directory for c++ header files
    1408            0 :   std::string cpp_ns_name = "";                  // c++ namespace
    1409            0 :   std::string info_file_name = "oksdalgen.info"; // name of info file
    1410            0 :   bool verbose = false;
    1411              : 
    1412            0 :   parse_arguments(argc, argv, class_names, file_names, include_dirs, user_classes, cpp_dir_name, cpp_ns_name, cpp_hdr_dir, info_file_name, verbose);
    1413              : 
    1414              :   // init OKS
    1415              : 
    1416            0 :   std::set<oks::OksFile *, std::less<oks::OksFile *> > file_hs;
    1417              : 
    1418            0 :   oks::OksKernel kernel(false, false, false, false);
    1419              : 
    1420            0 :   try
    1421              :     {
    1422            0 :       load_schemas(kernel, file_names, file_hs);
    1423              : 
    1424              :       // if no user defined classes, generate all
    1425              : 
    1426            0 :       if (class_names.size() == 0)
    1427              :         {
    1428            0 :           if (verbose)
    1429              :             {
    1430            0 :               std::cout << "No explicit classes were provided,\n"
    1431            0 :                   "search for classes which belong to the given schema files:\n";
    1432              :             }
    1433              : 
    1434            0 :           const oks::OksClass::Map& class_list = kernel.classes();
    1435              : 
    1436            0 :           if (!class_list.empty())
    1437              :             {
    1438            0 :               for (const auto& i : class_list)
    1439              :                 {
    1440            0 :                   if (verbose)
    1441              :                     {
    1442            0 :                       std::cout << " * check for class \"" << i.first << "\" ";
    1443              :                     }
    1444              : 
    1445            0 :                   if (file_hs.find(i.second->get_file()) != file_hs.end())
    1446              :                     {
    1447            0 :                       class_names.push_back(i.second->get_name());
    1448            0 :                       if (verbose)
    1449              :                         {
    1450            0 :                           std::cout << "OK\n";
    1451              :                         }
    1452              :                     }
    1453              :                   else
    1454              :                     {
    1455            0 :                       if (verbose)
    1456              :                         {
    1457            0 :                           std::cout << "skip\n";
    1458              :                         }
    1459              :                     }
    1460              :                 }
    1461              :             }
    1462              :           else
    1463              :             {
    1464            0 :               std::cerr << "No classes in schema file and no user classes specified\n";
    1465            0 :               exit(EXIT_FAILURE);
    1466              :             }
    1467              :         }
    1468              : 
    1469              :       // calculate set of classes which should be mentioned by the generator;
    1470              :       // note, some of classes can come from other DALs
    1471              : 
    1472            0 :       typedef std::set<const oks::OksClass *, std::less<const oks::OksClass *> > Set;
    1473            0 :       Set generated_classes;
    1474            0 :       ClassInfo::Map cl_info;
    1475              : 
    1476            0 :       unsigned int error_num = 0;
    1477              : 
    1478              :       // build set of classes which are generated
    1479              : 
    1480            0 :       for (const auto& i : class_names)
    1481              :         {
    1482            0 :           if (oks::OksClass *cl = kernel.find_class(i))
    1483              :             {
    1484            0 :               generated_classes.insert(cl);
    1485              :             }
    1486              :           else
    1487              :             {
    1488            0 :               std::cerr << "ERROR: can not find class " << i << std::endl;
    1489            0 :               error_num++;
    1490              :             }
    1491              :         }
    1492              : 
    1493              :       // build set of classes which are external to generated
    1494              : 
    1495            0 :       for (const auto& i : generated_classes)
    1496              :         {
    1497            0 :           if (const std::list<oks::OksRelationship *> * rels = i->direct_relationships())
    1498              :             {
    1499            0 :               for (const auto& j : *rels)
    1500              :                 {
    1501            0 :                   const oks::OksClass * rc = j->get_class_type();
    1502              : 
    1503            0 :                   if (rc == 0)
    1504              :                     {
    1505            0 :                       std::cerr << "\nERROR: the class \"" << j->get_type() << "\" (it is used by the relationship \"" << j->get_name() << "\" of class \"" << i->get_name() << "\") is not defined by the schema.\n";
    1506            0 :                       error_num++;
    1507              :                     }
    1508            0 :                   else if (generated_classes.find(rc) == generated_classes.end())
    1509              :                     {
    1510            0 :                       if (process_external_class(cl_info, rc, include_dirs, user_classes, verbose) == false)
    1511              :                         {
    1512            0 :                           std::cerr << "\nERROR: the class \"" << j->get_type() << "\" is used by the relationship \"" << j->get_name() << "\" of class \"" << i->get_name() << "\".\n"
    1513              :                               "       The class is not in the list of generated classes, "
    1514              :                               "it was not found among already generated headers "
    1515              :                               "(search list is defined by the -I | --include-dirs parameter) and "
    1516            0 :                               "it is not defined by user via -D | --user-defined-classes.\n";
    1517            0 :                           error_num++;
    1518              :                         }
    1519              :                     }
    1520              :                 }
    1521              :             }
    1522              : 
    1523            0 :           if (const std::list<std::string *> * sclasses = i->direct_super_classes())
    1524              :             {
    1525            0 :               for (const auto& j : *sclasses)
    1526              :                 {
    1527            0 :                   const oks::OksClass * rc = kernel.find_class(*j);
    1528              : 
    1529            0 :                   if (rc == 0)
    1530              :                     {
    1531            0 :                       std::cerr << "\nERROR: the class \"" << *j << "\" (it is direct superclass of class \"" << i->get_name() << "\") is not defined by the schema.\n";
    1532            0 :                       error_num++;
    1533              :                     }
    1534            0 :                   else if (generated_classes.find(rc) == generated_classes.end())
    1535              :                     {
    1536            0 :                       if (process_external_class(cl_info, rc, include_dirs, user_classes, verbose) == false)
    1537              :                         {
    1538            0 :                           std::cerr << "\nERROR: the class \"" << rc->get_name() << "\" is direct superclass of class \"" << i->get_name() << "\".\n"
    1539              :                               "       The class is not in the list of generated classes, "
    1540              :                               "it was not found among already generated headers "
    1541              :                               "(search list is defined by the -I | --include-dirs parameter) and "
    1542            0 :                               "it is not defined by user via -D | --user-defined-classes.\n";
    1543            0 :                           error_num++;
    1544              :                         }
    1545              :                     }
    1546              :                 }
    1547              :             }
    1548              :         }
    1549              : 
    1550            0 :       if (error_num != 0)
    1551              :         {
    1552            0 :           std::cerr << "\n*** " << error_num << (error_num == 1 ? " error was" : " errors were") << " found.\n\n";
    1553              :           return (EXIT_FAILURE);
    1554              :         }
    1555              : 
    1556            0 :       for (const auto& cl : generated_classes)
    1557              :         {
    1558            0 :           std::string name(alnum_name(cl->get_name()));
    1559              : 
    1560            0 :           std::string cpp_hdr_name = cpp_dir_name + "/" + name + ".hpp";
    1561            0 :           std::string cpp_src_name = cpp_dir_name + "/" + name + ".cpp";
    1562              : 
    1563            0 :           std::ofstream cpp_hdr_file(cpp_hdr_name.c_str());
    1564            0 :           std::ofstream cpp_src_file(cpp_src_name.c_str());
    1565              : 
    1566            0 :           if (!cpp_hdr_file)
    1567              :             {
    1568            0 :               std::cerr << "ERROR: can not create file \"" << cpp_hdr_name << "\"\n";
    1569              :               return (EXIT_FAILURE);
    1570              :             }
    1571              : 
    1572            0 :           if (!cpp_src_file)
    1573              :             {
    1574            0 :               std::cerr << "ERROR: can not create file \"" << cpp_src_name << "\"\n";
    1575              :               return (EXIT_FAILURE);
    1576              :             }
    1577              : 
    1578            0 :           gen_cpp_header_prologue(name, cpp_hdr_file, cpp_ns_name, cpp_hdr_dir);
    1579            0 :           gen_cpp_body_prologue(name, cpp_src_file, cpp_hdr_dir);
    1580              : 
    1581            0 :           gen_header(cl, cpp_hdr_file, cpp_ns_name, cpp_hdr_dir, cl_info);
    1582            0 :           gen_cpp_body(cl, cpp_src_file, cpp_ns_name, cpp_hdr_dir, cl_info);
    1583              : 
    1584            0 :           gen_cpp_header_epilogue(cpp_hdr_file);
    1585            0 :         }
    1586              : 
    1587              :       // generate dump applications
    1588              : 
    1589            0 :         {
    1590            0 :           struct ConfigurationImplementations
    1591              :           {
    1592              :             const char * name;
    1593              :             const char * header;
    1594              :             const char * class_name;
    1595              :             const char * header_prologue;
    1596              :             const char * main_function_prologue;
    1597            0 :           } confs[] =
    1598              :             {
    1599              :               { 0, "conffwk/Configuration.hpp", 0, "", "" } };
    1600              : 
    1601            0 :           for (unsigned int i = 0; i < sizeof(confs) / sizeof(ConfigurationImplementations); ++i)
    1602              :             {
    1603            0 :               std::string dump_name = cpp_dir_name + "/dump";
    1604            0 :               if (!cpp_ns_name.empty())
    1605              :                 {
    1606            0 :                   dump_name += '_';
    1607            0 :                   dump_name += alnum_name(cpp_ns_name);
    1608              :                 }
    1609            0 :               if (confs[i].name)
    1610              :                 {
    1611            0 :                   dump_name += '_';
    1612            0 :                   dump_name += confs[i].name;
    1613              :                 }
    1614            0 :               dump_name += ".cpp";
    1615              : 
    1616            0 :               std::ofstream dmp(dump_name.c_str());
    1617              : 
    1618            0 :               dmp.exceptions(std::ostream::failbit | std::ostream::badbit);
    1619              : 
    1620            0 :               if (dmp)
    1621              :                 {
    1622            0 :                   try
    1623              :                     {
    1624            0 :                       gen_dump_application(dmp, class_names, cpp_ns_name, cpp_hdr_dir, confs[i].header, confs[i].class_name, confs[i].header_prologue, confs[i].main_function_prologue);
    1625              :                     }
    1626            0 :                   catch (std::exception& ex)
    1627              :                     {
    1628            0 :                       std::cerr << "ERROR: can not create file \"" << dump_name << "\": " << ex.what() << std::endl;
    1629            0 :                     }
    1630              :                 }
    1631              :               else
    1632              :                 {
    1633            0 :                   std::cerr << "ERROR: can not create file \"" << dump_name << "\"\n";
    1634            0 :                   return (EXIT_FAILURE);
    1635              :                 }
    1636            0 :             }
    1637              :         }
    1638              : 
    1639              :       // generate info file
    1640              : 
    1641            0 :         {
    1642            0 :           std::ofstream info(info_file_name.c_str());
    1643              : 
    1644            0 :           if (info)
    1645              :             {
    1646            0 :               write_info_file(info, cpp_ns_name, cpp_hdr_dir, generated_classes);
    1647              :             }
    1648              :           else
    1649              :             {
    1650            0 :               std::cerr << "ERROR: can not create file \"" << info_file_name << "\"\n";
    1651            0 :               return (EXIT_FAILURE);
    1652              :             }
    1653            0 :         }
    1654              : 
    1655            0 :     }
    1656            0 :   catch (oks::exception & ex)
    1657              :     {
    1658            0 :       std::cerr << "Caught oks exception:\n" << ex << std::endl;
    1659            0 :       return (EXIT_FAILURE);
    1660            0 :     }
    1661            0 :   catch (std::exception & e)
    1662              :     {
    1663            0 :       std::cerr << "Caught standard C++ exception: " << e.what() << std::endl;
    1664            0 :       return (EXIT_FAILURE);
    1665            0 :     }
    1666            0 :   catch (...)
    1667              :     {
    1668            0 :       std::cerr << "Caught unknown exception" << std::endl;
    1669            0 :       return (EXIT_FAILURE);
    1670            0 :     }
    1671              : 
    1672            0 :   return (EXIT_SUCCESS);
    1673            0 : }
    1674              : 
        

Generated by: LCOV version 2.0-1