1 /******************************************************************************
3 * Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
20 #include "classcompiler.h"
25 using namespace icinga;
27 ClassCompiler::ClassCompiler(const std::string& path, std::istream *input)
28 : m_Path(path), m_Input(input)
33 ClassCompiler::~ClassCompiler(void)
38 std::string ClassCompiler::GetPath(void) const
43 void *ClassCompiler::GetScanner(void)
48 size_t ClassCompiler::ReadInput(char *buffer, size_t max_size)
50 m_Input->read(buffer, max_size);
51 return static_cast<size_t>(m_Input->gcount());
54 void ClassCompiler::HandleInclude(const std::string& path, const ClassDebugInfo& locp)
56 std::cout << "#include \"" << path << "\"" << std::endl << std::endl;
59 void ClassCompiler::HandleAngleInclude(const std::string& path, const ClassDebugInfo& locp)
61 std::cout << "#include <" << path << ">" << std::endl << std::endl;
64 void ClassCompiler::HandleNamespaceBegin(const std::string& name, const ClassDebugInfo& locp)
66 std::cout << "namespace " << name << std::endl
67 << "{" << std::endl << std::endl;
70 void ClassCompiler::HandleNamespaceEnd(const ClassDebugInfo& locp)
72 std::cout << "}" << std::endl;
75 void ClassCompiler::HandleCode(const std::string& code, const ClassDebugInfo& locp)
77 std::cout << code << std::endl;
80 void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
82 std::vector<Field>::const_iterator it;
84 /* forward declaration */
85 if (klass.Name.find_first_of(':') == std::string::npos)
86 std::cout << "class " << klass.Name << ";" << std::endl << std::endl;
88 /* ReflectionTypeImpl */
89 std::cout << "template<>" << std::endl
90 << "class ReflectionTypeImpl<" << klass.Name << ">"
91 << " : public ReflectionType, public Singleton<ReflectionTypeImpl<" << klass.Name << "> >" << std::endl
93 << "public:" << std::endl;
96 std::cout << "\t" << "virtual int GetFieldId(const String& name) const" << std::endl
97 << "\t" << "{" << std::endl
98 << "\t\t" << "return StaticGetFieldId(name);" << std::endl
99 << "\t" << "}" << std::endl << std::endl;
101 /* StaticGetFieldId */
102 std::cout << "\t" << "static int StaticGetFieldId(const String& name)" << std::endl
103 << "\t" << "{" << std::endl
104 << "\t\t" << "int offset = ";
106 if (!klass.Parent.empty())
107 std::cout << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount()";
111 std::cout << ";" << std::endl << std::endl;
114 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
115 std::cout << "\t\t" << "if (name == \"" << it->Name << "\")" << std::endl
116 << "\t\t\t" << "return offset + " << num << ";" << std::endl;
120 std::cout << std::endl
121 << "\t\t" << "return ";
123 if (!klass.Parent.empty())
124 std::cout << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldId(name)";
128 std::cout << ";" << std::endl
129 << "\t" << "}" << std::endl << std::endl;
132 std::cout << "\t" << "virtual ReflectionField GetFieldInfo(int id) const" << std::endl
133 << "\t" << "{" << std::endl
134 << "\t\t" << "return StaticGetFieldInfo(id);" << std::endl
135 << "\t" << "}" << std::endl << std::endl;
137 /* StaticGetFieldInfo */
138 std::cout << "\t" << "static ReflectionField StaticGetFieldInfo(int id)" << std::endl
139 << "\t" << "{" << std::endl;
141 if (!klass.Parent.empty())
142 std::cout << "\t\t" << "int real_id = id - " << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount();" << std::endl
143 << "\t\t" << "if (real_id < 0) { return " << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldInfo(id); }" << std::endl;
145 std::cout << "\t\t" << "switch (";
147 if (!klass.Parent.empty())
148 std::cout << "real_id";
152 std::cout << ") {" << std::endl;
155 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
156 std::cout << "\t\t\t" << "case " << num << ":" << std::endl
157 << "\t\t\t\t" << "return ReflectionField(" << num << ", \"" << it->Name << "\", " << it->Attributes << ");" << std::endl;
161 std::cout << "\t\t\t" << "default:" << std::endl
162 << "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
163 << "\t\t" << "}" << std::endl;
165 std::cout << "\t" << "}" << std::endl << std::endl;
168 std::cout << "\t" << "virtual int GetFieldCount(void) const" << std::endl
169 << "\t" << "{" << std::endl
170 << "\t\t" << "return StaticGetFieldCount();" << std::endl
171 << "\t" << "}" << std::endl << std::endl;
173 /* StaticGetFieldCount */
174 std::cout << "\t" << "static int StaticGetFieldCount(void)" << std::endl
175 << "\t" << "{" << std::endl
176 << "\t\t" << "return " << klass.Fields.size();
178 if (!klass.Parent.empty())
179 std::cout << " + " << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount()";
181 std::cout << ";" << std::endl
182 << "\t" << "}" << std::endl << std::endl;
184 std::cout << "};" << std::endl << std::endl;
186 /* ReflectionObjectImpl */
187 std::cout << "template<>" << std::endl
188 << "class ReflectionObjectImpl<" << klass.Name << ">"
189 << " : public " << (klass.Parent.empty() ? "ReflectionObject" : klass.Parent) << std::endl
191 << "public:" << std::endl
192 << "\t" << "DECLARE_PTR_TYPEDEFS(ReflectionObjectImpl<" << klass.Name << ">);" << std::endl << std::endl;
195 std::cout << "\t" << "virtual const ReflectionType *GetReflectionType(void) const" << std::endl
196 << "\t" << "{" << std::endl
197 << "\t\t" << "return ReflectionTypeImpl<" << klass.Name << ">::GetInstance();" << std::endl
198 << "\t" << "}" << std::endl << std::endl;
200 if (!klass.Fields.empty()) {
202 std::cout << "public:" << std::endl
203 << "\t" << "ReflectionObjectImpl<" << klass.Name << ">(void)" << std::endl
204 << "\t" << "{" << std::endl;
206 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
207 std::cout << "\t\t" << "Set" << it->GetFriendlyName() << "(" << "GetDefault" << it->GetFriendlyName() << "());" << std::endl;
210 std::cout << "\t" << "}" << std::endl << std::endl;
213 std::cout << "protected:" << std::endl
214 << "\t" << "virtual void SetField(int id, const Value& value)" << std::endl
215 << "\t" << "{" << std::endl;
217 if (!klass.Parent.empty())
218 std::cout << "\t\t" << "int real_id = id - ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl
219 << "\t\t" << "if (real_id < 0) { " << klass.Parent << "::SetField(id, value); return; }" << std::endl;
221 std::cout << "\t\t" << "switch (";
223 if (!klass.Parent.empty())
224 std::cout << "real_id";
228 std::cout << ") {" << std::endl;
231 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
232 std::cout << "\t\t\t" << "case " << num << ":" << std::endl
233 << "\t\t\t\t" << "Set" << it->GetFriendlyName() << "(";
235 if (it->Attributes & FAEnum)
236 std::cout << "static_cast<" << it->Type << ">(static_cast<int>(";
238 std::cout << "value";
240 if (it->Attributes & FAEnum)
243 std::cout << ");" << std::endl
244 << "\t\t\t\t" << "break;" << std::endl;
248 std::cout << "\t\t\t" << "default:" << std::endl
249 << "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
250 << "\t\t" << "}" << std::endl;
252 std::cout << "\t" << "}" << std::endl << std::endl;
255 std::cout << "protected:" << std::endl
256 << "\t" << "virtual Value GetField(int id) const" << std::endl
257 << "\t" << "{" << std::endl;
259 if (!klass.Parent.empty())
260 std::cout << "\t\t" << "int real_id = id - ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl
261 << "\t\t" << "if (real_id < 0) { return " << klass.Parent << "::GetField(id); }" << std::endl;
263 std::cout << "\t\t" << "switch (";
265 if (!klass.Parent.empty())
266 std::cout << "real_id";
270 std::cout << ") {" << std::endl;
273 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
274 std::cout << "\t\t\t" << "case " << num << ":" << std::endl
275 << "\t\t\t\t" << "return Get" << it->GetFriendlyName() << "();" << std::endl;
279 std::cout << "\t\t\t" << "default:" << std::endl
280 << "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
281 << "\t\t" << "}" << std::endl;
283 std::cout << "\t" << "}" << std::endl << std::endl;
286 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
289 if (it->Attributes & FAGetProtected)
294 std::cout << prot << ":" << std::endl
295 << "\t" << it->Type << " Get" << it->GetFriendlyName() << "(void) const" << std::endl
296 << "\t" << "{" << std::endl;
298 if (it->GetAccessor.empty())
299 std::cout << "\t\t" << "return m_" << it->GetFriendlyName() << ";" << std::endl;
301 std::cout << it->GetAccessor << std::endl;
303 std::cout << "\t" << "}" << std::endl << std::endl;
307 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
310 if (it->Attributes & FASetProtected)
312 else if (it->Attributes & FAConfig)
317 std::cout << prot << ":" << std::endl
318 << "\t" << "void Set" << it->GetFriendlyName() << "(const " << it->Type << "& value)" << std::endl
319 << "\t" << "{" << std::endl;
321 if (it->SetAccessor.empty())
322 std::cout << "\t\t" << "m_" << it->GetFriendlyName() << " = value;" << std::endl;
324 std::cout << it->SetAccessor << std::endl;
326 std::cout << "\t" << "}" << std::endl << std::endl;
330 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
333 std::cout << "private:" << std::endl
334 << "\t" << it->Type << " GetDefault" << it->GetFriendlyName() << "(void) const" << std::endl
335 << "\t" << "{" << std::endl;
337 if (it->DefaultAccessor.empty())
338 std::cout << "\t\t" << "return Empty;" << std::endl;
340 std::cout << it->DefaultAccessor << std::endl;
342 std::cout << "\t" << "}" << std::endl;
345 /* instance variables */
346 std::cout << "private:" << std::endl;
348 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
349 std::cout << "\t" << it->Type << " m_" << it->GetFriendlyName() << ";" << std::endl;
353 std::cout << "};" << std::endl << std::endl;
356 void ClassCompiler::CompileFile(const std::string& path)
358 std::ifstream stream;
359 stream.open(path.c_str(), std::ifstream::in);
362 throw std::invalid_argument("Could not open config file: " + path);
364 return CompileStream(path, &stream);
367 void ClassCompiler::CompileStream(const std::string& path, std::istream *stream)
369 stream->exceptions(std::istream::badbit);
371 std::cout << "#include \"base/reflectionobject.h\"" << std::endl
372 << "#include \"base/singleton.h\"" << std::endl
373 << "#include \"base/debug.h\"" << std::endl
374 << "#include \"base/value.h\"" << std::endl
375 << "#include \"base/array.h\"" << std::endl
376 << "#include \"base/dictionary.h\"" << std::endl << std::endl
377 << "#ifdef _MSC_VER" << std::endl
378 << "#pragma warning( push )" << std::endl
379 << "#pragma warning( disable : 4244 )" << std::endl
380 << "#pragma warning( disable : 4800 )" << std::endl
381 << "#endif /* _MSC_VER */" << std::endl << std::endl;
383 ClassCompiler ctx(path, stream);
386 std::cout << "#ifdef _MSC_VER" << std::endl
387 << "#pragma warning ( pop )" << std::endl
388 << "#endif /* _MSC_VER */" << std::endl;