]> granicus.if.org Git - icinga2/blob - tools/mkclass/classcompiler.cpp
Remove GetType().
[icinga2] / tools / mkclass / classcompiler.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2013 Icinga Development Team (http://www.icinga.org/)   *
4  *                                                                            *
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.                     *
9  *                                                                            *
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.                               *
14  *                                                                            *
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  ******************************************************************************/
19
20 #include "classcompiler.h"
21 #include <iostream>
22 #include <fstream>
23 #include <stdexcept>
24
25 using namespace icinga;
26
27 ClassCompiler::ClassCompiler(const std::string& path, std::istream *input)
28         : m_Path(path), m_Input(input)
29 {
30         InitializeScanner();
31 }
32
33 ClassCompiler::~ClassCompiler(void)
34 {
35         DestroyScanner();
36 }
37
38 std::string ClassCompiler::GetPath(void) const
39 {
40         return m_Path;
41 }
42
43 void *ClassCompiler::GetScanner(void)
44 {
45         return m_Scanner;
46 }
47
48 size_t ClassCompiler::ReadInput(char *buffer, size_t max_size)
49 {
50         m_Input->read(buffer, max_size);
51         return static_cast<size_t>(m_Input->gcount());
52 }
53
54 void ClassCompiler::HandleInclude(const std::string& path, const ClassDebugInfo& locp)
55 {
56         std::cout << "#include \"" << path << "\"" << std::endl << std::endl;
57 }
58
59 void ClassCompiler::HandleAngleInclude(const std::string& path, const ClassDebugInfo& locp)
60 {
61         std::cout << "#include <" << path << ">" << std::endl << std::endl;
62 }
63
64 void ClassCompiler::HandleNamespaceBegin(const std::string& name, const ClassDebugInfo& locp)
65 {
66         std::cout << "namespace " << name << std::endl
67                           << "{" << std::endl << std::endl;
68 }
69
70 void ClassCompiler::HandleNamespaceEnd(const ClassDebugInfo& locp)
71 {
72         std::cout << "}" << std::endl;
73 }
74
75 void ClassCompiler::HandleCode(const std::string& code, const ClassDebugInfo& locp)
76 {
77         std::cout << code << std::endl;
78 }
79
80 void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
81 {
82         std::vector<Field>::const_iterator it;
83
84         /* forward declaration */
85         if (klass.Name.find_first_of(':') == std::string::npos)
86                 std::cout << "class " << klass.Name << ";" << std::endl << std::endl;
87
88         /* TypeImpl */
89         std::cout << "template<>" << std::endl
90                 << "class TypeImpl<" << klass.Name << ">"
91                 << " : public Type" << std::endl
92                 << "{" << std::endl
93                 << "public:" << std::endl;
94
95         /* GetName */
96         std::cout << "\t" << "virtual String GetName(void) const" << std::endl
97                   << "\t" << "{" << std::endl
98                   << "\t\t" << "return \"" << klass.Name << "\";" << std::endl
99                   << "\t" << "}" << std::endl << std::endl;
100
101         /* IsAbstract */
102         std::cout << "\t" << "virtual bool IsAbstract(void) const" << std::endl
103                   << "\t" << "{" << std::endl
104                   << "\t\t" << "return " << (klass.Abstract ? "true" : "false") << ";" << std::endl
105                   << "\t" << "}" << std::endl << std::endl;
106
107         /* GetBaseType */
108         std::cout << "\t" << "virtual const Type *GetBaseType(void) const" << std::endl
109                 << "\t" << "{" << std::endl;
110
111         std::cout << "\t\t" << "return ";
112
113         if (!klass.Parent.empty())
114                 std::cout << "Type::GetByName(\"" << klass.Parent << "\")";
115         else
116                 std::cout << "NULL";
117
118         std::cout << ";" << std::endl
119                           << "\t" << "}" << std::endl << std::endl;
120
121         /* GetFieldId */
122         std::cout << "\t" << "virtual int GetFieldId(const String& name) const" << std::endl
123                 << "\t" << "{" << std::endl
124                 << "\t\t" << "return StaticGetFieldId(name);" << std::endl
125                 << "\t" << "}" << std::endl << std::endl;
126
127         /* StaticGetFieldId */
128         std::cout << "\t" << "static int StaticGetFieldId(const String& name)" << std::endl
129                 << "\t" << "{" << std::endl
130                 << "\t\t" << "int offset = ";
131
132         if (!klass.Parent.empty())
133                 std::cout << "TypeImpl<" << klass.Parent << ">::StaticGetFieldCount()";
134         else
135                 std::cout << "0";
136
137         std::cout << ";" << std::endl << std::endl;
138
139         int num = 0;
140         for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
141                 std::cout << "\t\t" << "if (name == \"" << it->Name << "\")" << std::endl
142                         << "\t\t\t" << "return offset + " << num << ";" << std::endl;
143                 num++;
144         }
145
146         std::cout << std::endl
147                 << "\t\t" << "return ";
148
149         if (!klass.Parent.empty())
150                 std::cout << "TypeImpl<" << klass.Parent << ">::StaticGetFieldId(name)";
151         else
152                 std::cout << "-1";
153
154         std::cout << ";" << std::endl
155                 << "\t" << "}" << std::endl << std::endl;
156
157         /* GetFieldInfo */
158         std::cout << "\t" << "virtual Field GetFieldInfo(int id) const" << std::endl
159                 << "\t" << "{" << std::endl
160                 << "\t\t" << "return StaticGetFieldInfo(id);" << std::endl
161                 << "\t" << "}" << std::endl << std::endl;
162
163         /* StaticGetFieldInfo */
164         std::cout << "\t" << "static Field StaticGetFieldInfo(int id)" << std::endl
165                 << "\t" << "{" << std::endl;
166
167         if (!klass.Parent.empty())
168                 std::cout << "\t\t" << "int real_id = id - " << "TypeImpl<" << klass.Parent << ">::StaticGetFieldCount();" << std::endl
169                 << "\t\t" << "if (real_id < 0) { return " << "TypeImpl<" << klass.Parent << ">::StaticGetFieldInfo(id); }" << std::endl;
170
171         std::cout << "\t\t" << "switch (";
172
173         if (!klass.Parent.empty())
174                 std::cout << "real_id";
175         else
176                 std::cout << "id";
177
178         std::cout << ") {" << std::endl;
179
180         num = 0;
181         for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
182                 std::cout << "\t\t\t" << "case " << num << ":" << std::endl
183                         << "\t\t\t\t" << "return Field(" << num << ", \"" << it->Name << "\", " << it->Attributes << ");" << std::endl;
184                 num++;
185         }
186
187         std::cout << "\t\t\t" << "default:" << std::endl
188                 << "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
189                 << "\t\t" << "}" << std::endl;
190
191         std::cout << "\t" << "}" << std::endl << std::endl;
192
193         /* GetFieldCount */
194         std::cout << "\t" << "virtual int GetFieldCount(void) const" << std::endl
195                 << "\t" << "{" << std::endl
196                 << "\t\t" << "return StaticGetFieldCount();" << std::endl
197                 << "\t" << "}" << std::endl << std::endl;
198
199         /* StaticGetFieldCount */
200         std::cout << "\t" << "static int StaticGetFieldCount(void)" << std::endl
201                 << "\t" << "{" << std::endl
202                 << "\t\t" << "return " << klass.Fields.size();
203
204         if (!klass.Parent.empty())
205                 std::cout << " + " << "TypeImpl<" << klass.Parent << ">::StaticGetFieldCount()";
206
207         std::cout << ";" << std::endl
208                 << "\t" << "}" << std::endl << std::endl;
209
210         std::cout << "};" << std::endl << std::endl;
211
212         /* ObjectImpl */
213         std::cout << "template<>" << std::endl
214                   << "class ObjectImpl<" << klass.Name << ">"
215                   << " : public " << (klass.Parent.empty() ? "Object" : klass.Parent) << std::endl
216                   << "{" << std::endl
217                   << "public:" << std::endl
218                   << "\t" << "DECLARE_PTR_TYPEDEFS(ObjectImpl<" << klass.Name << ">);" << std::endl << std::endl;
219
220         /* GetReflectionType */
221         std::cout << "\t" << "virtual const Type *GetReflectionType(void) const" << std::endl
222                           << "\t" << "{" << std::endl
223                           << "\t\t" << "return Type::GetByName(\"" << klass.Name << "\");" << std::endl
224                           << "\t" << "}" << std::endl << std::endl;
225
226         if (!klass.Fields.empty()) {
227                 /* constructor */
228                 std::cout << "public:" << std::endl
229                           << "\t" << "ObjectImpl<" << klass.Name << ">(void)" << std::endl
230                           << "\t" << "{" << std::endl;
231
232                 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
233                         std::cout << "\t\t" << "Set" << it->GetFriendlyName() << "(" << "GetDefault" << it->GetFriendlyName() << "());" << std::endl;
234                 }
235
236                 std::cout << "\t" << "}" << std::endl << std::endl;
237
238                 /* SetField */
239                 std::cout << "protected:" << std::endl
240                                   << "\t" << "virtual void SetField(int id, const Value& value)" << std::endl
241                                   << "\t" << "{" << std::endl;
242
243                 if (!klass.Parent.empty())
244                         std::cout << "\t\t" << "int real_id = id - TypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl
245                                   << "\t\t" << "if (real_id < 0) { " << klass.Parent << "::SetField(id, value); return; }" << std::endl;
246
247                 std::cout << "\t\t" << "switch (";
248
249                 if (!klass.Parent.empty())
250                         std::cout << "real_id";
251                 else
252                         std::cout << "id";
253
254                 std::cout << ") {" << std::endl;
255
256                 num = 0;
257                 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
258                         std::cout << "\t\t\t" << "case " << num << ":" << std::endl
259                                           << "\t\t\t\t" << "Set" << it->GetFriendlyName() << "(";
260                         
261                         if (it->Attributes & FAEnum)
262                                 std::cout << "static_cast<" << it->Type << ">(static_cast<int>(";
263
264                         std::cout << "value";
265                         
266                         if (it->Attributes & FAEnum)
267                                 std::cout << "))";
268                         
269                         std::cout << ");" << std::endl
270                                           << "\t\t\t\t" << "break;" << std::endl;
271                         num++;
272                 }
273
274                 std::cout << "\t\t\t" << "default:" << std::endl
275                                   << "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
276                                   << "\t\t" << "}" << std::endl;
277
278                 std::cout << "\t" << "}" << std::endl << std::endl;
279
280                 /* GetField */
281                 std::cout << "protected:" << std::endl
282                                   << "\t" << "virtual Value GetField(int id) const" << std::endl
283                                   << "\t" << "{" << std::endl;
284
285                 if (!klass.Parent.empty())
286                         std::cout << "\t\t" << "int real_id = id - TypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl
287                                           << "\t\t" << "if (real_id < 0) { return " << klass.Parent << "::GetField(id); }" << std::endl;
288
289                 std::cout << "\t\t" << "switch (";
290
291                 if (!klass.Parent.empty())
292                         std::cout << "real_id";
293                 else
294                         std::cout << "id";
295
296                 std::cout << ") {" << std::endl;
297
298                 num = 0;
299                 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
300                         std::cout << "\t\t\t" << "case " << num << ":" << std::endl
301                                           << "\t\t\t\t" << "return Get" << it->GetFriendlyName() << "();" << std::endl;
302                         num++;
303                 }
304
305                 std::cout << "\t\t\t" << "default:" << std::endl
306                                   << "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
307                                   << "\t\t" << "}" << std::endl;
308
309                 std::cout << "\t" << "}" << std::endl << std::endl;
310
311                 /* getters */
312                 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
313                         std::string prot;
314
315                         if (it->Attributes & FAGetProtected)
316                                 prot = "protected";
317                         else
318                                 prot = "public";
319
320                         std::cout << prot << ":" << std::endl
321                                           << "\t" << it->Type << " Get" << it->GetFriendlyName() << "(void) const" << std::endl
322                                           << "\t" << "{" << std::endl;
323
324                         if (it->GetAccessor.empty())
325                                 std::cout << "\t\t" << "return m_" << it->GetFriendlyName() << ";" << std::endl;
326                         else
327                                 std::cout << it->GetAccessor << std::endl;
328
329                         std::cout << "\t" << "}" << std::endl << std::endl;
330                 }
331
332                 /* setters */
333                 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
334                         std::string prot;
335
336                         if (it->Attributes & FASetProtected)
337                                 prot = "protected";
338                         else if (it->Attributes & FAConfig)
339                                 prot = "private";
340                         else
341                                 prot = "public";
342
343                         std::cout << prot << ":" << std::endl
344                                           << "\t" << "void Set" << it->GetFriendlyName() << "(const " << it->Type << "& value)" << std::endl
345                                           << "\t" << "{" << std::endl;
346
347                         if (it->SetAccessor.empty())
348                                 std::cout << "\t\t" << "m_" << it->GetFriendlyName() << " = value;" << std::endl;
349                         else
350                                 std::cout << it->SetAccessor << std::endl;
351
352                         std::cout << "\t" << "}" << std::endl << std::endl;
353                 }
354
355                 /* default */
356                 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
357                         std::string prot;
358
359                         std::cout << "private:" << std::endl
360                                           << "\t" << it->Type << " GetDefault" << it->GetFriendlyName() << "(void) const" << std::endl
361                                           << "\t" << "{" << std::endl;
362
363                         if (it->DefaultAccessor.empty())
364                                 std::cout << "\t\t" << "return " << it->Type << "();" << std::endl;
365                         else
366                                 std::cout << it->DefaultAccessor << std::endl;
367
368                         std::cout << "\t" << "}" << std::endl;
369                 }
370
371                 /* instance variables */
372                 std::cout << "private:" << std::endl;
373
374                 for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
375                         std::cout << "\t" << it->Type << " m_" << it->GetFriendlyName() << ";" << std::endl;
376                 }
377         }
378
379         std::cout << "};" << std::endl << std::endl;
380
381         /* FactoryHelper */
382         if (klass.Abstract) {
383                 std::cout << "template<>" << std::endl
384                           << "struct FactoryHelper<" << klass.Name << ">" << std::endl
385                           << "{" << std::endl
386                           << "\t" << "Type::Factory GetFactory(void)" << std::endl
387                           << "\t" << "{" << std::endl
388                           << "\t\t" << "return Type::Factory();"
389                           << "\t" << "}"
390                           << "};" << std::endl << std::endl;
391         }
392 }
393
394 void ClassCompiler::CompileFile(const std::string& path)
395 {
396         std::ifstream stream;
397         stream.open(path.c_str(), std::ifstream::in);
398
399         if (!stream)
400                 throw std::invalid_argument("Could not open config file: " + path);
401
402         return CompileStream(path, &stream);
403 }
404
405 void ClassCompiler::CompileStream(const std::string& path, std::istream *stream)
406 {
407         stream->exceptions(std::istream::badbit);
408
409         std::cout << "#include \"base/object.h\"" << std::endl
410                           << "#include \"base/type.h\"" << std::endl
411                           << "#include \"base/debug.h\"" << std::endl
412                           << "#include \"base/value.h\"" << std::endl
413                           << "#include \"base/array.h\"" << std::endl
414                           << "#include \"base/dictionary.h\"" << std::endl << std::endl
415                           << "#ifdef _MSC_VER" << std::endl
416                           << "#pragma warning( push )" << std::endl
417                           << "#pragma warning( disable : 4244 )" << std::endl
418                           << "#pragma warning( disable : 4800 )" << std::endl
419                           << "#endif /* _MSC_VER */" << std::endl << std::endl;
420
421         ClassCompiler ctx(path, stream);
422         ctx.Compile();
423
424         std::cout << "#ifdef _MSC_VER" << std::endl
425                           << "#pragma warning ( pop )" << std::endl
426                           << "#endif /* _MSC_VER */" << std::endl;
427 }