changed copyright notice
[lqt.git] / new / cpptoxml / main.cpp
blobabb62fb8311c8da54effe3752df93aac4f94c70a
1 /*
2 * Copyright (c) 2007 Mauro Iazzi
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
27 #include <iostream>
28 #include <typeinfo>
30 #include "binder.h"
31 #include "codemodel.h"
32 #include "control.h"
33 #include "parser.h"
34 #include "preprocessor.h"
36 #include <QByteArray>
37 #include <QFile>
38 #include <QTextCodec>
39 #include <QTextStream>
41 #include <QObject>
42 #include <QDir>
44 #include <QDebug>
46 #define ID_STR(i) (QString("_").append(QString::number(i->creationId())))
47 #define ATTR_STR(n, v) ( (v).prepend(" " n "=\"").append("\"") )
48 #define ATTR_NUM(n, v) ( (QString::number(v)).prepend(" " n "=\"").append("\"") )
49 #define ATTR_TRUE(n) ( ATTR_NUM(n, 1) )
51 using namespace std;
53 class XMLVisitor {
54 public:
55 QString XMLTag(CodeModelItem);
56 QString visit(TypeInfo);
57 QString visit(CodeModelItem);
58 template <typename T> QString visit(T) {
59 std::cerr << "unimplemented CodeModelItem: " << typeid(T).name() << std::endl;
60 return "";
63 QString XMLVisitor::visit(TypeInfo t) {
65 qDebug() << "=====";
66 QStringList::const_iterator constIterator;
67 for (constIterator = s_list.constBegin(); constIterator != s_list.constEnd(); ++constIterator)
68 qDebug() << *constIterator << "::";
69 qDebug() << "const " << t.isConstant();
70 qDebug() << "volatile " << t.isVolatile();
71 qDebug() << "reference " << t.isReference();
72 qDebug() << "indir " << t.indirections();
73 qDebug() << "fp? " << t.isFunctionPointer();
74 //QStringList arrayElements();
75 //QList<TypeInfo> arguments();
76 qDebug() << t.toString();
78 //if (s_list.size()>1) qDebug() << t.toString() << s_list;
79 //if (s_list.join("::")!=t.toString()) qDebug() << s_list.join("::") << t.toString();
80 QString ret(" type_name=\"");
81 ret += t.toString().append("\"");
82 ret += " type_base=\"";
83 ret += t.qualifiedName().join("::").append("\"");
84 if (t.isConstant()) ret += ATTR_TRUE("type_constant");
85 if (t.isVolatile()) ret += ATTR_TRUE("type_volatile");
86 if (t.isReference()) ret += ATTR_TRUE("type_reference");
87 if (t.indirections()>0) ret += ATTR_NUM("indirections", t.indirections());
88 return ret;
91 #define TAG_CASE(s) case _CodeModelItem::Kind_##s: return #s
92 QString XMLVisitor::XMLTag(CodeModelItem i) {
93 switch (i->kind()) {
94 TAG_CASE(Scope);
95 TAG_CASE(Namespace);
96 TAG_CASE(Member);
97 TAG_CASE(Function);
98 TAG_CASE(Argument);
99 TAG_CASE(Class);
100 TAG_CASE(Enum);
101 TAG_CASE(Enumerator);
102 TAG_CASE(File);
103 TAG_CASE(FunctionDefinition);
104 TAG_CASE(TemplateParameter);
105 TAG_CASE(TypeAlias);
106 TAG_CASE(Variable);
108 return "";
110 QString XMLVisitor::visit(CodeModelItem i) {
111 QString ret("");
112 ret += XMLTag(i);
114 ret += ATTR_STR("id", ID_STR(i));
115 ret += ATTR_STR("name", i->name());
116 ret += ATTR_STR("context", i->scope().join("::").append("::"));
117 ret += ATTR_STR("fullname", i->qualifiedName().join("::"));
119 if (i->kind() & _CodeModelItem::Kind_Scope) {
120 ret += " members=\"";
122 if ((i->kind() & _CodeModelItem::Kind_Namespace ) == _CodeModelItem::Kind_Namespace) {
123 foreach(NamespaceModelItem n, model_dynamic_cast<NamespaceModelItem>(i)->namespaces())
124 ret += ID_STR(n).append(" ");
126 if (i->kind() & _CodeModelItem::Kind_Scope) {
127 foreach(ClassModelItem n, model_dynamic_cast<ScopeModelItem>(i)->classes())
128 ret += ID_STR(n).append(" ");
129 foreach(EnumModelItem n, model_dynamic_cast<ScopeModelItem>(i)->enums())
130 ret += ID_STR(n).append(" ");
131 foreach(FunctionModelItem n, model_dynamic_cast<ScopeModelItem>(i)->functions())
132 ret += ID_STR(n).append(" ");
133 foreach(TypeAliasModelItem n, model_dynamic_cast<ScopeModelItem>(i)->typeAliases())
134 ret += ID_STR(n).append(" ");
135 foreach(VariableModelItem n, model_dynamic_cast<ScopeModelItem>(i)->variables())
136 ret += ID_STR(n).append(" ");
138 if (i->kind() & _CodeModelItem::Kind_Scope) {
139 ret += "\"";
141 if (i->kind() & _CodeModelItem::Kind_Member) {
142 MemberModelItem m = model_dynamic_cast<MemberModelItem>(i);
143 if (m->isConstant()) ret += ATTR_TRUE("constant");
144 if (m->isVolatile()) ret += ATTR_TRUE("volatile");
145 if (m->isStatic()) ret += ATTR_TRUE("static");
146 if (m->isAuto()) ret += ATTR_TRUE("auto");
147 if (m->isFriend()) ret += ATTR_TRUE("friend");
148 if (m->isRegister()) ret += ATTR_TRUE("register");
149 if (m->isExtern()) ret += ATTR_TRUE("extern");
150 if (m->isMutable()) ret += ATTR_TRUE("mutable");
152 ret += " access=\"";
153 switch (m->accessPolicy()) {
154 case CodeModel::Public:
155 ret += "public";
156 break;
157 case CodeModel::Private:
158 ret += "private";
159 break;
160 case CodeModel::Protected:
161 ret += "protected";
162 break;
164 ret += "\"";
166 ret += visit(m->type());
168 if ((i->kind() & _CodeModelItem::Kind_Function) == _CodeModelItem::Kind_Function) {
169 FunctionModelItem m = model_dynamic_cast<FunctionModelItem>(i);
170 if (m->isVirtual()) ret += ATTR_TRUE("virtual");
171 if (m->isInline()) ret += ATTR_TRUE("inline");
172 if (m->isExplicit()) ret += ATTR_TRUE("explicit");
173 if (m->isAbstract()) ret += ATTR_TRUE("abstract");
174 if (m->isVariadics()) ret += ATTR_TRUE("variadics");
175 //if (i->name()=="destroyed") qDebug() << CodeModel::Normal << CodeModel::Slot << CodeModel::Signal << m->functionType() << i->qualifiedName();
176 switch(m->functionType()) {
177 case CodeModel::Normal:
178 break;
179 case CodeModel::Slot:
180 ret += ATTR_TRUE("slot");
181 break;
182 case CodeModel::Signal:
183 ret += ATTR_TRUE("signal");
184 break;
187 if (i->kind() == _CodeModelItem::Kind_Argument) {
188 ArgumentModelItem a = model_dynamic_cast<ArgumentModelItem>(i);
189 ret += visit(a->type());
190 if (a->defaultValue()) {
191 ret += ATTR_TRUE("default");
192 ret += ATTR_STR("defaultvalue", a->defaultValueExpression());
195 if (i->kind() == _CodeModelItem::Kind_Class) {
196 ClassModelItem c = model_dynamic_cast<ClassModelItem>(i);
197 if (c->baseClasses().size()>0) {
198 ret += ATTR_STR("bases", c->baseClasses().join(";").append(";"));
200 switch(c->classType()) {
201 case CodeModel::Class:
202 ret += ATTR_STR("class_type", QString("class"));
203 break;
204 case CodeModel::Struct:
205 ret += ATTR_STR("class_type", QString("struct"));
206 break;
207 case CodeModel::Union:
208 ret += ATTR_STR("class_type", QString("union"));
209 break;
211 // TODO also list templateParameters (maybe in content?)
212 // TODO also list propertyDeclarations (maybe in content?)
214 if (i->kind() == _CodeModelItem::Kind_Enum) {
215 EnumModelItem e = model_dynamic_cast<EnumModelItem>(i);
216 // TODO try to understand the meaning of the access policy of enums
218 if (i->kind() == _CodeModelItem::Kind_Enumerator) {
219 EnumeratorModelItem e = model_dynamic_cast<EnumeratorModelItem>(i);
220 ret += e->value().prepend(" value=\"").append("\"");
222 if (i->kind() == _CodeModelItem::Kind_TypeAlias) {
223 TypeAliasModelItem a = model_dynamic_cast<TypeAliasModelItem>(i);
224 ret += visit(a->type());
227 ret.replace('>', "&gt;");
228 ret.replace('<', "&lt;");
229 ret = "<" + ret + " >\n";
232 // content of the entry:
233 // - Arguments of functions
234 // - members of scopes
235 // - enumeration values
237 if ((i->kind() & _CodeModelItem::Kind_Namespace ) == _CodeModelItem::Kind_Namespace) {
238 foreach(NamespaceModelItem n, model_dynamic_cast<NamespaceModelItem>(i)->namespaces())
239 ret += visit(model_static_cast<CodeModelItem>(n));
241 if (i->kind() & _CodeModelItem::Kind_Scope) {
242 foreach(ClassModelItem n, model_dynamic_cast<ScopeModelItem>(i)->classes())
243 ret += visit(model_static_cast<CodeModelItem>(n));
244 foreach(EnumModelItem n, model_dynamic_cast<ScopeModelItem>(i)->enums())
245 ret += visit(model_static_cast<CodeModelItem>(n));
246 foreach(FunctionModelItem n, model_dynamic_cast<ScopeModelItem>(i)->functions())
247 ret += visit(model_static_cast<CodeModelItem>(n));
248 foreach(TypeAliasModelItem n, model_dynamic_cast<ScopeModelItem>(i)->typeAliases())
249 ret += visit(model_static_cast<CodeModelItem>(n));
250 foreach(VariableModelItem n, model_dynamic_cast<ScopeModelItem>(i)->variables())
251 ret += visit(model_static_cast<CodeModelItem>(n));
253 if ((i->kind() & _CodeModelItem::Kind_Function) == _CodeModelItem::Kind_Function) {
254 foreach(ArgumentModelItem n, model_dynamic_cast<FunctionModelItem>(i)->arguments())
255 ret += visit(model_static_cast<CodeModelItem>(n));
257 if (i->kind() == _CodeModelItem::Kind_Enum) {
258 QString last = "0";
259 EnumModelItem e = model_dynamic_cast<EnumModelItem>(i);
260 foreach(EnumeratorModelItem n, model_dynamic_cast<EnumModelItem>(i)->enumerators()) {
261 if (n->value() == QString()) n->setValue(last.append("+1"));
262 ret += visit(model_static_cast<CodeModelItem>(n));
263 last = n->value();
268 ret += "</";
269 ret += XMLTag(i);
270 ret += ">\n";
271 return ret;
274 template<>
275 QString XMLVisitor::visit<CodeModelItem>(CodeModelItem i) {
276 QString ret;
277 ret += "unknown CodeModelItem"; ret += i->name();
278 QStringList s_list = i->qualifiedName();
279 QStringList::const_iterator constIterator;
280 for (constIterator = s_list.constBegin(); constIterator != s_list.constEnd(); ++constIterator) ret += *constIterator;
281 return ret;
283 template<>
284 QString XMLVisitor::visit<ClassModelItem>(ClassModelItem i) {
285 QString buf("<");
286 switch (i->classType()) {
287 case CodeModel::Struct: buf += "Struct"; break;
288 case CodeModel::Class: buf += "Class"; break;
289 case CodeModel::Union: buf += "Union"; break;
291 buf.append(" id=\"").append(ID_STR(i)).append("\"");
292 buf += QString(" name=\"").append(i->name().isEmpty()?QString("::"):i->name()).append("\"");
293 buf += " members=\"";
294 foreach (ClassModelItem m, i->classes()) buf += ID_STR(m).append(" ");
295 foreach (EnumModelItem m, i->enums()) buf += ID_STR(m).append(" ");
296 foreach (FunctionModelItem m, i->functions()) buf += ID_STR(m).append(" ");
297 foreach (TypeAliasModelItem m, i->typeAliases()) buf += ID_STR(m).append(" ");
298 foreach (VariableModelItem m, i->variables()) buf += ID_STR(m).append(" ");
299 buf.append("\" />\n");
301 foreach (ClassModelItem m, i->classes()) visit(m);
302 foreach (EnumModelItem m, i->enums()) visit(m);
303 foreach (FunctionModelItem m, i->functions()) visit(m);
304 foreach (TypeAliasModelItem m, i->typeAliases()) visit(m);
305 foreach (VariableModelItem m, i->variables()) visit(m);
306 return buf;
308 template<>
309 QString XMLVisitor::visit<NamespaceModelItem>(NamespaceModelItem n) {
310 QString buf("<Namespace");
311 buf.append(" id=\"").append(ID_STR(n)).append("\"");
312 buf += QString(" name=\"").append(n->name().isEmpty()?QString("::"):n->name()).append("\"");
313 buf += " members=\"";
314 foreach (NamespaceModelItem m, n->namespaces()) buf += ID_STR(m).append(" ");
315 foreach (ClassModelItem m, n->classes()) buf += ID_STR(m).append(" ");
316 foreach (EnumModelItem m, n->enums()) buf += ID_STR(m).append(" ");
317 foreach (FunctionModelItem m, n->functions()) buf += ID_STR(m).append(" ");
318 foreach (TypeAliasModelItem m, n->typeAliases()) buf += ID_STR(m).append(" ");
319 foreach (VariableModelItem m, n->variables()) buf += ID_STR(m).append(" ");
320 buf.append("\" />\n");
322 foreach (NamespaceModelItem m, n->namespaces()) buf += visit(m);
323 foreach (ClassModelItem m, n->classes()) buf += visit(m);
324 foreach (EnumModelItem m, n->enums()) buf += visit(m);
325 foreach (FunctionModelItem m, n->functions()) buf += visit(m);
326 foreach (TypeAliasModelItem m, n->typeAliases()) buf += visit(m);
327 foreach (VariableModelItem m, n->variables()) buf += visit(m);
328 return buf;
331 int main (int argc, char **argv) {
332 bool onlyPreprocess = false;
333 QString configName;
334 QString sourceName;
336 QStringList options;
337 for (int i=1;i<argc;i++) options << argv[i];
338 int i;
339 if ((i=options.indexOf("-C"))!=-1) {
340 if (options.count() > i+1) {
341 configName = options.at(i+1);
342 options.removeAt(i+1);
344 options.removeAt(i);
346 if ((i=options.indexOf("-P"))!=-1) {
347 onlyPreprocess = true;
348 options.removeAt(i);
350 if (options.count()>1) return 37;
351 sourceName = options.at(0);
353 QByteArray contents;
354 if (0) {
355 QFile file(argv[1]);
357 if (!file.open(QFile::ReadOnly))
358 return false;
360 QTextStream stream(&file);
361 stream.setCodec(QTextCodec::codecForName("UTF-8"));
362 contents = stream.readAll().toUtf8();
363 file.close();
364 } else {
365 Preprocessor pp;
366 QStringList inclist;
368 QString qtdir = getenv ("QTDIR");
369 if (qtdir.isEmpty()) {
370 fprintf(stderr, "Generator requires QTDIR to be set\n");
371 return false;
374 qtdir += "/include";
376 QString currentDir = QDir::current().absolutePath();
377 QFileInfo sourceInfo(sourceName);
378 //QDir::setCurrent(sourceInfo.absolutePath());
380 inclist << (sourceInfo.absolutePath());
381 inclist << (QDir::convertSeparators(qtdir));
382 inclist << (QDir::convertSeparators(qtdir + "/QtXml"));
383 inclist << (QDir::convertSeparators(qtdir + "/QtNetwork"));
384 inclist << (QDir::convertSeparators(qtdir + "/QtCore"));
385 inclist << (QDir::convertSeparators(qtdir + "/QtGui"));
386 inclist << (QDir::convertSeparators(qtdir + "/QtOpenGL"));
387 //qDebug() << inclist;
389 pp.addIncludePaths(inclist);
390 pp.processFile(sourceName, configName);
391 //qDebug() << pp.macroNames();
392 contents = pp.result();
393 //qDebug() << contents;
394 //QTextStream(stdout) << contents;
397 if (onlyPreprocess) {
398 QTextStream(stdout) << contents;
399 } else {
400 Control control;
401 Parser p(&control);
402 pool __pool;
404 TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
406 CodeModel model;
407 Binder binder(&model, p.location());
408 FileModelItem f_model = binder.run(ast);
410 XMLVisitor visitor;
411 QTextStream(stdout) << visitor.visit(model_static_cast<CodeModelItem>(f_model));
414 return 0;