LCOV - code coverage report
Current view: top level - src/error - exporterrors.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 351 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include "parser.hpp"
      10             : 
      11             : #include <algorithm>
      12             : #include <fstream>
      13             : #include <iostream>
      14             : 
      15             : #ifndef _WIN32
      16             : #include <errno.h>
      17             : #include <fcntl.h>
      18             : #include <stdio.h>
      19             : #include <string.h>
      20             : #include <sys/stat.h>
      21             : #include <sys/types.h>
      22             : #include <unistd.h>
      23             : #endif
      24             : 
      25             : using namespace std;
      26             : 
      27           0 : static ostream & printKDBErrors (ostream & os, parse_t & p)
      28             : {
      29           0 :         os << "/*This is an auto-generated file generated by exporterrors. Do not modify it.*/" << endl
      30           0 :            << endl
      31           0 :            << "#ifndef KDBERRORS_H" << endl
      32           0 :            << "#define KDBERRORS_H" << endl
      33           0 :            << endl
      34           0 :            << "#include <kdb.h>" << endl
      35           0 :            << "#include <kdbhelper.h>" << endl
      36           0 :            << "#include <kdblogger.h>" << endl
      37           0 :            << "#include <kdbmacros.h>" << endl
      38           0 :            << "#include <string.h>" << endl
      39           0 :            << endl
      40           0 :            << "#ifdef __cplusplus" << endl
      41           0 :            << "using namespace ckdb;" << endl
      42           0 :            << "#endif" << endl;
      43           0 :         os << endl << endl;
      44             : 
      45           0 :         for (size_t i = 1; i < p.size (); ++i)
      46             :         {
      47           0 :                 os << "#define ELEKTRA_SET_" << p[i]["macro"] << "_ERROR(key, text) \\" << endl
      48           0 :                    << "\tdo { ELEKTRA_LOG (\"Add Error " << p[i]["number"] << ": %s\", text); elektraSetError" << p[i]["number"]
      49           0 :                    << "(key, text, __FILE__, ELEKTRA_STRINGIFY(__LINE__), ELEKTRA_STRINGIFY(ELEKTRA_MODULE_NAME)); } while (0)" << endl;
      50           0 :                 os << "#define ELEKTRA_SET_" << p[i]["macro"] << "_ERRORF(key, text, ...) \\" << endl
      51           0 :                    << "\tdo { ELEKTRA_LOG (\"Add Error " << p[i]["number"] << ": \" text, __VA_ARGS__); elektraSetErrorf" << p[i]["number"]
      52           0 :                    << "(key, text, __FILE__, ELEKTRA_STRINGIFY(__LINE__), ELEKTRA_STRINGIFY(ELEKTRA_MODULE_NAME), __VA_ARGS__); } while (0)"
      53           0 :                    << endl;
      54             : 
      55           0 :                 os << "#define ELEKTRA_ADD_" << p[i]["macro"] << "_WARNING(key, text) \\" << endl
      56           0 :                    << "\tdo { ELEKTRA_LOG (\"Add Warning " << p[i]["number"] << ": %s\", text); elektraAddWarning" << p[i]["number"]
      57           0 :                    << "(key, text, __FILE__, ELEKTRA_STRINGIFY(__LINE__), ELEKTRA_STRINGIFY(ELEKTRA_MODULE_NAME)); } while (0)" << endl;
      58           0 :                 os << "#define ELEKTRA_ADD_" << p[i]["macro"] << "_WARNINGF(key, text, ...) \\" << endl
      59           0 :                    << "\tdo { ELEKTRA_LOG (\"Add Warning " << p[i]["number"] << ": \" text, __VA_ARGS__); elektraAddWarningf"
      60           0 :                    << p[i]["number"]
      61           0 :                    << "(key, text, __FILE__, ELEKTRA_STRINGIFY(__LINE__), ELEKTRA_STRINGIFY(ELEKTRA_MODULE_NAME), __VA_ARGS__); } while (0)"
      62           0 :                    << endl;
      63             : 
      64           0 :                 os << endl;
      65             :         }
      66           0 :         os << endl;
      67             : 
      68           0 :         for (size_t i = 1; i < p.size (); ++i)
      69             :         {
      70           0 :                 if (p[i]["unused"] == "yes")
      71             :                 {
      72             :                         continue;
      73             :                 }
      74             : 
      75           0 :                 if (p[i]["macro"].empty ())
      76             :                 {
      77           0 :                         throw invalid_argument ("Error with number " + p[i]["number"] + " does not have a mandatory macro.");
      78             :                 }
      79             : 
      80           0 :                 os << "#define ELEKTRA_WARNING_" << p[i]["macro"] << " \"" << p[i]["number"] << "\"" << endl;
      81           0 :                 os << "#define ELEKTRA_ERROR_" << p[i]["macro"] << " \"" << p[i]["number"] << "\"" << endl;
      82             :         }
      83             : 
      84           0 :         os << endl << endl;
      85             : 
      86           0 :         for (size_t i = 1; i < p.size (); ++i)
      87             :         {
      88             : 
      89           0 :                 for (int f = 0; f < 2; ++f)
      90             :                 {
      91           0 :                         if (f == 0)
      92             :                         {
      93           0 :                                 os << "static inline void elektraAddWarningf" << p[i]["number"] << "(Key *warningKey, const char *reason,"
      94           0 :                                    << endl
      95             :                                    << "      const char *file, const char *line, const char *module, ...)  __attribute__ ((format (printf, 2, "
      96           0 :                                       "6)));"
      97           0 :                                    << endl;
      98           0 :                                 os << "static inline void elektraAddWarningf" << p[i]["number"] << "(Key *warningKey, const char *reason,"
      99           0 :                                    << endl
     100           0 :                                    << "      const char *file, const char *line, const char *module, ...)" << endl;
     101             :                         }
     102             :                         else
     103             :                         {
     104           0 :                                 os << "static inline void elektraAddWarning" << p[i]["number"] << "(Key *warningKey, const char *reason,"
     105           0 :                                    << endl
     106           0 :                                    << "      const char *file, const char *line, const char *module)" << endl;
     107             :                         }
     108           0 :                         os << "{" << endl
     109           0 :                            << "      if (!warningKey) return;" << endl
     110           0 :                            << "" << endl
     111           0 :                            << "      char buffer[25] = \"warnings/#00\";buffer[12] = '\\0';" << endl
     112           0 :                            << "      const Key *meta = keyGetMeta(warningKey, \"warnings\");" << endl
     113           0 :                            << "      if (meta)" << endl
     114           0 :                            << "      {" << endl
     115           0 :                            << "              buffer[10] = keyString(meta)[0];" << endl
     116           0 :                            << "              buffer[11] = keyString(meta)[1];" << endl
     117           0 :                            << "              buffer[11]++;" << endl
     118           0 :                            << "              if (buffer[11] > '9')" << endl
     119           0 :                            << "              {" << endl
     120           0 :                            << "                      buffer[11] = '0';" << endl
     121           0 :                            << "                      buffer[10]++;" << endl
     122           0 :                            << "                      if (buffer[10] > '9') buffer[10] = '0';" << endl
     123           0 :                            << "              }" << endl
     124           0 :                            << "              keySetMeta(warningKey, \"warnings\", &buffer[10]);" << endl
     125           0 :                            << "      } else  keySetMeta(warningKey, \"warnings\", \"00\");" << endl
     126           0 :                            << "" << endl
     127           0 :                            << "      keySetMeta(warningKey, buffer, \"number description  module file line function reason\");" << endl
     128           0 :                            << "      strcat(buffer, \"/number\" );" << endl
     129           0 :                            << "      keySetMeta(warningKey, buffer, \"" << p[i]["number"] << "\");" << endl
     130           0 :                            << "      buffer[12] = '\\0'; strcat(buffer, \"/description\");" << endl
     131           0 :                            << "      keySetMeta(warningKey, buffer, \"" << p[i]["description"] << "\");" << endl
     132           0 :                            << "      buffer[12] = '\\0'; strcat(buffer, \"/module\");"
     133           0 :                            << endl
     134             :                            // TODO: Not the best implementation, fix if better way is found
     135           0 :                            << "      if (strcmp(module, \"ELEKTRA_MODULE_NAME\") == 0) module = \"kdb\";" << endl
     136           0 :                            << "      keySetMeta(warningKey, buffer, module);" << endl
     137           0 :                            << "      buffer[12] = '\\0'; strcat(buffer, \"/file\");" << endl // should be called sourcefile
     138           0 :                            << "      keySetMeta(warningKey, buffer, file);" << endl
     139           0 :                            << "      buffer[12] = '\\0'; strcat(buffer, \"/line\");" << endl
     140           0 :                            << "      keySetMeta(warningKey, buffer, line);" << endl
     141           0 :                            << "      buffer[12] = '\\0'; strcat(buffer, \"/mountpoint\");" << endl
     142           0 :                            << "      keySetMeta(warningKey, buffer, keyName(warningKey));" << endl
     143           0 :                            << "      buffer[12] = '\\0'; strcat(buffer, \"/configfile\");" << endl
     144           0 :                            << "      keySetMeta(warningKey, buffer, keyString(warningKey));" << endl
     145           0 :                            << "      buffer[12] = '\\0'; strcat(buffer, \"/reason\");" << endl;
     146           0 :                         if (f == 0)
     147             :                         {
     148           0 :                                 os << "      va_list arg;" << endl
     149           0 :                                    << "      va_start(arg, module);" << endl
     150           0 :                                    << "      char * r = elektraVFormat(reason, arg);" << endl
     151           0 :                                    << "      keySetMeta(warningKey, buffer, r);" << endl
     152           0 :                                    << "      elektraFree(r);" << endl
     153           0 :                                    << "      va_end(arg);" << endl;
     154             :                         }
     155             :                         else
     156             :                         {
     157           0 :                                 os << "      keySetMeta(warningKey, buffer, reason);" << endl;
     158             :                         }
     159           0 :                         os << "}" << endl << endl;
     160             :                 }
     161             : 
     162           0 :                 for (int f = 0; f < 2; ++f)
     163             :                 {
     164           0 :                         if (f == 0)
     165             :                         {
     166           0 :                                 os << "static inline void elektraSetErrorf" << p[i]["number"] << "(Key *errorKey, const char *reason,"
     167           0 :                                    << endl
     168             :                                    << "      const char *file, const char *line, const char *module, ...)  __attribute__ ((format (printf, 2, "
     169           0 :                                       "6)));"
     170           0 :                                    << endl
     171           0 :                                    << "static inline void elektraSetErrorf" << p[i]["number"] << "(Key *errorKey, const char *reason,"
     172           0 :                                    << endl
     173           0 :                                    << "      const char *file, const char *line, const char *module, ...)" << endl;
     174             :                         }
     175             :                         else
     176             :                         {
     177           0 :                                 os << "static inline void elektraSetError" << p[i]["number"] << "(Key *errorKey, const char *reason,"
     178           0 :                                    << endl
     179           0 :                                    << "      const char *file, const char *line, const char *module)" << endl;
     180             :                         }
     181           0 :                         os << "{" << endl
     182           0 :                            << "      if (!errorKey) return;" << endl
     183           0 :                            << "      char buffer[25] = \"warnings/#00\";" << endl
     184           0 :                            << "      const Key *meta = keyGetMeta(errorKey, \"error\");" << endl
     185           0 :                            << "      if (meta)" << endl
     186           0 :                            << "      {" << endl
     187           0 :                            << "              const Key *warningMeta = keyGetMeta(errorKey, \"warnings\");" << endl
     188           0 :                            << "              if (warningMeta)" << endl
     189           0 :                            << "              {" << endl
     190           0 :                            << "                      buffer[10] = keyString(warningMeta)[0];" << endl
     191           0 :                            << "                      buffer[11] = keyString(warningMeta)[1];" << endl
     192           0 :                            << "                      buffer[11]++;" << endl
     193           0 :                            << "                      if (buffer[11] > '9')" << endl
     194           0 :                            << "                      {" << endl
     195           0 :                            << "                              buffer[11] = '0';" << endl
     196           0 :                            << "                              buffer[10]++;" << endl
     197           0 :                            << "                              if (buffer[10] > '9') buffer[10] = '0';" << endl
     198           0 :                            << "                      }" << endl
     199           0 :                            << "                      keySetMeta(errorKey, \"warnings\", &buffer[10]);" << endl
     200           0 :                            << "              } else  keySetMeta(errorKey, \"warnings\", \"00\");" << endl
     201             :                            << "              keySetMeta(errorKey, buffer, \"number description  module file line function "
     202           0 :                               "reason\");"
     203           0 :                            << endl
     204           0 :                            << "              strcat(buffer, \"/number\" );" << endl
     205           0 :                            << "              keySetMeta(errorKey, buffer, \"" << p[i]["number"] << "\");" << endl
     206           0 :                            << "              buffer[12] = '\\0'; strcat(buffer, \"/description\");" << endl
     207           0 :                            << "              keySetMeta(errorKey, buffer, \"" << p[i]["description"] << "\");" << endl
     208           0 :                            << "              buffer[12] = '\\0'; strcat(buffer, \"/module\");"
     209           0 :                            << endl
     210             :                            // TODO: Not the best implementation, fix if better way is found
     211           0 :                            << "              if (strcmp(module, \"ELEKTRA_MODULE_NAME\") == 0) module = \"kdb\";" << endl
     212           0 :                            << "              keySetMeta(errorKey, buffer, module);" << endl
     213           0 :                            << "              buffer[12] = '\\0'; strcat(buffer, \"/file\");" << endl // should be called sourcefile
     214           0 :                            << "              keySetMeta(errorKey, buffer, file);" << endl
     215           0 :                            << "              buffer[12] = '\\0'; strcat(buffer, \"/line\");" << endl
     216           0 :                            << "              keySetMeta(errorKey, buffer, line);" << endl
     217           0 :                            << "              buffer[12] = '\\0'; strcat(buffer, \"/mountpoint\");" << endl
     218           0 :                            << "              keySetMeta(errorKey, buffer, keyName(errorKey));" << endl
     219           0 :                            << "              buffer[12] = '\\0'; strcat(buffer, \"/configfile\");" << endl
     220           0 :                            << "              keySetMeta(errorKey, buffer, keyString(errorKey));" << endl
     221           0 :                            << "              buffer[12] = '\\0'; strcat(buffer, \"/reason\");" << endl
     222           0 :                            << "      }" << endl
     223           0 :                            << "      else" << endl
     224           0 :                            << "      {" << endl
     225             :                            << "              keySetMeta(errorKey, \"error\", \""
     226             :                            << "number description  module file line function reason"
     227           0 :                            << "\");" << endl
     228           0 :                            << "              keySetMeta(errorKey, \"error/number\", \"" << p[i]["number"] << "\");" << endl
     229           0 :                            << "              keySetMeta(errorKey, \"error/description\", \"" << p[i]["description"] << "\");"
     230           0 :                            << endl
     231             :                            // TODO: Not the best implementation, fix if better way is found
     232           0 :                            << "              if (strcmp(module, \"ELEKTRA_MODULE_NAME\") == 0) module = \"kdb\";" << endl
     233           0 :                            << "              keySetMeta(errorKey, \"error/module\", module);" << endl
     234             :                            << "              keySetMeta(errorKey, \"error/file\", "
     235             :                            << "file"
     236           0 :                            << ");" << endl
     237             :                            << "              keySetMeta(errorKey, \"error/line\", "
     238             :                            << "line"
     239           0 :                            << ");" << endl
     240             :                            << "              keySetMeta(errorKey, \"error/mountpoint\", "
     241             :                            << "keyName(errorKey)"
     242           0 :                            << ");" << endl
     243             :                            << "              keySetMeta(errorKey, \"error/configfile\", "
     244             :                            << "keyString(errorKey)"
     245           0 :                            << ");" << endl
     246           0 :                            << "      }" << endl;
     247           0 :                         if (f == 0)
     248             :                         {
     249           0 :                                 os << "      va_list arg;" << endl
     250           0 :                                    << "      va_start(arg, module);" << endl
     251           0 :                                    << "      char * r = elektraVFormat(reason, arg);" << endl
     252           0 :                                    << "      if (meta)" << endl
     253           0 :                                    << "                      keySetMeta(errorKey, buffer, r);" << endl
     254           0 :                                    << "      else" << endl
     255             :                                    << "                      keySetMeta(errorKey, \"error/reason\", "
     256             :                                    << "r"
     257           0 :                                    << ");" << endl
     258           0 :                                    << "      elektraFree(r);" << endl
     259           0 :                                    << "      va_end(arg);" << endl;
     260             :                         }
     261             :                         else
     262             :                         {
     263           0 :                                 os << "      if (meta)" << endl
     264           0 :                                    << "                      keySetMeta(errorKey, buffer, reason);" << endl
     265           0 :                                    << "      else" << endl
     266           0 :                                    << "                      keySetMeta(errorKey, \"error/reason\", reason);" << endl;
     267             :                         }
     268           0 :                         os << "}" << endl << endl;
     269             :                 }
     270             :         }
     271             : 
     272           0 :         os << "static inline KeySet *elektraErrorSpecification (void)" << endl
     273           0 :            << "{" << endl
     274           0 :            << "      return ksNew (30," << endl
     275           0 :            << "              keyNew (\"system/elektra/modules/error/specification\"," << endl
     276           0 :            << "                      KEY_VALUE, \"the specification of all error codes\", KEY_END)," << endl;
     277           0 :         for (size_t i = 1; i < p.size (); ++i)
     278             :         {
     279           0 :                 os << "              keyNew (\"system/elektra/modules/error/specification/" << p[i]["number"] << "\"," << endl
     280           0 :                    << "                      KEY_END)," << endl
     281           0 :                    << "              keyNew (\"system/elektra/modules/error/specification/" << p[i]["number"] << "/description\"," << endl
     282           0 :                    << "                      KEY_VALUE, \"" << p[i]["description"] << "\", KEY_END)," << endl;
     283             :                 //                 << "              keyNew (\"system/elektra/modules/error/specification/" << p[i]["number"] << "/severity\","
     284             :                 //<<
     285             :                 // endl
     286             :                 //                 << "                      KEY_VALUE, \"" << p[i]["severity"] << "\", KEY_END)," << endl
     287             :                 //                 << "              keyNew (\"system/elektra/modules/error/specification/" << p[i]["number"] << "/module\"," <<
     288             :                 // endl
     289             :                 //                 << "                      KEY_VALUE, \"" << p[i]["module"] << "\", KEY_END)," << endl;
     290             :         }
     291           0 :         os << "              KS_END);" << endl << "}" << endl;
     292             : 
     293           0 :         os << "static inline void elektraTriggerWarnings (const char *nr, Key *parentKey, const char *message)" << endl << "{" << endl;
     294           0 :         for (size_t i = 1; i < p.size (); ++i)
     295             :         {
     296           0 :                 os << "      if (strcmp(nr, \"" << p[i]["number"] << "\") == 0)" << endl << "        {" << endl;
     297           0 :                 os << "              ELEKTRA_ADD_" << p[i]["macro"] << "_WARNING (parentKey, message);" << endl
     298           0 :                    << "              return;" << endl
     299           0 :                    << "      }" << endl;
     300             :         }
     301           0 :         os << "      ELEKTRA_ADD_INTERNAL_WARNINGF (parentKey, \"Unkown warning code %s\", nr);" << endl << "}" << endl << "" << endl;
     302           0 :         os << "static inline void elektraTriggerError (const char *nr, Key *parentKey, const char *message)" << endl << "{" << endl;
     303           0 :         for (size_t i = 1; i < p.size (); ++i)
     304             :         {
     305           0 :                 os << "      if (strcmp(nr, \"" << p[i]["number"] << "\") == 0)" << endl << "        {" << endl;
     306           0 :                 os << "              ELEKTRA_SET_" << p[i]["macro"] << "_ERROR (parentKey, message);" << endl
     307           0 :                    << "              return;" << endl
     308           0 :                    << "      }" << endl;
     309             :         }
     310           0 :         os << "      ELEKTRA_SET_INTERNAL_ERRORF (parentKey, \"Unkown error code %s\", nr);" << endl << "}" << endl;
     311             : 
     312           0 :         os << "#endif" << endl;
     313           0 :         return os;
     314             : }
     315             : 
     316           0 : static string macroCaseToPascalCase (const string & s)
     317             : {
     318           0 :         std::string result;
     319           0 :         result.resize (s.size ());
     320           0 :         auto upcase = true;
     321           0 :         std::transform (s.begin (), s.end (), result.begin (), [&upcase](char c) {
     322           0 :                 int x = upcase ? toupper (c) : tolower (c);
     323           0 :                 upcase = c == '_';
     324           0 :                 return x;
     325           0 :         });
     326           0 :         result.erase (std::remove (result.begin (), result.end (), '_'), result.end ());
     327           0 :         return result;
     328             : }
     329             : 
     330           0 : static ostream & printHighlevelErrorsHeader (ostream & os, parse_t & p)
     331             : {
     332           0 :         os << "/*This is an auto-generated file generated by exporterrors highlevel. Do not modify it.*/" << endl
     333           0 :            << endl
     334           0 :            << "#ifndef ELEKTRA_ERRORS_H" << endl
     335           0 :            << "#define ELEKTRA_ERRORS_H" << endl
     336           0 :            << endl
     337           0 :            << "#include <elektra/error.h>" << endl
     338           0 :            << "#include <elektra/types.h>" << endl
     339           0 :            << endl
     340           0 :            << "#ifdef __cplusplus" << endl
     341           0 :            << "extern \"C\" {" << endl
     342           0 :            << "#endif" << endl;
     343             : 
     344           0 :         for (size_t i = 1; i < p.size (); ++i)
     345             :         {
     346           0 :                 const auto & macroName = p[i]["macro"];
     347             :                 os << "#define ELEKTRA_ERROR_" << macroName << "_ERROR(description, ...) elektraError" << macroName
     348           0 :                    << "Error (\"TODO\", __FILE__, __LINE__)" << endl;
     349             :                 os << "#define ELEKTRA_ERROR_ADD_" << macroName << "_WARNING(error, description, ...) elektraErrorAdd" << macroName
     350           0 :                    << "Warning (error, \"TODO\", __FILE__, __LINE__)" << endl;
     351             : 
     352           0 :                 os << "ElektraError * elektraError" << macroCaseToPascalCase (macroName)
     353           0 :                    << "Error (const char * module, const char * file, kdb_long_t line, const char * description, ...);" << endl;
     354           0 :                 os << "void elektraErrorAdd" << macroCaseToPascalCase (macroName)
     355             :                    << "Warning (ElektraError * error, const char * module, const char * file, kdb_long_t line, const char * description, "
     356           0 :                       "...);"
     357           0 :                    << endl;
     358             : 
     359           0 :                 os << endl;
     360             :         }
     361             : 
     362           0 :         os << "#ifdef __cplusplus" << endl << "}" << endl << "#endif" << endl;
     363             : 
     364           0 :         os << "#endif // ELEKTRA_ERRORS_PRIVATE_H" << endl;
     365           0 :         os << endl;
     366           0 :         return os;
     367             : }
     368             : 
     369           0 : static ostream & printHighlevelErrorsSource (ostream & os, parse_t & p, const std::string & header)
     370             : {
     371           0 :         os << "/*This is an auto-generated file generated by exporterrors_highlevel. Do not modify it.*/" << endl
     372           0 :            << endl
     373           0 :            << "#include <" << header << ">" << endl
     374           0 :            << "#include <kdbprivate.h>" << endl
     375           0 :            << "#include <kdbhelper.h>" << endl
     376           0 :            << "#include <kdberrors.h>" << endl
     377           0 :            << endl;
     378             : 
     379             :         // work-around not needed after new error concept
     380           0 :         os << "#if defined(__GNUC__)" << endl
     381           0 :            << "#pragma GCC diagnostic push" << endl
     382           0 :            << "#pragma GCC diagnostic ignored \"-Wformat\"" << endl
     383           0 :            << "#endif" << endl
     384           0 :            << endl;
     385             : 
     386           0 :         for (size_t i = 1; i < p.size (); ++i)
     387             :         {
     388           0 :                 const auto & macroName = p[i]["macro"];
     389             : 
     390           0 :                 os << "ElektraError * elektraError" << macroCaseToPascalCase (macroName)
     391           0 :                    << "Error (const char * module, const char * file, kdb_long_t line, const char * description, ...) {" << endl
     392           0 :                    << "\tva_list arg;" << endl
     393           0 :                    << "\tva_start (arg, description);" << endl
     394           0 :                    << "\tchar * descriptionText = elektraVFormat (description, arg);" << endl
     395           0 :                    << "\tElektraError * error = elektraErrorCreate (ELEKTRA_ERROR_" << p[i]["macro"]
     396           0 :                    << ", descriptionText, module, file, line);" << endl
     397           0 :                    << "\telektraFree (descriptionText);" << endl
     398           0 :                    << "\tva_end (arg);" << endl
     399           0 :                    << "\treturn error;" << endl
     400           0 :                    << "}" << endl
     401           0 :                    << endl;
     402             : 
     403           0 :                 os << "void elektraErrorAdd" << macroCaseToPascalCase (macroName)
     404             :                    << "Warning (ElektraError * error, const char * module, const char * file, kdb_long_t line, const char * description, "
     405           0 :                       "...) {"
     406           0 :                    << endl
     407           0 :                    << "\tva_list arg;" << endl
     408           0 :                    << "\tva_start (arg, description);" << endl
     409           0 :                    << "\tchar * descriptionText = elektraVFormat (description, arg);" << endl
     410           0 :                    << "\tElektraError * warning = elektraErrorCreate (ELEKTRA_ERROR_" << p[i]["macro"]
     411           0 :                    << ", descriptionText, module, file, line);" << endl
     412           0 :                    << "\telektraFree (descriptionText);" << endl
     413           0 :                    << "\tva_end (arg);" << endl
     414           0 :                    << "\telektraErrorAddWarning (error, warning);" << endl
     415           0 :                    << "}" << endl
     416           0 :                    << endl;
     417             :         }
     418             : 
     419           0 :         os << "#if defined(__GNUC__)" << endl << "#pragma GCC diagnostic pop" << endl << "#endif" << endl << endl;
     420             : 
     421           0 :         return os;
     422             : }
     423             : 
     424             : template <typename Func>
     425           0 : static int writeFile (parse_t & data, const char * filename, Func printFn)
     426             : {
     427           0 :         std::string tmpfile = filename;
     428             : #ifndef _WIN32
     429           0 :         tmpfile += ".tmp";
     430           0 :         tmpfile += to_string (getpid ());
     431             : #endif
     432             :         {
     433           0 :                 ofstream fout (tmpfile);
     434           0 :                 if (!fout.is_open ())
     435             :                 {
     436           0 :                         cerr << "Could not open output file " << filename << endl;
     437           0 :                         return 1;
     438             :                 }
     439           0 :                 printFn (fout, data);
     440             :         }
     441             : 
     442             : #ifndef _WIN32
     443           0 :         int fd = open (tmpfile.c_str (), O_RDWR);
     444           0 :         if (fd == -1)
     445             :         {
     446           0 :                 cerr << "Could not reopen file " << filename << endl;
     447             :                 return 2;
     448             :         }
     449           0 :         if (fsync (fd) == -1)
     450             :         {
     451           0 :                 cerr << "Could not fsync config file " << filename << " because ", strerror (errno);
     452           0 :                 close (fd);
     453             :                 return 3;
     454             :         }
     455           0 :         close (fd);
     456             : 
     457           0 :         if (rename (tmpfile.c_str (), filename) == -1)
     458             :         {
     459           0 :                 cerr << "Could not rename file " << tmpfile << " to " << filename << endl;
     460             :                 return 4;
     461             :         }
     462             : #endif
     463             :         return 0;
     464             : }
     465             : 
     466           0 : static void printUsage (const std::string & name)
     467             : {
     468             :         cerr << "Usage " << name << "MODE infile [options]"
     469           0 :              << "\tMODES:" << endl
     470           0 :              << "\t\tkdb\t\t options: outfile" << endl
     471           0 :              << "\t\thighlevel\t\t options: outcodes outpublic outprivate outsource includepublic includeprivate" << endl
     472           0 :              << "\t\t\t outcodes: outfile for error codes enum" << endl
     473           0 :              << "\t\t\t outpublic: outfile for public header" << endl
     474           0 :              << "\t\t\t outprivate: outfile for private header" << endl
     475           0 :              << "\t\t\t outsource: outfile for source code" << endl
     476           0 :              << "\t\t\t includepublic: include path (including file name) for public header" << endl
     477           0 :              << "\t\t\t includeprivate: include path (including file name) for private header" << endl
     478           0 :              << endl;
     479           0 : }
     480             : 
     481           0 : int main (int argc, char ** argv) try
     482             : {
     483           0 :         if (argc < 2)
     484             :         {
     485           0 :                 printUsage (argv[0]);
     486           0 :                 return 1;
     487             :         }
     488             : 
     489           0 :         std::string mode = argv[1];
     490             : 
     491           0 :         if (mode == "kdb")
     492             :         {
     493           0 :                 switch (argc)
     494             :                 {
     495             :                 case 3:
     496             :                 {
     497           0 :                         string infile = argv[2];
     498           0 :                         parse_t data = parse (infile);
     499           0 :                         printKDBErrors (cout, data);
     500             :                         break;
     501             :                 }
     502             :                 case 4:
     503             :                 {
     504           0 :                         string infile = argv[2];
     505           0 :                         parse_t data = parse (infile);
     506           0 :                         writeFile (data, argv[3], printKDBErrors);
     507             :                         break;
     508             :                 }
     509             :                 default:
     510           0 :                         printUsage (argv[0]);
     511           0 :                         return 1;
     512             :                 }
     513             :         }
     514           0 :         else if (mode == "highlevel")
     515             :         {
     516           0 :                 switch (argc)
     517             :                 {
     518             :                 case 3:
     519             :                 {
     520           0 :                         string infile = argv[2];
     521           0 :                         parse_t data = parse (infile);
     522           0 :                         printHighlevelErrorsHeader (cout, data);
     523           0 :                         cout << endl << endl;
     524           0 :                         printHighlevelErrorsSource (cout, data, "");
     525             :                         break;
     526             :                 }
     527             :                 case 6:
     528             :                 {
     529           0 :                         string infile = argv[2];
     530           0 :                         parse_t data = parse (infile);
     531           0 :                         writeFile (data, argv[3], printHighlevelErrorsHeader);
     532             : 
     533           0 :                         auto func = [&](ostream & os, parse_t & p) { printHighlevelErrorsSource (os, p, argv[5]); };
     534             : 
     535           0 :                         writeFile (data, argv[4], func);
     536             :                         break;
     537             :                 }
     538             :                 default:
     539           0 :                         printUsage (argv[0]);
     540             : 
     541           0 :                         return 1;
     542             :                 }
     543             :         }
     544             :         else
     545             :         {
     546           0 :                 cerr << "Unknown mode" << endl;
     547           0 :                 printUsage (argv[0]);
     548           0 :                 return 1;
     549             :         }
     550             : 
     551             : 
     552             :         return 0;
     553             : }
     554           0 : catch (parse_error const & e)
     555             : {
     556           0 :         cerr << "The line " << e.linenr << " caused following parse error: " << e.info << endl;
     557             :         return 2;
     558           0 : }

Generated by: LCOV version 1.13