summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorJuha Vuolle <juha.vuolle@insta.fi>2021-03-18 11:11:05 +0200
committerJuha Vuolle <juha.vuolle@insta.fi>2021-04-13 14:53:54 +0200
commita447ae6d966a6d97548f23f4c3fe8cf6512d3576 (patch)
tree4693f22bd0c3f61efd321bb790c049c4be115661 /tools
parent33c325e573cb29aaa67399be761a3e1847c5cc53 (diff)
Create a patch for synchronizing MOC with qtbase
This commit adds a small script that can be used to both generate patch files and update the moc code from the upstream moc by applying these patches. The main purpose is to ease the synchronization work which has thus far been done manually. Pick-to: 6.1 Task-number: QTBUG-89830 Change-Id: I8c984b3ebcbefae2dfba4b4e887238f36b9c9c07 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'tools')
-rw-r--r--tools/qscxmlc/generator.cpp8
-rw-r--r--tools/qscxmlc/moc.h4
-rw-r--r--tools/qscxmlc/moc_patches/generator.cpp.patch321
-rw-r--r--tools/qscxmlc/moc_patches/generator.h.patch58
-rw-r--r--tools/qscxmlc/moc_patches/moc.h.patch105
-rw-r--r--tools/qscxmlc/moc_patches/outputrevision.h.patch25
-rwxr-xr-xtools/qscxmlc/moc_patches/update_moc.sh120
7 files changed, 637 insertions, 4 deletions
diff --git a/tools/qscxmlc/generator.cpp b/tools/qscxmlc/generator.cpp
index de42fa7..e739403 100644
--- a/tools/qscxmlc/generator.cpp
+++ b/tools/qscxmlc/generator.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com>
** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -105,10 +105,11 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
return nullptr;
}
+// -- QtScxml
Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
const QHash<QByteArray, QByteArray> &knownQObjectClasses,
const QHash<QByteArray, QByteArray> &knownGadgets,
- QIODevice &outfile, // -- QtScxml
+ QIODevice &outfile,
bool requireCompleteTypes)
: out(outfile),
cdef(classDef),
@@ -120,6 +121,7 @@ Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
if (cdef->superclassList.size())
purestSuperClass = cdef->superclassList.constFirst().first;
}
+// -- QtScxml
static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
{
diff --git a/tools/qscxmlc/moc.h b/tools/qscxmlc/moc.h
index 6c1a3a3..9639122 100644
--- a/tools/qscxmlc/moc.h
+++ b/tools/qscxmlc/moc.h
@@ -105,7 +105,9 @@ struct FunctionDef
bool inlineCode = false;
bool wasCloned = false;
- // bool returnTypeIsVolatile = false; -- QtScxml
+#if 0 // -- QtScxml
+ bool returnTypeIsVolatile = false;
+#endif // -- QtScxml
bool isCompat = false;
bool isInvokable = false;
bool isScriptable = false;
diff --git a/tools/qscxmlc/moc_patches/generator.cpp.patch b/tools/qscxmlc/moc_patches/generator.cpp.patch
new file mode 100644
index 0000000..45493ac
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/generator.cpp.patch
@@ -0,0 +1,321 @@
+--- .upstream/generator.cpp 2021-01-20 17:08:05.000000000 +0200
++++ generator.cpp 2021-03-19 15:52:02.000000000 +0200
+@@ -5,7 +5,7 @@
+ ** Copyright (C) 2018 Intel Corporation.
+ ** Contact: https://www.qt.io/licensing/
+ **
+-** This file is part of the tools applications of the Qt Toolkit.
++** This file is part of the QtScxml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+ ** Commercial License Usage
+@@ -29,7 +29,9 @@
+ ****************************************************************************/
+
+ #include "generator.h"
++#if 0 // -- QtScxml
+ #include "cbordevice.h"
++#endif // -- QtScxml
+ #include "outputrevision.h"
+ #include "utils.h"
+ #include <QtCore/qmetatype.h>
+@@ -48,6 +50,29 @@
+
+ QT_BEGIN_NAMESPACE
+
++// -- QtScxml
++void fprintf(QIODevice &out, const char *fmt, ...)
++{
++ va_list argp;
++ va_start(argp, fmt);
++ const int bufSize = 4096;
++ char buf[bufSize];
++ vsnprintf(buf, bufSize, fmt, argp);
++ va_end(argp);
++ out.write(buf);
++}
++
++void fputc(char c, QIODevice &out)
++{
++ out.write(&c, 1);
++}
++
++void fputs(const char *s, QIODevice &out)
++{
++ out.write(s);
++}
++// -- QtScxml
++
+ uint nameToBuiltinType(const QByteArray &name)
+ {
+ if (name.isEmpty())
+@@ -80,20 +105,23 @@
+ return nullptr;
+ }
+
+- Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+- const QHash<QByteArray, QByteArray> &knownQObjectClasses,
+- const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile,
+- bool requireCompleteTypes)
+- : out(outfile),
+- cdef(classDef),
+- metaTypes(metaTypes),
+- knownQObjectClasses(knownQObjectClasses),
+- knownGadgets(knownGadgets),
+- requireCompleteTypes(requireCompleteTypes)
+- {
+- if (cdef->superclassList.size())
+- purestSuperClass = cdef->superclassList.constFirst().first;
++// -- QtScxml
++Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
++ const QHash<QByteArray, QByteArray> &knownQObjectClasses,
++ const QHash<QByteArray, QByteArray> &knownGadgets,
++ QIODevice &outfile,
++ bool requireCompleteTypes)
++ : out(outfile),
++ cdef(classDef),
++ metaTypes(metaTypes),
++ knownQObjectClasses(knownQObjectClasses),
++ knownGadgets(knownGadgets),
++ requireCompleteTypes(requireCompleteTypes)
++{
++ if (cdef->superclassList.size())
++ purestSuperClass = cdef->superclassList.constFirst().first;
+ }
++// -- QtScxml
+
+ static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
+ {
+@@ -254,12 +282,16 @@
+ stringDataLength += thisLength;
+ if (stringDataLength / constCharArraySizeLimit) {
+ // save previous stringdata and start computing the next one.
+- fprintf(out, " char stringdata%d[%d];\n", stringDataCounter++, stringDataLength - thisLength);
++// -- QtScxml
++ fprintf(out, " unsigned char stringdata%d[%d];\n", stringDataCounter++,
++ stringDataLength - thisLength);
++// -- QtScxml
+ stringDataLength = thisLength;
+ }
+ }
+- fprintf(out, " char stringdata%d[%d];\n", stringDataCounter, stringDataLength);
+-
++// -- QtScxml
++ fprintf(out, " unsigned char stringdata%d[%d];\n", stringDataCounter, stringDataLength);
++// -- QtScxml
+ }
+ fprintf(out, "};\n");
+
+@@ -293,56 +325,24 @@
+ }
+ }
+ }
+- fprintf(out, "\n },\n");
++ fprintf(out, " },{\n"); // -- QtScxml
+ }
+
+ //
+ // Build stringdata array
+ //
+- fprintf(out, " \"");
+- int col = 0;
+- int len = 0;
+- int stringDataLength = 0;
++// -- QtScxml
+ for (int i = 0; i < strings.size(); ++i) {
+ QByteArray s = strings.at(i);
+- len = s.length();
+- stringDataLength += len + 1;
+- if (stringDataLength >= constCharArraySizeLimit) {
+- fprintf(out, "\",\n \"");
+- stringDataLength = len + 1;
+- col = 0;
+- } else if (i)
+- fputs("\\0", out); // add \0 at the end of each string
+-
+- if (col && col + len >= 72) {
+- fprintf(out, "\"\n \"");
+- col = 0;
+- } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
+- fprintf(out, "\"\"");
+- len += 2;
+- }
+- int idx = 0;
+- while (idx < s.length()) {
+- if (idx > 0) {
+- col = 0;
+- fprintf(out, "\"\n \"");
+- }
+- int spanLen = qMin(70, s.length() - idx);
+- // don't cut escape sequences at the end of a line
+- int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
+- if (backSlashPos >= idx) {
+- int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
+- spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx);
+- }
+- fprintf(out, "%.*s", spanLen, s.constData() + idx);
+- idx += spanLen;
+- col += spanLen;
+- }
+- col += len + 2;
++ int len = s.length();
++ for (int charPos = 0; charPos < len; ++charPos)
++ fprintf(out, "0x%.2x,", static_cast<quint8>(s.at(charPos)));
++ fprintf(out, "0%s // %d: %s\n", i < strings.size() - 1 ? "," : "", i, s.constData());
+ }
++// -- QtScxml
+
+ // Terminate stringdata struct
+- fprintf(out, "\"\n};\n");
++ fprintf(out, " }};\n"); // -- QtScxml
+ fprintf(out, "#undef QT_MOC_LITERAL\n\n");
+
+ //
+@@ -633,9 +633,12 @@
+ //
+ fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData());
+ fprintf(out, " if (!_clname) return nullptr;\n");
+- fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata0))\n"
+- " return static_cast<void*>(this);\n",
+- qualifiedClassNameIdentifier.constData());
++// -- QtScxml
++ fprintf(out, " if (!strcmp(_clname, reinterpret_cast<const char *>(\n"
++ " qt_meta_stringdata_%s.stringdata0)))\n"
++ " return static_cast<void*>(const_cast< %s*>(this));\n",
++ qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
++// -- QtScxml
+ for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
+ if (cdef->superclassList.at(i).second == FunctionDef::Private)
+ continue;
+@@ -674,7 +677,9 @@
+ //
+ // Generate plugin meta data
+ //
++#if 0 // -- QtScxml
+ generatePluginMetaData();
++#endif // -- QtScxml
+
+ //
+ // Generate function to make sure the non-class signals exist in the parent classes
+@@ -1129,6 +1134,13 @@
+ const FunctionDef &f = methodList.at(methodindex);
+ Q_ASSERT(!f.normalizedType.isEmpty());
+ fprintf(out, " case %d: ", methodindex);
++ // -- QtScxml
++ if (f.implementation) {
++ fprintf(out, f.implementation, "_o", methodindex);
++ fprintf(out, " break;\n");
++ continue;
++ }
++ // -- QtScxml
+ if (f.normalizedType != "void")
+ fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData());
+ fprintf(out, "_t->");
+@@ -1206,6 +1218,10 @@
+ const FunctionDef &f = cdef->signalList.at(methodindex);
+ if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic)
+ continue;
++ // -- QtScxml
++ if (f.mangledName.isEmpty())
++ continue;
++ // -- QtScxml
+ anythingUsed = true;
+ fprintf(out, " {\n");
+ fprintf(out, " using _t = %s (%s::*)(",f.type.rawName.constData() , cdef->classname.constData());
+@@ -1227,7 +1243,8 @@
+ else
+ fprintf(out, ");\n");
+ fprintf(out, " if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&%s::%s)) {\n",
+- cdef->classname.constData(), f.name.constData());
++ cdef->classname.constData(),
++ f.mangledName.constData()); // -- QtScxml
+ fprintf(out, " *result = %d;\n", methodindex);
+ fprintf(out, " return;\n");
+ fprintf(out, " }\n }\n");
+@@ -1322,8 +1339,11 @@
+ fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
+ propindex, prefix.constData(), p.read.constData());
+ else if (!p.read.isEmpty())
+- fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
+- propindex, p.type.constData(), prefix.constData(), p.read.constData());
++ // -- QtScxml
++ fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s%s; break;\n",
++ propindex, p.type.constData(), prefix.constData(), p.read.constData(),
++ p.read.endsWith(')') ? "" : "()");
++ // -- QtScxml
+ else
+ fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n",
+ propindex, p.type.constData(), prefix.constData(), p.member.constData());
+@@ -1443,6 +1463,10 @@
+ {
+ if (def->wasCloned || def->isAbstract)
+ return;
++// -- QtScxml
++ if (def->implementation)
++ return;
++// -- QtScxml
+ fprintf(out, "\n// SIGNAL %d\n%s %s::%s(",
+ index, def->type.name.constData(), cdef->qualified.constData(), def->name.constData());
+
+@@ -1489,10 +1513,8 @@
+ if (def->normalizedType == "void") {
+ fprintf(out, "nullptr");
+ } else {
+- if (def->returnTypeIsVolatile)
+- fprintf(out, "const_cast<void*>(reinterpret_cast<const volatile void*>(std::addressof(_t0)))");
+- else
+- fprintf(out, "const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t0)))");
++ // -- QtScxml removed unused returnTypeIsVolatile
++ fprintf(out, "const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t0)))");
+ }
+ int i;
+ for (i = 1; i < offset; ++i)
+@@ -1507,6 +1529,36 @@
+ fprintf(out, "}\n");
+ }
+
++// -- QtScxml
++void Generator::generateAccessorDefs()
++{
++ for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
++ const PropertyDef &p = cdef->propertyList.at(propindex);
++ if (p.read.isEmpty() || p.mangledName.isEmpty())
++ continue;
++
++ fprintf(out, "bool %s::%s() const\n{\n return %s;\n}\n\n", cdef->classname.constData(),
++ p.mangledName.constData(), p.read.constData());
++ }
++}
++
++void Generator::generateSignalDefs()
++{
++ for (int methodindex = 0; methodindex < cdef->signalList.size(); ++methodindex) {
++ const FunctionDef &f = cdef->signalList.at(methodindex);
++ if (!f.implementation || f.mangledName.isEmpty())
++ continue;
++
++ fprintf(out, "void %s::%s(bool _t1)\n{\n", cdef->classname.constData(),
++ f.mangledName.constData());
++ fprintf(out, " void *_a[] = { nullptr, "
++ "const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };\n ");
++ fprintf(out, f.implementation, "this", methodindex);
++ fprintf(out, "\n}\n\n");
++ }
++}
++
++#if 0
+ static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v);
+ static CborError jsonObjectToCbor(CborEncoder *parent, const QJsonObject &o)
+ {
+@@ -1629,7 +1681,11 @@
+
+ #define CBOR_ENCODER_WRITER_CONTROL 1
+ #define CBOR_ENCODER_WRITE_FUNCTION CborDevice::callback
++#endif
++// -- QtScxml
+
+ QT_END_NAMESPACE
+
++#if 0 // -- QtScxml
+ #include "cborencoder.c"
++#endif // -- QtScxml
diff --git a/tools/qscxmlc/moc_patches/generator.h.patch b/tools/qscxmlc/moc_patches/generator.h.patch
new file mode 100644
index 0000000..8f4b5b4
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/generator.h.patch
@@ -0,0 +1,58 @@
+--- .upstream/generator.h 2021-01-20 17:08:05.000000000 +0200
++++ generator.h 2021-03-19 15:52:02.000000000 +0200
+@@ -3,7 +3,7 @@
+ ** Copyright (C) 2016 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+-** This file is part of the tools applications of the Qt Toolkit.
++** This file is part of the QtScxml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+ ** Commercial License Usage
+@@ -31,20 +31,33 @@
+
+ #include "moc.h"
+
++// -- QtScxml
++#include <QtCore/qhash.h>
++#include <QtCore/qlist.h>
++#include <QtCore/qiodevice.h>
++// -- QtScxml
++
+ QT_BEGIN_NAMESPACE
+
+ class Generator
+ {
+- FILE *out;
++ QIODevice &out; // -- QtScxml
+ ClassDef *cdef;
+ QList<uint> meta_data;
+
+ public:
+ Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes,
+ const QHash<QByteArray, QByteArray> &knownQObjectClasses,
+- const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr,
++ const QHash<QByteArray, QByteArray> &knownGadgets,
++ QIODevice &outfile, // -- QtScxml
+ bool requireCompleteTypes = false);
+ void generateCode();
++
++// -- QtScxml
++ void generateAccessorDefs();
++ void generateSignalDefs();
++// -- QtScxml
++
+ private:
+ bool registerableMetaType(const QByteArray &propertyType);
+ void registerClassInfoStrings();
+@@ -63,7 +76,10 @@
+ void generateMetacall();
+ void generateStaticMetacall();
+ void generateSignal(FunctionDef *def, int index);
++ void generateQPropertyApi();
++#if 0 // -- QtScxml
+ void generatePluginMetaData();
++#endif // -- QtScxml
+ QMultiMap<QByteArray, int> automaticPropertyMetaTypesHelper();
+ QMap<int, QMultiMap<QByteArray, int>>
+ methodsWithAutomaticTypesHelper(const QList<FunctionDef> &methodList);
diff --git a/tools/qscxmlc/moc_patches/moc.h.patch b/tools/qscxmlc/moc_patches/moc.h.patch
new file mode 100644
index 0000000..4eb3191
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/moc.h.patch
@@ -0,0 +1,105 @@
+--- .upstream/moc.h 2021-03-18 12:30:56.000000000 +0200
++++ moc.h 2021-03-19 15:59:05.000000000 +0200
+@@ -3,7 +3,7 @@
+ ** Copyright (C) 2016 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+-** This file is part of the tools applications of the Qt Toolkit.
++** This file is part of the QtScxml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+ ** Commercial License Usage
+@@ -29,15 +29,13 @@
+ #ifndef MOC_H
+ #define MOC_H
+
+-#include "parser.h"
+-#include <qstringlist.h>
+-#include <qmap.h>
+-#include <qpair.h>
+-#include <qjsondocument.h>
+-#include <qjsonarray.h>
+-#include <qjsonobject.h>
+-#include <qversionnumber.h>
+-#include <stdio.h>
++// -- QtScxml
++#include <QtCore/qmap.h>
++#include <QtCore/qpair.h>
++#include <QtCore/qjsondocument.h>
++#include <QtCore/qjsonarray.h>
++// -- QtScxml
++
+ #include <ctype.h>
+
+ QT_BEGIN_NAMESPACE
+@@ -48,16 +46,18 @@
+ {
+ enum ReferenceType { NoReference, Reference, RValueReference, Pointer };
+
+- inline Type() : isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {}
++ inline Type() : isVolatile(false), isScoped(false), /* firstToken(NOTOKEN) -- QtScxml ,*/ referenceType(NoReference) {}
+ inline explicit Type(const QByteArray &_name)
+- : name(_name), rawName(name), isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {}
++ : name(_name), rawName(name), isVolatile(false), isScoped(false), /* firstToken(NOTOKEN) -- QtScxml ,*/ referenceType(NoReference) {}
+ QByteArray name;
+ //When used as a return type, the type name may be modified to remove the references.
+ // rawName is the type as found in the function signature
+ QByteArray rawName;
+ uint isVolatile : 1;
+ uint isScoped : 1;
++#if 0 // -- QtScxml
+ Token firstToken;
++#endif // -- QtScxml
+ ReferenceType referenceType;
+ };
+ Q_DECLARE_TYPEINFO(Type, Q_RELOCATABLE_TYPE);
+@@ -105,8 +105,9 @@
+ bool inlineCode = false;
+ bool wasCloned = false;
+
++#if 0 // -- QtScxml
+ bool returnTypeIsVolatile = false;
+-
++#endif // -- QtScxml
+ bool isCompat = false;
+ bool isInvokable = false;
+ bool isScriptable = false;
+@@ -120,6 +121,11 @@
+
+ QJsonObject toJson() const;
+ static void accessToJson(QJsonObject *obj, Access acs);
++
++// -- QtScxml
++ QByteArray mangledName;
++ const char *implementation = nullptr;
++// -- QtScxml
+ };
+ Q_DECLARE_TYPEINFO(FunctionDef, Q_RELOCATABLE_TYPE);
+
+@@ -144,6 +150,10 @@
+ int location = -1; // token index, used for error reporting
+
+ QJsonObject toJson() const;
++
++// -- QtScxml
++ QByteArray mangledName;
++// -- QtScxml
+ };
+ Q_DECLARE_TYPEINFO(PropertyDef, Q_RELOCATABLE_TYPE);
+
+@@ -217,6 +227,7 @@
+ };
+ Q_DECLARE_TYPEINFO(NamespaceDef, Q_RELOCATABLE_TYPE);
+
++#if 0 // -- QtScxml
+ class Moc : public Parser
+ {
+ public:
+@@ -295,6 +306,7 @@
+ void checkSuperClasses(ClassDef *def);
+ void checkProperties(ClassDef* cdef);
+ };
++#endif // -- QtScxml
+
+ inline QByteArray noRef(const QByteArray &type)
+ {
diff --git a/tools/qscxmlc/moc_patches/outputrevision.h.patch b/tools/qscxmlc/moc_patches/outputrevision.h.patch
new file mode 100644
index 0000000..4defacc
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/outputrevision.h.patch
@@ -0,0 +1,25 @@
+--- .upstream/outputrevision.h 2021-01-20 17:08:05.000000000 +0200
++++ outputrevision.h 2021-03-19 15:52:02.000000000 +0200
+@@ -3,7 +3,7 @@
+ ** Copyright (C) 2016 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+-** This file is part of the tools applications of the Qt Toolkit.
++** This file is part of the QtScxml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+ ** Commercial License Usage
+@@ -29,7 +29,13 @@
+ #ifndef OUTPUTREVISION_H
+ #define OUTPUTREVISION_H
+
++#include <QtCore/qglobal.h> // -- QtScxml
++
++QT_BEGIN_NAMESPACE // -- QtScxml
++
+ // if the output revision changes, you MUST change it in qobjectdefs.h too
+ enum { mocOutputRevision = 68 }; // moc format output revision
+
++QT_END_NAMESPACE // -- QtScxml
++
+ #endif // OUTPUTREVISION_H
diff --git a/tools/qscxmlc/moc_patches/update_moc.sh b/tools/qscxmlc/moc_patches/update_moc.sh
new file mode 100755
index 0000000..1acc130
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/update_moc.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+#
+#############################################################################
+##
+## Copyright (C) 2021 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the QtScxml module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+############################################################################/
+
+usage() {
+ cat <<EOF >&2
+
+Usage: update_moc [gu] [moc directory]
+
+The moc directory should be qtbase's moc source directory
+(absolute or relative). The script must be run from the directory
+containing the moc files (moc.h et. al).
+
+The script has two modes:
+
+'g' Generates updated patches of the current qtscxml-specific moc
+ changes. Use this when the qtscxml-specific parts in moc files
+ have changed and the patches should be updated accordingly.
+
+'u' Updates the moc from the upstream qtbase moc.
+ This mode gets the applicable qtbase moc files from the provided
+ directory, and updates their qtscxml copies by applying patches to them.
+ If you have not modified qtscxml moc code and just want to update the moc
+ code from upstream, this is the one you should use.
+
+Examples:
+moc_patches/update_moc g ../../../qtbase/src/tools/moc
+moc_patches/update_moc u ../../../qtbase/src/tools/moc
+
+EOF
+ die "$@"
+}
+
+checkFile () {
+ for f
+ do [[ -f "$f" ]] || die "Error: file \"$f\" does not exist."
+ done
+}
+
+warn () { echo "$@" >&2; }
+die () {
+ [[ -h .upstream ]] && rm .upstream
+ warn "$@"
+ exit 1
+}
+
+generate_patch() {
+ echo Generating patches recording how qscxmlc moc differs from upstream.
+
+ # Link the upstream moc files to create a patch file with filepaths
+ # that are independent of the actual used upstream moc location.
+ ln -s "$MOC_DIR" .upstream
+
+ for file in "${FILES[@]}"
+ do
+ checkFile "$file" ".upstream/$file"
+ diff -u ".upstream/$file" "$file" > "moc_patches/$file.patch"
+ echo Generated "moc_patches/$file.patch"
+ done
+ # tidy up
+ rm .upstream
+}
+
+update_moc() {
+ echo Updating qscxmlc moc from upstream by applying saved patches.
+
+ for file in "${FILES[@]}"
+ do
+ checkFile "moc_patches/$file.patch" "$MOC_DIR/$file"
+ echo Patching file: "$file" with "moc_patches/$file.patch"
+ # overwrite the current file from upstream
+ cp "$MOC_DIR/$file" "$file"
+ if patch "$file" "moc_patches/$file.patch"
+ then echo Patched "$file"
+ else warn "Please hand-patch $file; see $file.orig and $file.rej and tidy them away when you are done."
+ fi
+ done
+}
+
+MODE="$1"
+MOC_DIR="$2"
+FILES=( "outputrevision.h" "moc.h" "generator.h" "generator.cpp" )
+
+[[ -f moc_patches/update_moc.sh ]] || usage "Error: script must be run from the tools/qscxmlc/ directory."
+[[ -n "$MOC_DIR" ]] || usage "Error: You did not specify a moc directory."
+[[ -d "$MOC_DIR" ]] || usage "Error: moc directory \"$MOC_DIR\" does not exist."
+
+case "$MODE" in
+ g) generate_patch ;;
+ u) update_moc ;;
+ *) usage "Error: mode \"$MODE\" is not recognized." ;;
+esac
+
+echo Done