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: 2025-12-21 13:07:08 Functions: 0.0 % 12 0

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

Generated by: LCOV version 2.0-1