Implement new plugin mechanism

moc can now embed meta information about the plugin
inside the plugin itself. This information can
be queried by Qt without having to load the plugin.

Source compatibility with the old plugin loading
mechanism is still there, but will be removed before
Qt 5.0.

Change-Id: I03e4196ddfed07d0fe94acca40d5de8a6ce7f920
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Lars Knoll 2012-02-06 23:36:17 +01:00 committed by Qt by Nokia
parent 556dd0228a
commit 7184456f9a
17 changed files with 653 additions and 273 deletions

View File

@ -76,6 +76,7 @@ class QString;
# define emit # define emit
#endif #endif
#define Q_CLASSINFO(name, value) #define Q_CLASSINFO(name, value)
#define Q_PLUGIN_METADATA(x)
#define Q_INTERFACES(x) #define Q_INTERFACES(x)
#define Q_PROPERTY(text) #define Q_PROPERTY(text)
#define Q_PRIVATE_PROPERTY(d, text) #define Q_PRIVATE_PROPERTY(d, text)

View File

@ -203,7 +203,7 @@ int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library
qDebug() << "++++" << i << shnam; qDebug() << "++++" << i << shnam;
#endif #endif
if (qstrcmp(shnam, ".qtplugin") == 0 || qstrcmp(shnam, ".rodata") == 0) { if (qstrcmp(shnam, ".qtmetadata") == 0 || qstrcmp(shnam, ".qtplugin") == 0 || qstrcmp(shnam, ".rodata") == 0) {
if (!(sh.type & 0x1)) { if (!(sh.type & 0x1)) {
if (shnam[1] == 'r') { if (shnam[1] == 'r') {
if (lib) if (lib)
@ -227,7 +227,7 @@ int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library
*pos = sh.offset; *pos = sh.offset;
*sectionlen = sh.size - 1; *sectionlen = sh.size - 1;
if (shnam[1] == 'q') if (shnam[1] == 'q')
return Ok; return shnam[3] == 'm' ? QtMetaDataSection : QtPluginSection;
} }
s += e_shentsize; s += e_shentsize;
} }

View File

@ -72,7 +72,7 @@ typedef quintptr qelfaddr_t;
class QElfParser class QElfParser
{ {
public: public:
enum {Ok = 0, NotElf = 1, NoQtSection = 2, Corrupt = 3}; enum { QtMetaDataSection, QtPluginSection, NoQtSection, NotElf, Corrupt };
enum {ElfLittleEndian = 0, ElfBigEndian = 1}; enum {ElfLittleEndian = 0, ElfBigEndian = 1};
struct ElfSectionHeader struct ElfSectionHeader

View File

@ -51,6 +51,10 @@
#include "qpluginloader.h" #include "qpluginloader.h"
#include "private/qobject_p.h" #include "private/qobject_p.h"
#include "private/qcoreapplication_p.h" #include "private/qcoreapplication_p.h"
#include "qjsondocument.h"
#include "qjsonvalue.h"
#include "qjsonobject.h"
#include "qjsonarray.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -137,29 +141,44 @@ void QFactoryLoader::update()
continue; continue;
} }
QStringList keys; QStringList keys;
if (!library->loadPlugin()) { if (library->compatPlugin) {
if (qt_debug_component()) { qWarning() << "Compat plugin, need to load for accessing meta data";
qDebug() << library->errorString; if (!library->loadPlugin()) {
qDebug() << " could not load"; if (qt_debug_component()) {
qDebug() << library->errorString;
qDebug() << " could not load";
}
library->release();
continue;
} }
library->release();
continue; if (!library->inst)
library->inst = library->instance();
QObject *instance = library->inst.data();
if (!instance) {
library->release();
// ignore plugins that have a valid signature but cannot be loaded.
continue;
}
QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
if (instance && factory && instance->qt_metacast(d->iid))
keys = factory->keys();
} else {
QString iid = library->metaData.value(QLatin1String("IID")).toString();
if (iid == QLatin1String(d->iid.constData(), d->iid.size())) {
QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject();
QJsonArray k = object.value(QLatin1String("Keys")).toArray();
for (int i = 0; i < k.size(); ++i) {
QString s = k.at(i).toString();
keys += s;
}
}
if (qt_debug_component())
qDebug() << "Got keys from plugin meta data" << keys;
} }
if (!library->inst)
library->inst = library->instance();
QObject *instance = library->inst.data();
if (!instance) {
library->release();
// ignore plugins that have a valid signature but cannot be loaded.
continue;
}
QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
if (instance && factory && instance->qt_metacast(d->iid))
keys = factory->keys();
if (keys.isEmpty())
library->unload();
if (keys.isEmpty()) { if (keys.isEmpty()) {
library->unload();
library->release(); library->release();
continue; continue;
} }
@ -173,7 +192,12 @@ void QFactoryLoader::update()
if (!d->cs) if (!d->cs)
key = key.toLower(); key = key.toLower();
QLibraryPrivate *previous = d->keyMap.value(key); QLibraryPrivate *previous = d->keyMap.value(key);
if (!previous || (previous->qt_version > QT_VERSION && library->qt_version <= QT_VERSION)) { int prev_qt_version = 0;
if (previous) {
prev_qt_version = (int)previous->metaData.value(QLatin1String("version")).toDouble();
}
int qt_version = (int)library->metaData.value(QLatin1String("version")).toDouble();
if (!previous || (prev_qt_version > QT_VERSION && qt_version <= QT_VERSION)) {
d->keyMap[key] = library; d->keyMap[key] = library;
d->keyList += keys.at(k); d->keyList += keys.at(k);
} }
@ -200,23 +224,76 @@ QStringList QFactoryLoader::keys() const
Q_D(const QFactoryLoader); Q_D(const QFactoryLoader);
QMutexLocker locker(&d->mutex); QMutexLocker locker(&d->mutex);
QStringList keys = d->keyList; QStringList keys = d->keyList;
QObjectList instances = QPluginLoader::staticInstances(); QVector<QStaticPlugin> staticPlugins = QLibraryPrivate::staticPlugins();
for (int i = 0; i < instances.count(); ++i) for (int i = 0; i < staticPlugins.count(); ++i) {
if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i))) if (staticPlugins.at(i).metaData) {
if (instances.at(i)->qt_metacast(d->iid)) const char *rawMetaData = staticPlugins.at(i).metaData();
keys += factory->keys(); QJsonObject object = QLibraryPrivate::fromRawMetaData(rawMetaData).object();
if (object.value(QLatin1String("IID")) != QLatin1String(d->iid.constData(), d->iid.size()))
continue;
QJsonObject meta = object.value(QLatin1String("MetaData")).toObject();
QJsonArray a = meta.value(QLatin1String("Keys")).toArray();
for (int i = 0; i < a.size(); ++i) {
QString s = a.at(i).toString();
if (!s.isEmpty())
keys += s;
}
} else {
// compat plugin
QObject *instance = staticPlugins.at(i).instance();
QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
if (instance && factory && instance->qt_metacast(d->iid))
keys = factory->keys();
}
}
return keys; return keys;
} }
QList<QJsonObject> QFactoryLoader::metaData() const
{
Q_D(const QFactoryLoader);
QMutexLocker locker(&d->mutex);
QList<QJsonObject> metaData;
for (int i = 0; i < d->libraryList.size(); ++i)
metaData.append(d->libraryList.at(i)->metaData);
QVector<QStaticPlugin> staticPlugins = QLibraryPrivate::staticPlugins();
for (int i = 0; i < staticPlugins.count(); ++i) {
if (staticPlugins.at(i).metaData) {
const char *rawMetaData = staticPlugins.at(i).metaData();
QJsonObject object = QLibraryPrivate::fromRawMetaData(rawMetaData).object();
if (object.value(QLatin1String("IID")) != QLatin1String(d->iid.constData(), d->iid.size()))
continue;
QJsonObject meta = object.value(QLatin1String("MetaData")).toObject();
metaData.append(meta);
} else {
// compat plugins
QObject *instance = staticPlugins.at(i).instance();
QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
if (instance && factory && instance->qt_metacast(d->iid)) {
QJsonObject meta;
QJsonArray a = QJsonArray::fromStringList(factory->keys());
meta.insert(QLatin1String("Keys"), a);
metaData.append(meta);
}
}
}
return metaData;
}
QObject *QFactoryLoader::instance(const QString &key) const QObject *QFactoryLoader::instance(const QString &key) const
{ {
Q_D(const QFactoryLoader); Q_D(const QFactoryLoader);
QMutexLocker locker(&d->mutex); QMutexLocker locker(&d->mutex);
QObjectList instances = QPluginLoader::staticInstances(); QVector<QStaticPlugin> staticPlugins = QLibraryPrivate::staticPlugins();
for (int i = 0; i < instances.count(); ++i) for (int i = 0; i < staticPlugins.count(); ++i) {
if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i))) QObject *instance = staticPlugins.at(i).instance();
if (instances.at(i)->qt_metacast(d->iid) && factory->keys().contains(key, Qt::CaseInsensitive)) if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance))
return instances.at(i); if (instance->qt_metacast(d->iid) && factory->keys().contains(key, Qt::CaseInsensitive))
return instance;
}
QString lowered = d->cs ? key : key.toLower(); QString lowered = d->cs ? key : key.toLower();
if (QLibraryPrivate* library = d->keyMap.value(lowered)) { if (QLibraryPrivate* library = d->keyMap.value(lowered)) {
@ -234,6 +311,26 @@ QObject *QFactoryLoader::instance(const QString &key) const
return 0; return 0;
} }
QObject *QFactoryLoader::instance(int index) const
{
Q_D(const QFactoryLoader);
if (index < 0 || index >= d->libraryList.size())
return 0;
QLibraryPrivate *library = d->libraryList.at(index);
if (library->instance || library->loadPlugin()) {
if (!library->inst)
library->inst = library->instance();
QObject *obj = library->inst.data();
if (obj) {
if (!obj->parent())
obj->moveToThread(QCoreApplicationPrivate::mainThread());
return obj;
}
}
return 0;
}
#if defined(Q_OS_UNIX) && !defined (Q_OS_MAC) #if defined(Q_OS_UNIX) && !defined (Q_OS_MAC)
QLibraryPrivate *QFactoryLoader::library(const QString &key) const QLibraryPrivate *QFactoryLoader::library(const QString &key) const
{ {

View File

@ -55,8 +55,8 @@
#include "QtCore/qobject.h" #include "QtCore/qobject.h"
#include "QtCore/qstringlist.h" #include "QtCore/qstringlist.h"
#include "QtCore/qjsonobject.h"
#include "private/qlibrary_p.h" #include "private/qlibrary_p.h"
#ifndef QT_NO_LIBRARY #ifndef QT_NO_LIBRARY
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -74,8 +74,11 @@ public:
Qt::CaseSensitivity = Qt::CaseSensitive); Qt::CaseSensitivity = Qt::CaseSensitive);
~QFactoryLoader(); ~QFactoryLoader();
QStringList keys() const; QT_DEPRECATED QStringList keys() const;
QObject *instance(const QString &key) const; QList<QJsonObject> metaData() const;
QT_DEPRECATED QObject *instance(const QString &key) const;
QObject *instance(int index) const;
#if defined(Q_OS_UNIX) && !defined (Q_OS_MAC) #if defined(Q_OS_UNIX) && !defined (Q_OS_MAC)
QLibraryPrivate *library(const QString &key) const; QLibraryPrivate *library(const QString &key) const;

View File

@ -60,6 +60,9 @@
#include <qdebug.h> #include <qdebug.h>
#include <qvector.h> #include <qvector.h>
#include <qdir.h> #include <qdir.h>
#include <qendian.h>
#include <qjsondocument.h>
#include <qjsonvalue.h>
#include "qelfparser_p.h" #include "qelfparser_p.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -330,7 +333,7 @@ static long qt_find_pattern(const char *s, ulong s_len,
information could not be read. information could not be read.
Returns true if version information is present and successfully read. Returns true if version information is present and successfully read.
*/ */
static bool qt_unix_query(const QString &library, uint *version, bool *debug, QLibraryPrivate *lib = 0) static bool qt_unix_query(const QString &library, QLibraryPrivate *lib)
{ {
QFile file(library); QFile file(library);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
@ -357,35 +360,71 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QL
/* /*
ELF binaries on GNU, have .qplugin sections. ELF binaries on GNU, have .qplugin sections.
*/ */
bool hasMetaData = false;
long pos = 0; long pos = 0;
const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; const char oldPattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA";
const ulong oldPlen = qstrlen(oldPattern);
const char pattern[] = "QTMETADATA ";
const ulong plen = qstrlen(pattern); const ulong plen = qstrlen(pattern);
#if defined (Q_OF_ELF) && defined(Q_CC_GNU) #if defined (Q_OF_ELF) && defined(Q_CC_GNU)
int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen); int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen);
if (r == QElfParser::NoQtSection) { if (r == QElfParser::Corrupt || r == QElfParser::NotElf) {
if (lib && qt_debug_component()) {
qWarning("QElfParser: %s",qPrintable(lib->errorString));
}
return false;
} else if (r == QElfParser::NoQtSection || r == QElfParser::QtPluginSection) {
if (pos > 0) { if (pos > 0) {
// find inside .rodata // find inside .rodata
long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen); long rel = qt_find_pattern(filedata + pos, fdlen, oldPattern, oldPlen);
if (rel < 0) { if (rel < 0) {
pos = -1; pos = -1;
} else { } else {
pos += rel; pos += rel;
} }
} else { } else {
pos = qt_find_pattern(filedata, fdlen, pattern, plen); pos = qt_find_pattern(filedata, fdlen, oldPattern, oldPlen);
} }
} else if (r != QElfParser::Ok) { } else if (r == QElfParser::QtMetaDataSection) {
if (lib && qt_debug_component()) { long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
qWarning("QElfParser: %s",qPrintable(lib->errorString)); if (rel < 0)
} pos = -1;
return false; else
pos += rel;
hasMetaData = true;
} }
#else #else
pos = qt_find_pattern(filedata, fdlen, pattern, plen); pos = qt_find_pattern(filedata, fdlen, pattern, plen);
if (pos > 0)
hasMetaData = true;
else
pos = qt_find_pattern(filedata, fdlen, oldPattern, oldPlen);
#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) #endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
bool ret = false; bool ret = false;
if (pos >= 0)
ret = qt_parse_pattern(filedata + pos, version, debug); if (pos >= 0) {
if (hasMetaData) {
const char *data = filedata + pos;
QJsonDocument doc = QLibraryPrivate::fromRawMetaData(data);
lib->metaData = doc.object();
lib->compatPlugin = false;
if (qt_debug_component())
qWarning("Found metadata in lib %s, metadata=\n%s\n",
library.toLocal8Bit().constData(), doc.toJson().constData());
ret = !doc.isNull();
} else {
qWarning("Old plugin format found in lib %s", library.toLocal8Bit().constData());
uint version;
bool isDebug;
ret = qt_parse_pattern(filedata + pos, &version, &isDebug);
if (ret) {
lib->metaData.insert(QLatin1String("version"), (int)version);
lib->metaData.insert(QLatin1String("debug"), isDebug);
lib->compatPlugin = true;
}
}
}
if (!ret && lib) if (!ret && lib)
lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library); lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
@ -446,8 +485,9 @@ static LibraryMap *libraryMap()
} }
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version) QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
:pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), qt_version(0), : pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin) compatPlugin(false), loadHints(0),
libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin)
{ libraryMap()->insert(canonicalFileName, this); } { libraryMap()->insert(canonicalFileName, this); }
QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version) QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version)
@ -488,6 +528,8 @@ bool QLibraryPrivate::load()
return false; return false;
bool ret = load_sys(); bool ret = load_sys();
if (qt_debug_component())
qDebug() << "loaded library" << fileName;
if (ret) { if (ret) {
//when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted
//this allows to unload the library at a later time //this allows to unload the library at a later time
@ -643,13 +685,9 @@ const char* qt_try_versioninfo(void *pfn, bool *exceptionThrown)
} }
#endif #endif
#ifdef Q_CC_BOR
typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)();
#else
typedef const char * (*QtPluginQueryVerificationDataFunction)(); typedef const char * (*QtPluginQueryVerificationDataFunction)();
#endif
bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt_version, bool *debug, bool *exceptionThrown) bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, QLibraryPrivate *priv, bool *exceptionThrown)
{ {
*exceptionThrown = false; *exceptionThrown = false;
const char *szData = 0; const char *szData = 0;
@ -662,9 +700,41 @@ bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt
#else #else
szData = pfn(); szData = pfn();
#endif #endif
return qt_parse_pattern(szData, qt_version, debug); uint qt_version;
bool debug;
if (qt_parse_pattern(szData, &qt_version, &debug)) {
priv->metaData.insert(QLatin1String("version"), (int)qt_version);
priv->metaData.insert(QLatin1String("debug"), debug);
priv->compatPlugin = true;
return true;
}
return false;
} }
bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryPrivate *priv, bool *exceptionThrown)
{
*exceptionThrown = false;
const char *szData = 0;
if (!pfn)
return false;
#ifdef QT_USE_MS_STD_EXCEPTION
szData = qt_try_versioninfo((void *)pfn, exceptionThrown);
if (*exceptionThrown)
return false;
#else
szData = pfn();
#endif
if (!szData)
return false;
QJsonDocument doc = QLibraryPrivate::fromRawMetaData(szData);
if (doc.isNull())
return false;
priv->metaData = doc.object();
priv->compatPlugin = false;
return true;
}
bool QLibraryPrivate::isPlugin() bool QLibraryPrivate::isPlugin()
{ {
errorString.clear(); errorString.clear();
@ -672,7 +742,6 @@ bool QLibraryPrivate::isPlugin()
return pluginState == IsAPlugin; return pluginState == IsAPlugin;
#ifndef QT_NO_PLUGIN_CHECK #ifndef QT_NO_PLUGIN_CHECK
bool debug = !QLIBRARY_AS_DEBUG;
bool success = false; bool success = false;
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
@ -692,7 +761,7 @@ bool QLibraryPrivate::isPlugin()
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
if (!pHnd) { if (!pHnd) {
// use unix shortcut to avoid loading the library // use unix shortcut to avoid loading the library
success = qt_unix_query(fileName, &qt_version, &debug, this); success = qt_unix_query(fileName, this);
} else } else
#endif #endif
{ {
@ -713,24 +782,50 @@ bool QLibraryPrivate::isPlugin()
temporary_load = load_sys(); temporary_load = load_sys();
#endif #endif
} }
#ifdef Q_OS_WIN QtPluginQueryVerificationDataFunction getMetaData = NULL;
QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction)
#ifdef Q_OS_WINCE
::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data")
#else
::GetProcAddress(hTempModule, "qt_plugin_query_verification_data")
#endif
: (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
#else
QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL;
qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
#endif
bool exceptionThrown = false; bool exceptionThrown = false;
bool ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction, bool ret = false;
&qt_version, &debug, &exceptionThrown); #ifdef Q_OS_WIN
if (hTempModule) {
getMetaData = (QtPluginQueryVerificationDataFunction)
#ifdef Q_OS_WINCE
::GetProcAddress(hTempModule, L"qt_plugin_query_metadata")
#else
::GetProcAddress(hTempModule, "qt_plugin_query_metadata")
#endif
;
} else
#endif
{
getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata");
}
if (getMetaData) {
ret = qt_get_metadata(getMetaData, this, &exceptionThrown);
} else {
// try the old plugin style
QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL;
#ifdef Q_OS_WIN
if (hTempModule) {
qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction)
#ifdef Q_OS_WINCE
::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data")
#else
::GetProcAddress(hTempModule, "qt_plugin_query_verification_data")
#endif
;
} else
#endif
{
qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
}
ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction, this, &exceptionThrown);
}
if (!exceptionThrown) { if (!exceptionThrown) {
if (!ret) { if (!ret) {
qt_version = 0;
if (temporary_load) if (temporary_load)
unload_sys(); unload_sys();
} else { } else {
@ -772,6 +867,8 @@ bool QLibraryPrivate::isPlugin()
pluginState = IsNotAPlugin; // be pessimistic pluginState = IsNotAPlugin; // be pessimistic
uint qt_version = (uint)metaData.value(QLatin1String("version")).toDouble();
bool debug = metaData.value(QLatin1String("debug")).toBool();
if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) { if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
if (qt_debug_component()) { if (qt_debug_component()) {
qWarning("In %s:\n" qWarning("In %s:\n"

View File

@ -58,6 +58,9 @@
#include "QtCore/qstringlist.h" #include "QtCore/qstringlist.h"
#include "QtCore/qplugin.h" #include "QtCore/qplugin.h"
#include "QtCore/qsharedpointer.h" #include "QtCore/qsharedpointer.h"
#include "QtCore/qjsonobject.h"
#include "QtCore/qjsondocument.h"
#include "QtCore/qendian.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
# include "QtCore/qt_windows.h" # include "QtCore/qt_windows.h"
#endif #endif
@ -90,16 +93,26 @@ public:
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString()); static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
static QVector<QStaticPlugin> staticPlugins();
QWeakPointer<QObject> inst; QWeakPointer<QObject> inst;
QtPluginInstanceFunction instance; QtPluginInstanceFunction instance;
uint qt_version; QJsonObject metaData;
QString lastModified; bool compatPlugin;
QString errorString; QString errorString;
QLibrary::LoadHints loadHints; QLibrary::LoadHints loadHints;
bool isPlugin(); bool isPlugin();
static inline QJsonDocument fromRawMetaData(const char *raw) {
raw += strlen("QTMETADATA ");
// the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h),
// but doesn't include the size of the header (8 bytes)
QByteArray json(raw, qFromLittleEndian<uint>(*(uint *)(raw + 8)) + 8);
return QJsonDocument::fromBinaryData(json);
}
private: private:
explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version); explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version);
@ -112,7 +125,7 @@ private:
QAtomicInt libraryRefCount; QAtomicInt libraryRefCount;
QAtomicInt libraryUnloadCount; QAtomicInt libraryUnloadCount;
enum {IsAPlugin, IsNotAPlugin, MightBeAPlugin } pluginState; enum { IsAPlugin, IsNotAPlugin, MightBeAPlugin } pluginState;
friend class QLibraryPrivateHasFriends; friend class QLibraryPrivateHasFriends;
}; };

View File

@ -59,15 +59,33 @@ QT_BEGIN_NAMESPACE
#endif #endif
typedef QObject *(*QtPluginInstanceFunction)(); typedef QObject *(*QtPluginInstanceFunction)();
typedef const char *(*QtPluginMetaDataFunction)();
struct QStaticPlugin
{
QtPluginInstanceFunction instance;
QtPluginMetaDataFunction metaData;
};
void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
#if defined (Q_OF_ELF) && defined (Q_CC_GNU)
# define QT_PLUGIN_VERIFICATION_SECTION \
__attribute__ ((section (".qtplugin"))) __attribute__((used))
# define QT_PLUGIN_METADATA_SECTION \
__attribute__ ((section (".qtmetadata"))) __attribute__((used))
#else
# define QT_PLUGIN_VERIFICATION_SECTION
# define QT_PLUGIN_METADATA_SECTION
#endif
void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function);
#define Q_IMPORT_PLUGIN(PLUGIN) \ #define Q_IMPORT_PLUGIN(PLUGIN) \
extern QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGIN(); \ extern const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGIN(); \
class Static##PLUGIN##PluginInstance{ \ class Static##PLUGIN##PluginInstance{ \
public: \ public: \
Static##PLUGIN##PluginInstance() { \ Static##PLUGIN##PluginInstance() { \
qRegisterStaticPluginInstanceFunction(qt_plugin_instance_##PLUGIN); \ qRegisterStaticPluginFunction(qt_static_plugin_##PLUGIN()); \
} \ } \
}; \ }; \
static Static##PLUGIN##PluginInstance static##PLUGIN##Instance; static Static##PLUGIN##PluginInstance static##PLUGIN##Instance;
@ -80,21 +98,43 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio
return _instance; \ return _instance; \
} }
# define Q_EXPORT_PLUGIN(PLUGIN) \ #if defined(QT_STATICPLUGIN)
Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN)
# define Q_EXPORT_STATIC_PLUGIN(PLUGIN) \ # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS) \
Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGIN) static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \
Q_PLUGIN_INSTANCE(PLUGINCLASS) \
static const char *qt_plugin_query_metadata() { return (const char *)qt_pluginMetaData; } \
const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASS() { \
QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance, qt_plugin_query_metadata }; \
return plugin; \
}
#else
# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS) \
Q_EXTERN_C Q_DECL_EXPORT \
const char *qt_plugin_query_metadata() \
{ return (const char *)qt_pluginMetaData; } \
Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \
Q_PLUGIN_INSTANCE(PLUGINCLASS)
#endif
#define Q_EXPORT_PLUGIN(PLUGIN) \
Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN)
#define Q_EXPORT_STATIC_PLUGIN(PLUGIN)
#define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS)
#if defined(QT_STATICPLUGIN) #if defined(QT_STATICPLUGIN)
# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \ # define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
QT_PREPEND_NAMESPACE(QObject) \ static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \
*qt_plugin_instance_##PLUGIN() \ Q_PLUGIN_INSTANCE(PLUGINCLASS) \
Q_PLUGIN_INSTANCE(PLUGINCLASS) const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGIN() { \
QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance, 0 }; \
# define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS) \ return plugin; \
Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) }
#else #else
// NOTE: if you change pattern, you MUST change the pattern in // NOTE: if you change pattern, you MUST change the pattern in
@ -118,25 +158,13 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio
"version="QT_VERSION_STR"\n" \ "version="QT_VERSION_STR"\n" \
"debug="QPLUGIN_DEBUG_STR; "debug="QPLUGIN_DEBUG_STR;
# if defined (Q_OF_ELF) && defined (Q_CC_GNU)
# define Q_PLUGIN_VERIFICATION_SECTION \
__attribute__ ((section (".qtplugin"))) __attribute__((used))
# else
# define Q_PLUGIN_VERIFICATION_SECTION
# endif
# if defined (Q_OS_WIN32) && defined(Q_CC_BOR)
# define Q_STANDARD_CALL __stdcall
# else
# define Q_STANDARD_CALL
# endif
# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \ # define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
Q_PLUGIN_VERIFICATION_SECTION Q_PLUGIN_VERIFICATION_DATA \ QT_PLUGIN_VERIFICATION_SECTION Q_PLUGIN_VERIFICATION_DATA \
Q_EXTERN_C Q_DECL_EXPORT \ Q_EXTERN_C Q_DECL_EXPORT \
const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \ const char * qt_plugin_query_verification_data() \
{ return qt_plugin_verification_data; } \ { return qt_plugin_verification_data; } \
Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) * Q_STANDARD_CALL qt_plugin_instance() \ Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) * qt_plugin_instance() \
Q_PLUGIN_INSTANCE(PLUGINCLASS) Q_PLUGIN_INSTANCE(PLUGINCLASS)
# define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS) # define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS)

View File

@ -291,8 +291,8 @@ QString QPluginLoader::errorString() const
return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString; return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
} }
typedef QList<QtPluginInstanceFunction> StaticInstanceFunctionList; typedef QVector<QStaticPlugin> StaticPluginList;
Q_GLOBAL_STATIC(StaticInstanceFunctionList, staticInstanceFunctionList) Q_GLOBAL_STATIC(StaticPluginList, staticPluginList)
/*! \since 4.4 /*! \since 4.4
@ -329,13 +329,13 @@ QLibrary::LoadHints QPluginLoader::loadHints() const
/*! /*!
\relates QPluginLoader \relates QPluginLoader
\since 4.4 \since 5.0
Registers the given \a function with the plugin loader. Registers the given \a plugin with the plugin loader.
*/ */
void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function) void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin plugin)
{ {
staticInstanceFunctionList()->append(function); staticPluginList()->append(plugin);
} }
/*! /*!
@ -345,14 +345,23 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio
QObjectList QPluginLoader::staticInstances() QObjectList QPluginLoader::staticInstances()
{ {
QObjectList instances; QObjectList instances;
StaticInstanceFunctionList *functions = staticInstanceFunctionList(); const StaticPluginList *plugins = staticPluginList();
if (functions) { if (plugins) {
for (int i = 0; i < functions->count(); ++i) for (int i = 0; i < plugins->size(); ++i)
instances.append((*functions)[i]()); instances += plugins->at(i).instance();
} }
return instances; return instances;
} }
QVector<QStaticPlugin> QLibraryPrivate::staticPlugins()
{
StaticPluginList *plugins = staticPluginList();
if (plugins)
return *plugins;
return QVector<QStaticPlugin>();
}
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QT_NO_LIBRARY #endif // QT_NO_LIBRARY

View File

@ -55,7 +55,6 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QLibraryPrivate; class QLibraryPrivate;
class Q_CORE_EXPORT QPluginLoader : public QObject class Q_CORE_EXPORT QPluginLoader : public QObject
@ -70,7 +69,7 @@ public:
QObject *instance(); QObject *instance();
static QObjectList staticInstances(); QT_DEPRECATED static QObjectList staticInstances();
bool load(); bool load();
bool unload(); bool unload();

View File

@ -43,6 +43,11 @@
#include "outputrevision.h" #include "outputrevision.h"
#include "utils.h" #include "utils.h"
#include <QtCore/qmetatype.h> #include <QtCore/qmetatype.h>
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qplugin.h>
#include <stdio.h> #include <stdio.h>
#include <private/qmetaobject_p.h> //for the flags. #include <private/qmetaobject_p.h> //for the flags.
@ -421,6 +426,11 @@ void Generator::generateCode()
// //
for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex) for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
generateSignal(&cdef->signalList[signalindex], signalindex); generateSignal(&cdef->signalList[signalindex], signalindex);
//
// Generate plugin meta data
//
generatePluginMetaData();
} }
@ -1051,4 +1061,42 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, "}\n"); fprintf(out, "}\n");
} }
void Generator::generatePluginMetaData()
{
if (cdef->pluginData.iid.isEmpty())
return;
QJsonObject data;
data.insert(QLatin1String("IID"), QLatin1String(cdef->pluginData.iid.constData()));
data.insert(QLatin1String("className"), QLatin1String(cdef->classname.constData()));
data.insert(QLatin1String("version"), (int)QT_VERSION);
data.insert(QLatin1String("debug"),
#ifdef QT_NO_DEBUG
false
#else
true
#endif
);
data.insert(QLatin1String("MetaData"), cdef->pluginData.metaData.object());
QJsonDocument doc(data);
fprintf(out, "\nQT_PLUGIN_METADATA_SECTION const uint qt_section_alignment_dummy = 42;\n");
fprintf(out,
"\nQT_PLUGIN_METADATA_SECTION\n"
"static const unsigned char qt_pluginMetaData[] = {\n"
" 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', ' ',\n ");
#if 0
fprintf(out, "\"%s\";\n", doc.toJson().constData());
#else
QByteArray binary = doc.toBinaryData();
for (int i = 0; i < binary.size() - 1; ++i) {
fprintf(out, " 0x%02x,", (uchar)binary.at(i));
if (!((i + 1) % 8))
fprintf(out, "\n ");
}
fprintf(out, " 0x%02x\n};\n", (uchar)binary.at(binary.size() - 1));
#endif
fprintf(out, "QT_MOC_EXPORT_PLUGIN(%s)\n\n", cdef->classname.constData());
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -63,6 +63,7 @@ private:
void generateMetacall(); void generateMetacall();
void generateStaticMetacall(); void generateStaticMetacall();
void generateSignal(FunctionDef *def, int index); void generateSignal(FunctionDef *def, int index);
void generatePluginMetaData();
int strreg(const char *); // registers a string and returns its id int strreg(const char *); // registers a string and returns its id
QList<QByteArray> strings; QList<QByteArray> strings;

View File

@ -43,12 +43,12 @@
// DO NOT EDIT. // DO NOT EDIT.
static const short keyword_trans[][128] = { static const short keyword_trans[][128] = {
{0,0,0,0,0,0,0,0,0,532,529,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,546,543,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
532,252,530,533,0,38,239,531,25,26,236,234,30,235,27,237, 546,252,544,547,0,38,239,545,25,26,236,234,30,235,27,237,
22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43, 22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,21,8,8,8,8,8,8,8,8,8,31,534,32,238,8, 8,21,8,8,8,8,8,8,8,8,8,31,548,32,238,8,
0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13, 0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13,
14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0}, 14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -129,7 +129,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,290,222,0,0,461,0,0,0, 0,0,0,0,0,0,0,0,290,222,0,0,475,0,0,0,
0,0,0,0,55,0,0,330,0,0,0,0,0,0,0,0}, 0,0,0,0,55,0,0,330,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -168,7 +168,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,485,0,0,0,0,0,0,0,0,0,0,357, 0,0,0,0,499,0,0,0,0,0,0,0,0,0,0,357,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -190,7 +190,7 @@ static const short keyword_trans[][128] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0, 0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0,
537,537,537,537,537,537,537,537,537,537,0,0,0,0,0,0, 551,551,551,551,551,551,551,551,551,551,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -349,7 +349,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,536,0,0,0,0,535, 0,0,0,0,0,0,0,0,0,0,550,0,0,0,0,549,
0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -385,21 +385,29 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,458,0,0,0,300,0,0,0,0,0,0,0,0,0,0, 0,472,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,439,388,378,383,364,0,448,0,0,0,0,0,358, 0,0,0,453,402,392,397,364,0,462,0,0,0,0,0,358,
370,0,521,436,0,0,0,0,0,0,0,0,0,0,0,0, 370,0,535,450,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,475,0,0,0,0,0,372, 0,0,0,0,0,0,0,0,0,0,0,0,378,0,0,0,
0,0,371,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,489,0,0,0,0,0,372,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@ -407,7 +415,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,418,396,0,0,401,0,0,0,410,0,0, 0,0,0,0,0,432,410,0,0,415,0,0,0,424,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@ -415,7 +423,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,504,0,437,0,0,0,465,0,0,471,0,0,0, 0,0,0,518,0,451,0,0,0,479,0,0,485,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@ -424,7 +432,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,450,0,497,0,0,0,0,0,0,0,0,0, 0,0,0,0,464,0,511,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -432,7 +440,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
513,0,0,481,0,0,0,0,0,0,0,0,0,0,0,0, 527,0,0,495,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
}; };
@ -815,164 +823,178 @@ static const struct
{CHARACTER, 0, 69, 368, CHARACTER}, {CHARACTER, 0, 69, 368, CHARACTER},
{CHARACTER, 0, 84, 369, CHARACTER}, {CHARACTER, 0, 84, 369, CHARACTER},
{Q_GADGET_TOKEN, 0, 0, 0, CHARACTER}, {Q_GADGET_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 82, 371, CHARACTER},
{CHARACTER, 44, 0, 0, CHARACTER}, {CHARACTER, 44, 0, 0, CHARACTER},
{CHARACTER, 45, 0, 0, CHARACTER},
{CHARACTER, 0, 80, 373, CHARACTER}, {CHARACTER, 0, 80, 373, CHARACTER},
{CHARACTER, 0, 69, 374, CHARACTER}, {CHARACTER, 0, 69, 374, CHARACTER},
{CHARACTER, 0, 82, 375, CHARACTER}, {CHARACTER, 0, 82, 375, CHARACTER},
{CHARACTER, 0, 84, 376, CHARACTER}, {CHARACTER, 0, 84, 376, CHARACTER},
{CHARACTER, 0, 89, 377, CHARACTER}, {CHARACTER, 0, 89, 377, CHARACTER},
{Q_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, {Q_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 78, 379, CHARACTER}, {CHARACTER, 0, 85, 379, CHARACTER},
{CHARACTER, 0, 85, 380, CHARACTER}, {CHARACTER, 0, 71, 380, CHARACTER},
{CHARACTER, 0, 77, 381, CHARACTER}, {CHARACTER, 0, 73, 381, CHARACTER},
{CHARACTER, 0, 83, 382, CHARACTER}, {CHARACTER, 0, 78, 382, CHARACTER},
{CHARACTER, 0, 95, 383, CHARACTER},
{CHARACTER, 0, 77, 384, CHARACTER},
{CHARACTER, 0, 69, 385, CHARACTER},
{CHARACTER, 0, 84, 386, CHARACTER},
{CHARACTER, 0, 65, 387, CHARACTER},
{CHARACTER, 0, 68, 388, CHARACTER},
{CHARACTER, 0, 65, 389, CHARACTER},
{CHARACTER, 0, 84, 390, CHARACTER},
{CHARACTER, 0, 65, 391, CHARACTER},
{Q_PLUGIN_METADATA_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 78, 393, CHARACTER},
{CHARACTER, 0, 85, 394, CHARACTER},
{CHARACTER, 0, 77, 395, CHARACTER},
{CHARACTER, 0, 83, 396, CHARACTER},
{Q_ENUMS_TOKEN, 0, 0, 0, CHARACTER}, {Q_ENUMS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 76, 384, CHARACTER}, {CHARACTER, 0, 76, 398, CHARACTER},
{CHARACTER, 0, 65, 385, CHARACTER}, {CHARACTER, 0, 65, 399, CHARACTER},
{CHARACTER, 0, 71, 386, CHARACTER}, {CHARACTER, 0, 71, 400, CHARACTER},
{CHARACTER, 0, 83, 387, CHARACTER}, {CHARACTER, 0, 83, 401, CHARACTER},
{Q_FLAGS_TOKEN, 0, 0, 0, CHARACTER}, {Q_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 389, CHARACTER}, {CHARACTER, 0, 69, 403, CHARACTER},
{CHARACTER, 0, 67, 390, CHARACTER}, {CHARACTER, 0, 67, 404, CHARACTER},
{CHARACTER, 0, 76, 391, CHARACTER}, {CHARACTER, 0, 76, 405, CHARACTER},
{CHARACTER, 0, 65, 392, CHARACTER}, {CHARACTER, 0, 65, 406, CHARACTER},
{CHARACTER, 0, 82, 393, CHARACTER}, {CHARACTER, 0, 82, 407, CHARACTER},
{CHARACTER, 0, 69, 394, CHARACTER}, {CHARACTER, 0, 69, 408, CHARACTER},
{CHARACTER, 0, 95, 395, CHARACTER}, {CHARACTER, 0, 95, 409, CHARACTER},
{CHARACTER, 45, 0, 0, CHARACTER},
{CHARACTER, 0, 76, 397, CHARACTER},
{CHARACTER, 0, 65, 398, CHARACTER},
{CHARACTER, 0, 71, 399, CHARACTER},
{CHARACTER, 0, 83, 400, CHARACTER},
{Q_DECLARE_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 78, 402, CHARACTER},
{CHARACTER, 0, 84, 403, CHARACTER},
{CHARACTER, 0, 69, 404, CHARACTER},
{CHARACTER, 0, 82, 405, CHARACTER},
{CHARACTER, 0, 70, 406, CHARACTER},
{CHARACTER, 0, 65, 407, CHARACTER},
{CHARACTER, 0, 67, 408, CHARACTER},
{CHARACTER, 0, 69, 409, CHARACTER},
{Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 411, CHARACTER},
{CHARACTER, 0, 84, 412, CHARACTER},
{CHARACTER, 0, 65, 413, CHARACTER},
{CHARACTER, 0, 84, 414, CHARACTER},
{CHARACTER, 0, 89, 415, CHARACTER},
{CHARACTER, 0, 80, 416, CHARACTER},
{CHARACTER, 0, 69, 417, CHARACTER},
{Q_DECLARE_METATYPE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 88, 419, CHARACTER},
{CHARACTER, 0, 84, 420, CHARACTER},
{CHARACTER, 0, 69, 421, CHARACTER},
{CHARACTER, 0, 78, 422, CHARACTER},
{CHARACTER, 0, 83, 423, CHARACTER},
{CHARACTER, 0, 73, 424, CHARACTER},
{CHARACTER, 0, 79, 425, CHARACTER},
{CHARACTER, 0, 78, 426, CHARACTER},
{CHARACTER, 0, 95, 427, CHARACTER},
{CHARACTER, 0, 73, 428, CHARACTER},
{CHARACTER, 0, 78, 429, CHARACTER},
{CHARACTER, 0, 84, 430, CHARACTER},
{CHARACTER, 0, 69, 431, CHARACTER},
{CHARACTER, 0, 82, 432, CHARACTER},
{CHARACTER, 0, 70, 433, CHARACTER},
{CHARACTER, 0, 65, 434, CHARACTER},
{CHARACTER, 0, 67, 435, CHARACTER},
{CHARACTER, 0, 69, 409, CHARACTER},
{CHARACTER, 46, 0, 0, CHARACTER}, {CHARACTER, 46, 0, 0, CHARACTER},
{CHARACTER, 0, 84, 438, CHARACTER}, {CHARACTER, 0, 76, 411, CHARACTER},
{CHARACTER, 0, 83, 387, CHARACTER}, {CHARACTER, 0, 65, 412, CHARACTER},
{CHARACTER, 0, 76, 440, CHARACTER}, {CHARACTER, 0, 71, 413, CHARACTER},
{CHARACTER, 0, 65, 441, CHARACTER}, {CHARACTER, 0, 83, 414, CHARACTER},
{CHARACTER, 0, 83, 442, CHARACTER}, {Q_DECLARE_FLAGS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 83, 443, CHARACTER}, {CHARACTER, 0, 78, 416, CHARACTER},
{CHARACTER, 0, 73, 444, CHARACTER}, {CHARACTER, 0, 84, 417, CHARACTER},
{CHARACTER, 0, 78, 445, CHARACTER}, {CHARACTER, 0, 69, 418, CHARACTER},
{CHARACTER, 0, 70, 446, CHARACTER}, {CHARACTER, 0, 82, 419, CHARACTER},
{CHARACTER, 0, 79, 447, CHARACTER}, {CHARACTER, 0, 70, 420, CHARACTER},
{Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER}, {CHARACTER, 0, 65, 421, CHARACTER},
{CHARACTER, 0, 78, 449, CHARACTER}, {CHARACTER, 0, 67, 422, CHARACTER},
{CHARACTER, 0, 69, 423, CHARACTER},
{Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 425, CHARACTER},
{CHARACTER, 0, 84, 426, CHARACTER},
{CHARACTER, 0, 65, 427, CHARACTER},
{CHARACTER, 0, 84, 428, CHARACTER},
{CHARACTER, 0, 89, 429, CHARACTER},
{CHARACTER, 0, 80, 430, CHARACTER},
{CHARACTER, 0, 69, 431, CHARACTER},
{Q_DECLARE_METATYPE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 88, 433, CHARACTER},
{CHARACTER, 0, 84, 434, CHARACTER},
{CHARACTER, 0, 69, 435, CHARACTER},
{CHARACTER, 0, 78, 436, CHARACTER},
{CHARACTER, 0, 83, 437, CHARACTER},
{CHARACTER, 0, 73, 438, CHARACTER},
{CHARACTER, 0, 79, 439, CHARACTER},
{CHARACTER, 0, 78, 440, CHARACTER},
{CHARACTER, 0, 95, 441, CHARACTER},
{CHARACTER, 0, 73, 442, CHARACTER},
{CHARACTER, 0, 78, 443, CHARACTER},
{CHARACTER, 0, 84, 444, CHARACTER},
{CHARACTER, 0, 69, 445, CHARACTER},
{CHARACTER, 0, 82, 446, CHARACTER},
{CHARACTER, 0, 70, 447, CHARACTER},
{CHARACTER, 0, 65, 448, CHARACTER},
{CHARACTER, 0, 67, 449, CHARACTER},
{CHARACTER, 0, 69, 423, CHARACTER},
{CHARACTER, 47, 0, 0, CHARACTER}, {CHARACTER, 47, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 451, CHARACTER}, {CHARACTER, 0, 84, 452, CHARACTER},
{CHARACTER, 0, 82, 452, CHARACTER}, {CHARACTER, 0, 83, 401, CHARACTER},
{CHARACTER, 0, 70, 453, CHARACTER}, {CHARACTER, 0, 76, 454, CHARACTER},
{CHARACTER, 0, 65, 454, CHARACTER}, {CHARACTER, 0, 65, 455, CHARACTER},
{CHARACTER, 0, 67, 455, CHARACTER}, {CHARACTER, 0, 83, 456, CHARACTER},
{CHARACTER, 0, 69, 456, CHARACTER},
{CHARACTER, 0, 83, 457, CHARACTER}, {CHARACTER, 0, 83, 457, CHARACTER},
{Q_INTERFACES_TOKEN, 0, 0, 0, CHARACTER}, {CHARACTER, 0, 73, 458, CHARACTER},
{CHARACTER, 0, 108, 459, CHARACTER}, {CHARACTER, 0, 78, 459, CHARACTER},
{CHARACTER, 0, 115, 460, CHARACTER}, {CHARACTER, 0, 70, 460, CHARACTER},
{SIGNALS, 0, 0, 0, CHARACTER}, {CHARACTER, 0, 79, 461, CHARACTER},
{CHARACTER, 0, 111, 462, CHARACTER}, {Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 116, 463, CHARACTER}, {CHARACTER, 0, 78, 463, CHARACTER},
{CHARACTER, 0, 115, 464, CHARACTER},
{SLOTS, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 71, 466, CHARACTER},
{CHARACTER, 0, 78, 467, CHARACTER},
{CHARACTER, 0, 65, 468, CHARACTER},
{CHARACTER, 0, 76, 469, CHARACTER},
{Q_SIGNAL_TOKEN, 0, 83, 470, CHARACTER},
{Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 79, 472, CHARACTER},
{CHARACTER, 0, 84, 473, CHARACTER},
{Q_SLOT_TOKEN, 0, 83, 474, CHARACTER},
{Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 86, 476, CHARACTER},
{CHARACTER, 0, 65, 477, CHARACTER},
{CHARACTER, 0, 84, 478, CHARACTER},
{CHARACTER, 0, 69, 479, CHARACTER},
{CHARACTER, 0, 95, 480, CHARACTER},
{CHARACTER, 48, 0, 0, CHARACTER}, {CHARACTER, 48, 0, 0, CHARACTER},
{CHARACTER, 0, 76, 482, CHARACTER}, {CHARACTER, 0, 69, 465, CHARACTER},
{CHARACTER, 0, 79, 483, CHARACTER}, {CHARACTER, 0, 82, 466, CHARACTER},
{CHARACTER, 0, 84, 484, CHARACTER}, {CHARACTER, 0, 70, 467, CHARACTER},
{CHARACTER, 0, 65, 468, CHARACTER},
{CHARACTER, 0, 67, 469, CHARACTER},
{CHARACTER, 0, 69, 470, CHARACTER},
{CHARACTER, 0, 83, 471, CHARACTER},
{Q_INTERFACES_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 108, 473, CHARACTER},
{CHARACTER, 0, 115, 474, CHARACTER},
{SIGNALS, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 111, 476, CHARACTER},
{CHARACTER, 0, 116, 477, CHARACTER},
{CHARACTER, 0, 115, 478, CHARACTER},
{SLOTS, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 71, 480, CHARACTER},
{CHARACTER, 0, 78, 481, CHARACTER},
{CHARACTER, 0, 65, 482, CHARACTER},
{CHARACTER, 0, 76, 483, CHARACTER},
{Q_SIGNAL_TOKEN, 0, 83, 484, CHARACTER},
{Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 79, 486, CHARACTER},
{CHARACTER, 0, 84, 487, CHARACTER},
{Q_SLOT_TOKEN, 0, 83, 488, CHARACTER},
{Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 86, 490, CHARACTER},
{CHARACTER, 0, 65, 491, CHARACTER},
{CHARACTER, 0, 84, 492, CHARACTER},
{CHARACTER, 0, 69, 493, CHARACTER},
{CHARACTER, 0, 95, 494, CHARACTER},
{CHARACTER, 49, 0, 0, CHARACTER},
{CHARACTER, 0, 76, 496, CHARACTER},
{CHARACTER, 0, 79, 497, CHARACTER},
{CHARACTER, 0, 84, 498, CHARACTER},
{Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER}, {Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 95, 486, CHARACTER}, {CHARACTER, 0, 95, 500, CHARACTER},
{CHARACTER, 0, 77, 487, CHARACTER}, {CHARACTER, 0, 77, 501, CHARACTER},
{CHARACTER, 0, 79, 488, CHARACTER}, {CHARACTER, 0, 79, 502, CHARACTER},
{CHARACTER, 0, 67, 489, CHARACTER}, {CHARACTER, 0, 67, 503, CHARACTER},
{CHARACTER, 0, 95, 490, CHARACTER}, {CHARACTER, 0, 95, 504, CHARACTER},
{CHARACTER, 0, 67, 491, CHARACTER}, {CHARACTER, 0, 67, 505, CHARACTER},
{CHARACTER, 0, 79, 492, CHARACTER}, {CHARACTER, 0, 79, 506, CHARACTER},
{CHARACTER, 0, 77, 493, CHARACTER}, {CHARACTER, 0, 77, 507, CHARACTER},
{CHARACTER, 0, 80, 494, CHARACTER}, {CHARACTER, 0, 80, 508, CHARACTER},
{CHARACTER, 0, 65, 495, CHARACTER},
{CHARACTER, 0, 84, 496, CHARACTER},
{Q_MOC_COMPAT_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 79, 498, CHARACTER},
{CHARACTER, 0, 75, 499, CHARACTER},
{CHARACTER, 0, 65, 500, CHARACTER},
{CHARACTER, 0, 66, 501, CHARACTER},
{CHARACTER, 0, 76, 502, CHARACTER},
{CHARACTER, 0, 69, 503, CHARACTER},
{Q_INVOKABLE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 82, 505, CHARACTER},
{CHARACTER, 0, 73, 506, CHARACTER},
{CHARACTER, 0, 80, 507, CHARACTER},
{CHARACTER, 0, 84, 508, CHARACTER},
{CHARACTER, 0, 65, 509, CHARACTER}, {CHARACTER, 0, 65, 509, CHARACTER},
{CHARACTER, 0, 66, 510, CHARACTER}, {CHARACTER, 0, 84, 510, CHARACTER},
{CHARACTER, 0, 76, 511, CHARACTER}, {Q_MOC_COMPAT_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 512, CHARACTER}, {CHARACTER, 0, 79, 512, CHARACTER},
{Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER}, {CHARACTER, 0, 75, 513, CHARACTER},
{CHARACTER, 0, 82, 514, CHARACTER}, {CHARACTER, 0, 65, 514, CHARACTER},
{CHARACTER, 0, 79, 515, CHARACTER}, {CHARACTER, 0, 66, 515, CHARACTER},
{CHARACTER, 0, 80, 516, CHARACTER}, {CHARACTER, 0, 76, 516, CHARACTER},
{CHARACTER, 0, 69, 517, CHARACTER}, {CHARACTER, 0, 69, 517, CHARACTER},
{CHARACTER, 0, 82, 518, CHARACTER}, {Q_INVOKABLE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 84, 519, CHARACTER}, {CHARACTER, 0, 82, 519, CHARACTER},
{CHARACTER, 0, 89, 520, CHARACTER}, {CHARACTER, 0, 73, 520, CHARACTER},
{CHARACTER, 0, 80, 521, CHARACTER},
{CHARACTER, 0, 84, 522, CHARACTER},
{CHARACTER, 0, 65, 523, CHARACTER},
{CHARACTER, 0, 66, 524, CHARACTER},
{CHARACTER, 0, 76, 525, CHARACTER},
{CHARACTER, 0, 69, 526, CHARACTER},
{Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 82, 528, CHARACTER},
{CHARACTER, 0, 79, 529, CHARACTER},
{CHARACTER, 0, 80, 530, CHARACTER},
{CHARACTER, 0, 69, 531, CHARACTER},
{CHARACTER, 0, 82, 532, CHARACTER},
{CHARACTER, 0, 84, 533, CHARACTER},
{CHARACTER, 0, 89, 534, CHARACTER},
{Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, {Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 522, CHARACTER}, {CHARACTER, 0, 69, 536, CHARACTER},
{CHARACTER, 0, 86, 523, CHARACTER}, {CHARACTER, 0, 86, 537, CHARACTER},
{CHARACTER, 0, 73, 524, CHARACTER}, {CHARACTER, 0, 73, 538, CHARACTER},
{CHARACTER, 0, 83, 525, CHARACTER}, {CHARACTER, 0, 83, 539, CHARACTER},
{CHARACTER, 0, 73, 526, CHARACTER}, {CHARACTER, 0, 73, 540, CHARACTER},
{CHARACTER, 0, 79, 527, CHARACTER}, {CHARACTER, 0, 79, 541, CHARACTER},
{CHARACTER, 0, 78, 528, CHARACTER}, {CHARACTER, 0, 78, 542, CHARACTER},
{Q_REVISION_TOKEN, 0, 0, 0, CHARACTER}, {Q_REVISION_TOKEN, 0, 0, 0, CHARACTER},
{NEWLINE, 0, 0, 0, NOTOKEN}, {NEWLINE, 0, 0, 0, NOTOKEN},
{QUOTE, 0, 0, 0, NOTOKEN}, {QUOTE, 0, 0, 0, NOTOKEN},

View File

@ -44,6 +44,9 @@
#include "qdatetime.h" #include "qdatetime.h"
#include "utils.h" #include "utils.h"
#include "outputrevision.h" #include "outputrevision.h"
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
// for normalizeTypeInternal // for normalizeTypeInternal
#include <private/qmetaobject_moc_p.h> #include <private/qmetaobject_moc_p.h>
@ -673,6 +676,9 @@ void Moc::parse()
case Q_PROPERTY_TOKEN: case Q_PROPERTY_TOKEN:
parseProperty(&def); parseProperty(&def);
break; break;
case Q_PLUGIN_METADATA_TOKEN:
parsePluginData(&def);
break;
case Q_ENUMS_TOKEN: case Q_ENUMS_TOKEN:
parseEnumOrFlag(&def, false); parseEnumOrFlag(&def, false);
break; break;
@ -813,6 +819,8 @@ void Moc::generate(FILE *out)
if (mustIncludeQMetaTypeH) if (mustIncludeQMetaTypeH)
fprintf(out, "#include <QtCore/qmetatype.h>\n"); fprintf(out, "#include <QtCore/qmetatype.h>\n");
if (mustIncludeQPluginH)
fprintf(out, "#include <QtCore/qplugin.h>\n");
fprintf(out, "#if !defined(Q_MOC_OUTPUT_REVISION)\n" fprintf(out, "#if !defined(Q_MOC_OUTPUT_REVISION)\n"
"#error \"The header file '%s' doesn't include <QObject>.\"\n", (const char *)fn); "#error \"The header file '%s' doesn't include <QObject>.\"\n", (const char *)fn);
@ -1080,6 +1088,50 @@ void Moc::parseProperty(ClassDef *def)
def->propertyList += propDef; def->propertyList += propDef;
} }
void Moc::parsePluginData(ClassDef *def)
{
next(LPAREN);
QByteArray metaData;
while (test(IDENTIFIER)) {
QByteArray l = lexem();
if (l == "IID") {
next(STRING_LITERAL);
def->pluginData.iid = unquotedLexem();
} else if (l == "FILE") {
next(STRING_LITERAL);
QByteArray metaDataFile = unquotedLexem();
QFileInfo fi(QFileInfo(QString::fromLocal8Bit(currentFilenames.top())).dir(), QString::fromLocal8Bit(metaDataFile));
if (!fi.exists()) {
QByteArray msg;
msg += "Plugin Metadata file ";
msg += lexem();
msg += " does not exist. Declaration will be ignored";
warning(msg.constData());
return;
}
QFile file(fi.canonicalFilePath());
file.open(QFile::ReadOnly);
metaData = file.readAll();
}
}
if (!metaData.isEmpty()) {
def->pluginData.metaData = QJsonDocument::fromJson(metaData);
if (!def->pluginData.metaData.isObject()) {
QByteArray msg;
msg += "Plugin Metadata file ";
msg += lexem();
msg += " does not contain a valid JSON object. Declaration will be ignored";
warning(msg.constData());
def->pluginData.iid = QByteArray();
return;
}
}
mustIncludeQPluginH = true;
next(RPAREN);
}
void Moc::parsePrivateProperty(ClassDef *def) void Moc::parsePrivateProperty(ClassDef *def)
{ {
next(LPAREN); next(LPAREN);

View File

@ -46,6 +46,7 @@
#include <QStringList> #include <QStringList>
#include <QMap> #include <QMap>
#include <QPair> #include <QPair>
#include <QJsonDocument>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
@ -167,6 +168,11 @@ struct ClassDef {
bool hasQObject; bool hasQObject;
bool hasQGadget; bool hasQGadget;
struct PluginData {
QByteArray iid;
QJsonDocument metaData;
} pluginData;
QList<FunctionDef> constructorList; QList<FunctionDef> constructorList;
QList<FunctionDef> signalList, slotList, methodList, publicList; QList<FunctionDef> signalList, slotList, methodList, publicList;
int notifyableProperties; int notifyableProperties;
@ -192,7 +198,7 @@ class Moc : public Parser
{ {
public: public:
Moc() Moc()
: noInclude(false), generatedCode(false), mustIncludeQMetaTypeH(false) : noInclude(false), generatedCode(false), mustIncludeQMetaTypeH(false), mustIncludeQPluginH(false)
{} {}
QByteArray filename; QByteArray filename;
@ -200,6 +206,7 @@ public:
bool noInclude; bool noInclude;
bool generatedCode; bool generatedCode;
bool mustIncludeQMetaTypeH; bool mustIncludeQMetaTypeH;
bool mustIncludeQPluginH;
QByteArray includePath; QByteArray includePath;
QList<QByteArray> includeFiles; QList<QByteArray> includeFiles;
QList<ClassDef> classList; QList<ClassDef> classList;
@ -229,6 +236,7 @@ public:
void parseSlots(ClassDef *def, FunctionDef::Access access); void parseSlots(ClassDef *def, FunctionDef::Access access);
void parseSignals(ClassDef *def); void parseSignals(ClassDef *def);
void parseProperty(ClassDef *def); void parseProperty(ClassDef *def);
void parsePluginData(ClassDef *def);
void createPropertyDef(PropertyDef &def); void createPropertyDef(PropertyDef &def);
void parseEnumOrFlag(ClassDef *def, bool isFlag); void parseEnumOrFlag(ClassDef *def, bool isFlag);
void parseFlag(ClassDef *def); void parseFlag(ClassDef *def);

View File

@ -169,6 +169,7 @@ enum Token {
Q_OBJECT_TOKEN = Q_META_TOKEN_BEGIN, Q_OBJECT_TOKEN = Q_META_TOKEN_BEGIN,
Q_GADGET_TOKEN, Q_GADGET_TOKEN,
Q_PROPERTY_TOKEN, Q_PROPERTY_TOKEN,
Q_PLUGIN_METADATA_TOKEN,
Q_ENUMS_TOKEN, Q_ENUMS_TOKEN,
Q_FLAGS_TOKEN, Q_FLAGS_TOKEN,
Q_DECLARE_FLAGS_TOKEN, Q_DECLARE_FLAGS_TOKEN,

View File

@ -228,6 +228,7 @@ static const Keyword keywords[] = {
{ "Q_OBJECT", "Q_OBJECT_TOKEN" }, { "Q_OBJECT", "Q_OBJECT_TOKEN" },
{ "Q_GADGET", "Q_GADGET_TOKEN" }, { "Q_GADGET", "Q_GADGET_TOKEN" },
{ "Q_PROPERTY", "Q_PROPERTY_TOKEN" }, { "Q_PROPERTY", "Q_PROPERTY_TOKEN" },
{ "Q_PLUGIN_METADATA", "Q_PLUGIN_METADATA_TOKEN" },
{ "Q_ENUMS", "Q_ENUMS_TOKEN" }, { "Q_ENUMS", "Q_ENUMS_TOKEN" },
{ "Q_FLAGS", "Q_FLAGS_TOKEN" }, { "Q_FLAGS", "Q_FLAGS_TOKEN" },
{ "Q_DECLARE_FLAGS", "Q_DECLARE_FLAGS_TOKEN" }, { "Q_DECLARE_FLAGS", "Q_DECLARE_FLAGS_TOKEN" },