]> granicus.if.org Git - icinga2/blobdiff - tools/mkclass/classcompiler.cpp
Implement include guards for mkclass
[icinga2] / tools / mkclass / classcompiler.cpp
index 561ac74c0dcbbac7a472bead985fb7e93ed0036e..203e90f803cd4cbb26a90d80de254380e66e81e1 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  * Icinga 2                                                                   *
- * Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/)   *
+ * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
  *                                                                            *
  * This program is free software; you can redistribute it and/or              *
  * modify it under the terms of the GNU General Public License                *
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
  ******************************************************************************/
 
-#include "classcompiler.h"
+#include "classcompiler.hpp"
 #include <iostream>
 #include <fstream>
 #include <stdexcept>
 #include <map>
 #include <vector>
+#include <cstring>
 
 using namespace icinga;
 
@@ -53,28 +54,28 @@ size_t ClassCompiler::ReadInput(char *buffer, size_t max_size)
        return static_cast<size_t>(m_Input->gcount());
 }
 
-void ClassCompiler::HandleInclude(const std::string& path, const ClassDebugInfo& locp)
+void ClassCompiler::HandleInclude(const std::string& path, const ClassDebugInfo&)
 {
        std::cout << "#include \"" << path << "\"" << std::endl << std::endl;
 }
 
-void ClassCompiler::HandleAngleInclude(const std::string& path, const ClassDebugInfo& locp)
+void ClassCompiler::HandleAngleInclude(const std::string& path, const ClassDebugInfo&)
 {
        std::cout << "#include <" << path << ">" << std::endl << std::endl;
 }
 
-void ClassCompiler::HandleNamespaceBegin(const std::string& name, const ClassDebugInfo& locp)
+void ClassCompiler::HandleNamespaceBegin(const std::string& name, const ClassDebugInfo&)
 {
        std::cout << "namespace " << name << std::endl
                          << "{" << std::endl << std::endl;
 }
 
-void ClassCompiler::HandleNamespaceEnd(const ClassDebugInfo& locp)
+void ClassCompiler::HandleNamespaceEnd(const ClassDebugInfo&)
 {
        std::cout << "}" << std::endl;
 }
 
-void ClassCompiler::HandleCode(const std::string& code, const ClassDebugInfo& locp)
+void ClassCompiler::HandleCode(const std::string& code, const ClassDebugInfo&)
 {
        std::cout << code << std::endl;
 }
@@ -100,7 +101,7 @@ unsigned long ClassCompiler::SDBM(const std::string& str, size_t len = std::stri
         return hash;
 }
 
-void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
+void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
 {
        std::vector<Field>::const_iterator it;
 
@@ -111,8 +112,13 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
        /* TypeImpl */
        std::cout << "template<>" << std::endl
                << "class TypeImpl<" << klass.Name << ">"
-               << " : public Type" << std::endl
-               << "{" << std::endl
+               << " : public Type";
+       
+       if (!klass.TypeBase.empty())
+               std::cout << ", public " + klass.TypeBase;
+
+       std::cout << std::endl
+               << " {" << std::endl
                << "public:" << std::endl;
 
        /* GetName */
@@ -121,10 +127,10 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
                  << "\t\t" << "return \"" << klass.Name << "\";" << std::endl
                  << "\t" << "}" << std::endl << std::endl;
 
-       /* IsAbstract */
-       std::cout << "\t" << "virtual bool IsAbstract(void) const" << std::endl
+       /* GetAttributes */
+       std::cout << "\t" << "virtual int GetAttributes(void) const" << std::endl
                  << "\t" << "{" << std::endl
-                 << "\t\t" << "return " << (klass.Abstract ? "true" : "false") << ";" << std::endl
+                 << "\t\t" << "return " << klass.Attributes << ";" << std::endl
                  << "\t" << "}" << std::endl << std::endl;
 
        /* GetBaseType */
@@ -149,15 +155,18 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
 
        /* StaticGetFieldId */
        std::cout << "\t" << "static int StaticGetFieldId(const String& name)" << std::endl
-               << "\t" << "{" << std::endl
-               << "\t\t" << "int offset = ";
+               << "\t" << "{" << std::endl;
 
-       if (!klass.Parent.empty())
-               std::cout << "TypeImpl<" << klass.Parent << ">::StaticGetFieldCount()";
-       else
-               std::cout << "0";
+       if (!klass.Fields.empty()) {
+               std::cout << "\t\t" << "int offset = ";
+
+               if (!klass.Parent.empty())
+                       std::cout << "TypeImpl<" << klass.Parent << ">::StaticGetFieldCount()";
+               else
+                       std::cout << "0";
 
-       std::cout << ";" << std::endl << std::endl;
+               std::cout << ";" << std::endl << std::endl;
+       }
 
        std::map<int, std::vector<std::pair<int, std::string> > > jumptable;
 
@@ -406,7 +415,14 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
                                prot = "public";
 
                        std::cout << prot << ":" << std::endl
-                                         << "\t" << "void Set" << it->GetFriendlyName() << "(const " << it->Type << "& value)" << std::endl
+                                         << "\t" << "void Set" << it->GetFriendlyName() << "(";
+
+                       if (it->Type == "bool" || it->Type == "double" || it->Type == "int")
+                               std::cout << it->Type;
+                       else
+                               std::cout << "const " << it->Type << "&";
+
+                       std::cout << " value)" << std::endl
                                          << "\t" << "{" << std::endl;
 
                        if (it->SetAccessor.empty())
@@ -444,7 +460,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
        std::cout << "};" << std::endl << std::endl;
 
        /* FactoryHelper */
-       if (klass.Abstract) {
+       if (klass.Attributes & TAAbstract) {
                std::cout << "template<>" << std::endl
                          << "struct FactoryHelper<" << klass.Name << ">" << std::endl
                          << "{" << std::endl
@@ -467,17 +483,55 @@ void ClassCompiler::CompileFile(const std::string& path)
        return CompileStream(path, &stream);
 }
 
+std::string ClassCompiler::BaseName(const  std::string& path)
+{
+       char *dir = strdup(path.c_str());
+       std::string result;
+
+       if (dir == NULL)
+               throw std::bad_alloc();
+
+#ifndef _WIN32
+       result = basename(dir);
+#else /* _WIN32 */
+       result = PathFindFileName(dir);
+#endif /* _WIN32 */
+
+       free(dir);
+
+       return result;
+}
+
+std::string ClassCompiler::FileNameToGuardName(const std::string& fname)
+{
+       std::string result = fname;
+
+       for (int i = 0; i < result.size(); i++) {
+               result[i] = toupper(result[i]);
+
+               if (result[i] == '.')
+                       result[i] = '_';
+       }
+
+       return result;
+}
+
 void ClassCompiler::CompileStream(const std::string& path, std::istream *stream)
 {
        stream->exceptions(std::istream::badbit);
 
-       std::cout << "#include \"base/object.h\"" << std::endl
-                         << "#include \"base/type.h\"" << std::endl
-                         << "#include \"base/debug.h\"" << std::endl
-                         << "#include \"base/value.h\"" << std::endl
-                         << "#include \"base/array.h\"" << std::endl
-                         << "#include \"base/dictionary.h\"" << std::endl
-                         << "#include \"base/utility.h\"" << std::endl << std::endl
+       std::string guard_name = FileNameToGuardName(BaseName(path));
+
+       std::cout << "#ifndef " << guard_name << std::endl
+                         << "#define " << guard_name << std::endl << std::endl;
+
+       std::cout << "#include \"base/object.hpp\"" << std::endl
+                         << "#include \"base/type.hpp\"" << std::endl
+                         << "#include \"base/debug.hpp\"" << std::endl
+                         << "#include \"base/value.hpp\"" << std::endl
+                         << "#include \"base/array.hpp\"" << std::endl
+                         << "#include \"base/dictionary.hpp\"" << std::endl
+                         << "#include \"base/utility.hpp\"" << std::endl << std::endl
                          << "#ifdef _MSC_VER" << std::endl
                          << "#pragma warning( push )" << std::endl
                          << "#pragma warning( disable : 4244 )" << std::endl
@@ -490,4 +544,6 @@ void ClassCompiler::CompileStream(const std::string& path, std::istream *stream)
        std::cout << "#ifdef _MSC_VER" << std::endl
                          << "#pragma warning ( pop )" << std::endl
                          << "#endif /* _MSC_VER */" << std::endl;
+
+       std::cout << "#endif /* " << guard_name << " */" << std::endl;
 }