summaryrefslogtreecommitdiff
path: root/src/dbusxmlscanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbusxmlscanner.cpp')
-rw-r--r--src/dbusxmlscanner.cpp877
1 files changed, 877 insertions, 0 deletions
diff --git a/src/dbusxmlscanner.cpp b/src/dbusxmlscanner.cpp
new file mode 100644
index 0000000..246bbe9
--- /dev/null
+++ b/src/dbusxmlscanner.cpp
@@ -0,0 +1,877 @@
+/******************************************************************************
+ *
+ *
+ *
+ * Copyright (C) 2009 by Tobias Hunger <tobias@aquazul.com>
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#include "dbusxmlscanner.h"
+
+#include "commentscan.h"
+#include "entry.h"
+
+#include <qfile.h>
+#include <qxml.h>
+#include <qstring.h>
+
+#include "message.h"
+#include "util.h"
+#include "arguments.h"
+
+// -----------------------------------------------------------------------
+// Convenience defines:
+// -----------------------------------------------------------------------
+
+#define CONDITION(cond, msg) \
+ do {\
+ if (cond)\
+ {\
+ if (m_errorString.isEmpty()) { m_errorString = msg; }\
+ return false;\
+ }\
+ }\
+ while (0)
+
+#define DOC_ERROR(msg) \
+ warn_doc_error(m_fileName.data(), lineNumber(), msg.data())
+
+#define COND_DOC_ERROR(cond, msg) \
+ do {\
+ if (cond)\
+ {\
+ DOC_ERROR(msg);\
+ return true;\
+ }\
+ }\
+ while (0)
+
+#define DBUS(name) isDBusElement(namespaceURI, localName, qName, name)
+#define EXTENSION(name) isExtensionElement(namespaceURI, localName, qName, name)
+
+// -----------------------------------------------------------------------
+// DBusXMLHandler class
+// -----------------------------------------------------------------------
+
+const QString EXTENSION_URI("http://psiamp.org/dtd/doxygen_dbusxml.dtd");
+
+/** DBus implementation of the generic QXmlDefaultHandler. */
+class DBusXMLHandler : public QXmlDefaultHandler
+{
+public:
+ DBusXMLHandler(ParserInterface * parser,
+ QXmlSimpleReader * reader,
+ const char * file_name,
+ Entry * root) :
+ m_parser(parser),
+ m_locator(reader),
+ m_currentEntry(0),
+ m_currentInterface(0),
+ m_currentMethod(0),
+ m_currentArgument(0),
+ m_currentProperty(0),
+ m_currentEnum(0),
+ m_fileName(file_name),
+ m_currentComment(0)
+ {
+ setDocumentLocator(&m_locator);
+
+ m_scopeCount = 0;
+
+ // Set up stack cleanup:
+ m_structStack.setAutoDelete(TRUE);
+ m_elementStack.setAutoDelete(TRUE);
+ m_scopeStack.setAutoDelete(TRUE);
+
+ openScopes(root);
+ }
+
+ ~DBusXMLHandler()
+ { closeScopes(); }
+
+ QString errorString()
+ { return m_errorString; }
+
+ bool startElement(const QString &namespaceURI,
+ const QString &localName,
+ const QString &qName,
+ const QXmlAttributes &attributes)
+ {
+ // add to elements stack:
+ m_elementStack.append(new ElementData(qName.utf8()));
+
+ // First we need a node.
+ if (DBUS("node"))
+ {
+ CONDITION(!m_currentNode.isEmpty(), "Node inside a node.");
+
+ const int idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(idx < 0, QCString("Anonymous node found."));
+
+ m_currentNode = attributes.value(idx).utf8();
+ // A node is actually of little interest, so do nothing here.
+ return true;
+ }
+
+ // Then we need an interface.
+ if (DBUS("interface"))
+ {
+ // We need a nodeName for interfaces:
+ CONDITION(m_currentNode.isEmpty(), "Interface without a node.");
+ CONDITION(m_currentInterface, "Interface within another interface.");
+
+ const int idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(idx < 0, QString("Interface without a name found."));
+
+ // A interface is roughly equivalent to a class:
+ m_currentInterface = createEntry();
+
+ m_currentInterface->section = Entry::CLASS_SEC;
+ m_currentInterface->spec |= Entry::Interface;
+ m_currentInterface->type = "Interface";
+ m_currentInterface->name = substitute(attributes.value(idx).utf8(), ".", "::");
+
+ openScopes(m_currentInterface);
+
+ return true;
+ }
+
+ if (DBUS("method") || DBUS("signal"))
+ {
+ // We need a interfaceName for methods and signals:
+ CONDITION(!m_currentInterface, "Method or signal found outside a interface.");
+ CONDITION(m_currentMethod, "Method or signal found inside another method or signal.");
+ CONDITION(m_currentProperty, "Methor or signal found inside a property.");
+ CONDITION(!m_structStack.isEmpty(), "Method or signal found inside a struct.");
+ CONDITION(m_currentEnum, "Methor or signal found inside a enum.");
+
+ const int idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(idx < 0, QString("Method or signal without a name found."));
+
+ m_currentMethod = createEntry();
+
+ m_currentMethod->section = Entry::FUNCTION_SEC;
+ m_currentMethod->name = attributes.value(idx).utf8();
+ m_currentMethod->mtype = Method;
+ m_currentMethod->type = "void";
+
+ if (DBUS("signal"))
+ { m_currentMethod->mtype = Signal; }
+ }
+
+ if (DBUS("arg"))
+ {
+ // We need a method for arguments:
+ CONDITION(!m_currentMethod, "Argument found outside a method or signal.");
+ CONDITION(m_currentArgument, "Argument found inside another argument.");
+
+ const int name_idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(name_idx < 0, QString("Argument without a name found."));
+ COND_DOC_ERROR(!hasType(attributes), QString("Argument without a type found."));
+
+ const int direction_idx(indexOf(attributes, "direction"));
+
+ if ((m_currentMethod->mtype == Signal &&
+ direction_idx >= 0 &&
+ attributes.value(direction_idx) != "in") ||
+ (m_currentMethod->mtype == Method &&
+ direction_idx >= 0 &&
+ attributes.value(direction_idx) != "in" &&
+ attributes.value(direction_idx) != "out"))
+ {
+ m_errorString = "Invalid direction found.";
+ return false;
+ }
+
+ m_currentArgument = new Argument;
+ m_currentArgument->type = getType(attributes).utf8();
+ m_currentArgument->name = attributes.value(name_idx).utf8();
+ if (direction_idx >= 0)
+ { m_currentArgument->attrib = attributes.value(direction_idx).utf8(); }
+ else
+ {
+ if (m_currentMethod->mtype == Signal)
+ { m_currentArgument->attrib = "in"; }
+ else
+ { m_currentArgument->attrib = "out"; }
+ }
+ }
+
+ if (DBUS("property"))
+ {
+ CONDITION(m_currentMethod, "Property found inside a method or signal.");
+ CONDITION(!m_currentInterface, "Property found outside an interface.");
+ CONDITION(m_currentProperty, "Property found inside another property.");
+ CONDITION(!m_structStack.isEmpty(), "Property found inside a struct.");
+ CONDITION(m_currentEnum, "Property found inside a enum.");
+
+ const int name_idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(name_idx < 0, QString("Anonymous property found."));
+ COND_DOC_ERROR(!hasType(attributes), QString("Property without a type found."));
+
+ const int access_idx(indexOf(attributes, "access"));
+ COND_DOC_ERROR(access_idx < 0, QString("Property without a access attribute found."));
+ COND_DOC_ERROR(attributes.value(access_idx) != "read" &&
+ attributes.value(access_idx) != "write" &&
+ attributes.value(access_idx) != "readwrite",
+ QString("Property with invalid access attribute \"%1\" found.").
+ arg(attributes.value(access_idx)));
+
+ m_currentProperty = createEntry();
+
+ m_currentProperty->section = Entry::FUNCTION_SEC;
+
+ if (attributes.value(access_idx) == "read" ||
+ attributes.value(access_idx) == "readwrite")
+ { m_currentProperty->spec |= Entry::Readable; }
+
+ if (attributes.value(access_idx) == "write" ||
+ attributes.value(access_idx) == "readwrite")
+ { m_currentProperty->spec |= Entry::Writable; }
+
+ m_currentProperty->name = attributes.value(name_idx).utf8();
+ m_currentProperty->mtype = Property;
+ m_currentProperty->type = getType(attributes).utf8();
+ }
+
+ if (EXTENSION("namespace"))
+ {
+ CONDITION(m_currentNode.isEmpty(), "Namespace found outside a node.");
+ CONDITION(m_currentInterface, "Namespace found inside an interface.");
+
+ const int idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(idx < 0, QString("Anonymous namespace found."));
+
+ m_namespaceStack.append(openNamespace(attributes.value(idx)));
+ openScopes(m_namespaceStack.last());
+ }
+
+ if (EXTENSION("struct"))
+ {
+ CONDITION(m_currentMethod, "Struct found inside a method or signal.");
+ CONDITION(m_currentProperty, "Struct found inside a property.");
+ CONDITION(m_currentEnum, "Struct found inside an enum.");
+
+ const int idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(idx < 0, QString("Anonymous struct found."));
+
+ Entry * current_struct = createEntry();
+ current_struct->section = Entry::CLASS_SEC;
+ current_struct->spec = Entry::Struct;
+ current_struct->name = attributes.value(idx).utf8();
+
+ openScopes(current_struct);
+
+ current_struct->type = current_struct->name + " struct";
+
+ m_structStack.append(new StructData(current_struct));
+ }
+
+ if (EXTENSION("member"))
+ {
+ CONDITION(m_structStack.isEmpty(), "Member found outside of struct.");
+
+ const int name_idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(name_idx < 0, QString("Anonymous member found."));
+ COND_DOC_ERROR(!hasType(attributes), QString("Member without a type found."));
+
+ createEntry();
+
+ m_currentEntry->section = Entry::VARIABLE_SEC;
+ m_currentEntry->name = attributes.value(name_idx).utf8();
+ m_currentEntry->type = getType(attributes).utf8();
+
+ QString type(getDBusType(m_currentEntry->type));
+ m_structStack.last()->type.append(type.utf8());
+ }
+
+ if (EXTENSION("enum") || EXTENSION("flagset"))
+ {
+ CONDITION(m_currentMethod, "Enum found inside a method or signal.");
+ CONDITION(m_currentProperty, "Enum found inside a property.");
+
+ const int name_idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(name_idx < 0, QString("Anonymous enum found."));
+
+ const int type_idx(indexOf(attributes, "type"));
+ QString type = "u";
+ if (type_idx >= 0)
+ { type = attributes.value(type_idx); }
+ if (type != "y" && type != "q" && type != "u" && type != "t")
+ { DOC_ERROR(QString("Invalid enum type \"%1\" found.").arg(type)); }
+
+ m_currentEnum = createEntry();
+ m_currentEnum->section = Entry::ENUM_SEC;
+ m_currentEnum->name = attributes.value(name_idx).utf8();
+
+ openScopes(m_currentEnum);
+
+ m_currentEnum->type = m_currentEntry->name + " enum";
+
+ addNamedType(type.utf8());
+ }
+
+ if (EXTENSION("value"))
+ {
+ CONDITION(!m_currentEnum, "Value found outside an enum.");
+
+ const int name_idx(indexOf(attributes, "name"));
+ COND_DOC_ERROR(name_idx < 0, QString("Anonymous value found."));
+
+ const int value_idx(indexOf(attributes, "value"));
+
+ createEntry();
+
+ m_currentEntry->section = Entry::VARIABLE_SEC;
+ m_currentEntry->name = attributes.value(name_idx).utf8();
+ m_currentEntry->type = m_currentEnum->name; // "@"; // enum marker!
+ if (value_idx >= 0)
+ { m_currentEntry->initializer = attributes.value(value_idx).utf8(); }
+ }
+
+ return true;
+ }
+
+ bool endElement(const QString &namespaceURI,
+ const QString &localName,
+ const QString &qName)
+ {
+ // Clean up elements stack:
+ // Since we made sure to get the elements in the proper order when
+ // adding we do not need to do so again here.
+ COND_DOC_ERROR(m_elementStack.last()->element != qName.utf8(),
+ QString("Malformed XML: Unexpected closing element found.").
+ arg(m_elementStack.last()->element).utf8());
+ m_elementStack.removeLast();
+
+ // Interface:
+ if (DBUS("interface"))
+ {
+ CONDITION(!m_currentInterface, "end of interface found without start.");
+ m_currentInterface->endBodyLine = lineNumber();
+ closeScopes();
+ m_currentInterface = 0;
+ }
+
+ if (DBUS("method") || DBUS("signal"))
+ {
+ CONDITION(!m_currentMethod, "end of method found without start.");
+ CONDITION(!m_currentInterface, "end of method found outside interface.");
+ m_currentMethod->endBodyLine = lineNumber();
+ m_currentInterface->addSubEntry(m_currentMethod);
+ m_currentMethod = 0;
+ }
+
+ if (DBUS("property"))
+ {
+ CONDITION(!m_currentProperty, "end of property found without start.");
+ CONDITION(!m_currentInterface, "end of property found outside interface.");
+ m_currentProperty->endBodyLine = lineNumber();
+ m_currentInterface->addSubEntry(m_currentProperty);
+ m_currentProperty = 0;
+ }
+
+ if (DBUS("arg"))
+ {
+ CONDITION(!m_currentMethod, "end of arg found outside method.");
+ m_currentMethod->argList->append(m_currentArgument);
+ m_currentArgument = 0;
+ }
+
+ if (EXTENSION("namespace"))
+ {
+ Entry * current = m_namespaceStack.last();
+ CONDITION(!current, "end of namespace without start.");
+ m_namespaceStack.removeLast();
+
+ current->endBodyLine = lineNumber();
+ closeScopes();
+ }
+
+ if (EXTENSION("struct"))
+ {
+ StructData * data = m_structStack.last();
+ CONDITION(!data, "end of struct without start.");
+
+ data->entry->endBodyLine = lineNumber();
+
+ QString current_type;
+ current_type.append(QString("("));
+ current_type.append(data->type);
+ current_type.append(QString(")"));
+
+ addNamedType(current_type.utf8());
+
+ closeScopes();
+
+ m_structStack.removeLast();
+ }
+
+ if (EXTENSION("member"))
+ {
+ StructData * data = m_structStack.last();
+ CONDITION(!data, "end of member outside struct.");
+ data->entry->addSubEntry(m_currentEntry);
+ }
+
+ if (EXTENSION("enum") || EXTENSION("flagset"))
+ {
+ CONDITION(!m_currentEnum, "end of enum without start.");
+ m_currentEnum->endBodyLine = lineNumber();
+ closeScopes();
+
+ m_currentEnum = 0;
+ }
+
+ if (EXTENSION("value"))
+ {
+ CONDITION(!m_currentEntry, "end of value without start");
+ m_currentEntry->endBodyLine = lineNumber();
+
+ m_currentEnum->addSubEntry(m_currentEntry);
+ }
+
+ return true;
+ }
+
+ bool characters(const QString & /*chars*/)
+ { return true; }
+
+ bool comment(const QString & comment_)
+ {
+ if (m_currentComment)
+ { handleComment(); }
+
+ m_currentComment = new CommentData(m_fileName, lineNumber(), comment_.utf8());
+
+ if (m_currentComment->shouldIgnore)
+ {
+ delete m_currentComment;
+ m_currentComment = 0;
+ return true;
+ }
+
+ if (m_currentComment->associateWithPrevious)
+ { handleComment(); }
+
+ return true;
+ }
+
+ void handleComment()
+ {
+ if (m_currentComment == 0 || m_currentEntry == 0)
+ { return; }
+
+ QCString text(m_currentComment->text);
+
+ m_currentEntry->docFile = m_currentComment->fileName;
+ m_currentEntry->docLine = m_currentComment->line;
+
+ int position(0);
+ bool needs_entry(false);
+ bool brief(false);
+ Protection prot(Public);
+ int lineNr = lineNumber();
+
+ while (parseCommentBlock(m_parser,
+ m_currentEntry,
+ text, m_fileName.data(),
+ lineNr,
+ brief, m_currentComment->isJavaStyle,
+ false,
+ prot,
+ position,
+ needs_entry))
+ {
+ if (needs_entry) { createEntry(); }
+ }
+ if (needs_entry) { createEntry(); }
+
+ delete m_currentComment;
+ m_currentComment = 0;
+ }
+
+ QXmlLocator * locator()
+ { return &m_locator; }
+
+ int lineNumber()
+ { return m_locator.lineNumber(); }
+
+ void setSection()
+ {
+ Entry * current = createEntry();
+ current->reset();
+
+ current->name = m_fileName;
+ current->section = Entry::SOURCE_SEC;
+
+ // Open/Close the scope to do the bookkeeping:
+ openScopes(current);
+ closeScopes();
+ }
+
+private:
+ bool isDBusElement(const QString & namespaceURI,
+ const QString & localName,
+ const QString & qName,
+ const QString & element)
+ {
+ return (namespaceURI.isEmpty() && localName == element && qName == element) ||
+ (namespaceURI.isEmpty() && localName.isEmpty() && qName == element);
+ }
+
+ bool isExtensionElement(const QString & namespaceURI,
+ const QString & localName,
+ const QString & qName,
+ const QString & element)
+ {
+ (void)qName;
+
+ return namespaceURI == EXTENSION_URI && localName == element;
+ }
+
+ bool hasType(const QXmlAttributes & attributes)
+ {
+ const int type_idx(indexOf(attributes, "type"));
+ const int named_type_idx(indexOf(attributes, "named-type"));
+
+ return named_type_idx >= 0 || type_idx >= 0;
+ }
+
+ QString getType(const QXmlAttributes & attributes)
+ {
+ const int type_idx(indexOf(attributes, "type"));
+ const int named_type_idx(indexOf(attributes, "named-type"));
+
+ QCString type;
+
+ if (named_type_idx >= 0)
+ {
+ type = attributes.value(named_type_idx).utf8();
+ if (type.left(2)!="::")
+ { type = getCurrentScope(attributes.value(named_type_idx).utf8()); }
+ else
+ { type = type.mid(2); }
+ if (m_namedTypeMap.contains(type))
+ {
+ if (type_idx >= 0)
+ {
+ const QCString dbus_type(attributes.value(type_idx).utf8());
+ if (dbus_type != m_namedTypeMap[type])
+ {
+ DOC_ERROR(QString("Type \"%1\" does not match up with "
+ "previous definition of named type \"%2\" (which was \"%3\".").
+ arg(dbus_type).
+ arg(type).
+ arg(m_namedTypeMap[type]));
+ }
+ }
+ return type;
+ }
+
+ DOC_ERROR(QString("Undefined named type \"%1\" used.").arg(type));
+ }
+
+ if (type_idx >= 0)
+ {
+ type = attributes.value(type_idx).utf8();
+
+ QRegExp reg_exp(QCString("(a?[ybnqiuxdtsogv]|a[{]sv[}])"));
+ if (reg_exp.match(type.data()))
+ { return type; }
+
+ DOC_ERROR(QString("Unnamed complex D-Bus type \"%1\" found.").arg(type));
+ }
+
+ return QString();
+ }
+
+ QString getDBusType(const QCString & type)
+ {
+ QCString scoped_type = type;
+ if (!scoped_type.contains("::"))
+ { scoped_type = getCurrentScope(type); }
+
+ if (m_namedTypeMap.contains(scoped_type))
+ { return m_namedTypeMap[scoped_type]; }
+ else
+ { return type; }
+ }
+
+ void addNamedType(const QCString &type)
+ {
+ QCString scoped_name(getCurrentScope());
+
+ if (m_namedTypeMap.contains(scoped_name))
+ {
+ DOC_ERROR(QString("Named type \"%1\" is already defined.").arg(scoped_name));
+ return;
+ }
+
+ m_namedTypeMap.insert(scoped_name, type);
+ }
+
+ QCString getCurrentScope(const QCString & type = QCString())
+ {
+ QCString scoped_name;
+ if (!m_scopeStack.isEmpty())
+ {
+ scoped_name = m_scopeStack.last()->scope->name;
+ scoped_name.append("::");
+ }
+ if (!type.isEmpty())
+ { scoped_name.append(type); }
+ else
+ { scoped_name = scoped_name.left(scoped_name.length() - 2); }
+
+ return scoped_name;
+ }
+
+ int indexOf(const QXmlAttributes & attributes, const QString & name,
+ const QString & type = "CDATA", const bool mandatory = true)
+ {
+ const int idx(attributes.index(name));
+ if (idx < 0 || idx > attributes.length()) { return -1; }
+ if (attributes.type(idx) != type) { return -1; }
+ if (mandatory && attributes.value(idx).isEmpty()) { return -1; }
+
+ return idx;
+ }
+
+ Entry * createEntry()
+ {
+ Entry * entry = new Entry();
+
+ entry->protection = Public ;
+ entry->virt = Normal;
+ entry->stat = false;
+ entry->lang = SrcLangExt_XML;
+ entry->spec = 0;
+
+ entry->fileName = m_fileName;
+ entry->startLine = lineNumber();
+ entry->bodyLine = lineNumber();
+
+ entry->callGraph = false;
+ entry->callerGraph = false;
+
+ initGroupInfo(entry);
+
+ m_currentEntry = entry;
+
+ handleComment();
+
+ return entry;
+ }
+
+ void openScopes(Entry * object)
+ {
+ int cur_scope_separator_pos = 0;
+ int last_scope_separator_pos = 0;
+ while (0 <= (cur_scope_separator_pos = object->name.find("::", last_scope_separator_pos)))
+ {
+ QString scope = object->name.mid(last_scope_separator_pos,
+ cur_scope_separator_pos - last_scope_separator_pos);
+ last_scope_separator_pos = cur_scope_separator_pos + 2;
+
+ Entry * current_namespace = openNamespace(scope);
+
+ if (!m_scopeStack.isEmpty())
+ { m_scopeStack.last()->scope->addSubEntry(current_namespace); }
+
+ m_scopeStack.append(new ScopeData(current_namespace, m_scopeCount));
+ }
+
+ QCString scoped_name(getCurrentScope());
+ if (!scoped_name.isEmpty())
+ { scoped_name.append("::"); }
+ scoped_name.append(object->name.mid(last_scope_separator_pos));
+
+ object->name = scoped_name;
+
+ if (!m_scopeStack.isEmpty())
+ { m_scopeStack.last()->scope->addSubEntry(object); }
+ m_scopeStack.append(new ScopeData(object, m_scopeCount));
+
+ ++m_scopeCount;
+ }
+
+ Entry * openNamespace(const QString & name)
+ {
+ Entry * current_namespace = createEntry();
+ QCString scoped_name(getCurrentScope());
+ if (!scoped_name.isEmpty())
+ { scoped_name.append("::"); }
+ scoped_name.append(name.utf8());
+ current_namespace->name = scoped_name;
+ current_namespace->section = Entry::NAMESPACE_SEC;
+ current_namespace->type = "namespace" ;
+
+ return current_namespace;
+ }
+
+ void closeScopes()
+ {
+ const int current_scope_count(m_scopeStack.last()->count);
+
+ // Do not close the root scope.
+ if (current_scope_count == 0)
+ { return; }
+
+ while (current_scope_count == m_scopeStack.last()->count)
+ { m_scopeStack.removeLast(); }
+ }
+
+ ParserInterface * m_parser;
+
+ QXmlLocator m_locator;
+ QCString m_currentNode; // Nodes can not be nested, no entry necessary.
+
+ struct ElementData
+ {
+ ElementData(const QCString & e) :
+ element(e)
+ { }
+ ~ElementData() { }
+
+ QCString element; //*< The element name
+ QCString text; //*< The actual xml code.
+ };
+ QList<ElementData> m_elementStack;
+
+ Entry * m_currentEntry; // The currently open entry.
+
+ Entry * m_currentInterface; // Interfaces can not be nested.
+ Entry * m_currentMethod; // Methods can not be nested.
+ Argument * m_currentArgument; // Arguments can not be nested.
+ Entry * m_currentProperty; // Properties can not be nested.
+ Entry * m_currentEnum; // Enums can not be nested.
+ QList<Entry> m_namespaceStack;
+
+ struct StructData
+ {
+ StructData(Entry * e) : entry(e) { }
+ ~StructData() { }
+
+ QCString type;
+ Entry * entry;
+ };
+ QList<StructData> m_structStack; // Structs can be nested.
+
+ struct ScopeData
+ {
+ ScopeData(Entry * s, int c) :
+ scope(s),
+ count(c)
+ { }
+ ~ScopeData() { }
+
+ Entry * scope;
+ int count;
+ };
+ QList<ScopeData> m_scopeStack; // Scopes are nested.
+
+ QCString m_fileName;
+
+ struct CommentData
+ {
+ CommentData(const QCString & f, const int l, const QCString & t) :
+ isJavaStyle(false),
+ isQtStyle(false),
+ line(l),
+ fileName(f)
+ {
+ isJavaStyle = t.length()>0 && t.at(0)=='*';
+ isQtStyle = t.length()>0 && t.at(0)=='!';
+ shouldIgnore = (!isJavaStyle && !isQtStyle);
+ associateWithPrevious = (t.length()>1 && t.at(1)=='<');
+ if (associateWithPrevious)
+ { text = t.mid(2); }
+ else
+ { text = t.mid(1); }
+ }
+ ~CommentData() { }
+
+ QCString text;
+ bool isJavaStyle;
+ bool isQtStyle;
+ bool shouldIgnore;
+ bool associateWithPrevious;
+ int line;
+ QCString fileName;
+ };
+ CommentData * m_currentComment;
+
+ int m_scopeCount; //*< unique scope id.
+
+ QString m_errorString;
+
+ QMap<QCString, QCString> m_namedTypeMap;
+};
+
+// -----------------------------------------------------------------------
+// DBusXMLScanner
+// -----------------------------------------------------------------------
+
+DBusXMLScanner::DBusXMLScanner()
+{ }
+
+DBusXMLScanner::~DBusXMLScanner()
+{ }
+
+void DBusXMLScanner::parseInput(const char * fileName,
+ const char * /* fileBuf */,
+ Entry * root)
+{
+ QFile inputFile(fileName);
+
+ QXmlInputSource inputSource(inputFile);
+ QXmlSimpleReader reader;
+
+ DBusXMLHandler handler(this, &reader, fileName, root);
+ reader.setContentHandler(&handler);
+ reader.setErrorHandler(&handler);
+ reader.setLexicalHandler(&handler);
+
+ groupEnterFile(fileName, 1);
+ handler.setSection();
+ reader.parse(inputSource);
+
+ if (!handler.errorString().isEmpty())
+ { err("DBus XML Parser: Error at line %d: %s\n",
+ handler.locator()->lineNumber(),handler.errorString().utf8().data()); }
+
+ groupLeaveFile(fileName, 1);
+}
+
+bool DBusXMLScanner::needsPreprocessing(const QCString & /* extension */)
+{ return (false); }
+
+void DBusXMLScanner::parseCode(CodeOutputInterface & /* codeOutIntf */,
+ const char * /* scopeName */,
+ const QCString & /* input */,
+ bool /* isExampleBlock */,
+ const char * /* exampleName */,
+ FileDef * /* fileDef */,
+ int /* startLine */,
+ int /* endLine */,
+ bool /* inlineFragment */,
+ MemberDef * /* memberDef */,
+ bool /*showLineNumbers*/,
+ Definition * /* searchCtx */)
+{ }
+
+void DBusXMLScanner::resetCodeParserState()
+{ }
+
+void DBusXMLScanner::parsePrototype(const char * /* text */)
+{ }