summaryrefslogtreecommitdiffstats
path: root/tools/qscxmlc/moc_patches
diff options
context:
space:
mode:
Diffstat (limited to 'tools/qscxmlc/moc_patches')
-rw-r--r--tools/qscxmlc/moc_patches/generator.cpp.patch286
-rw-r--r--tools/qscxmlc/moc_patches/generator.h.patch51
-rw-r--r--tools/qscxmlc/moc_patches/moc.cpp.patch29
-rw-r--r--tools/qscxmlc/moc_patches/moc.h.patch94
-rw-r--r--tools/qscxmlc/moc_patches/outputrevision.h.patch16
-rwxr-xr-xtools/qscxmlc/moc_patches/update_moc.sh94
6 files changed, 570 insertions, 0 deletions
diff --git a/tools/qscxmlc/moc_patches/generator.cpp.patch b/tools/qscxmlc/moc_patches/generator.cpp.patch
new file mode 100644
index 0000000..26906d8
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/generator.cpp.patch
@@ -0,0 +1,286 @@
+--- .upstream/generator.cpp 2024-02-01 11:08:00.055494626 +0100
++++ generator.cpp 2024-02-05 14:18:32.229391845 +0100
+@@ -4,7 +4,9 @@
+ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+ #include "generator.h"
++#if 0 // -- QtScxml
+ #include "cbordevice.h"
++#endif // -- QtScxml
+ #include "outputrevision.h"
+ #include "utils.h"
+ #include <QtCore/qmetatype.h>
+@@ -25,6 +27,29 @@
+
+ using namespace QtMiscUtils;
+
++// -- 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())
+@@ -57,22 +82,25 @@
+ return nullptr;
+ }
+
+- Generator::Generator(Moc *moc, ClassDef *classDef, const QList<QByteArray> &metaTypes,
+- const QHash<QByteArray, QByteArray> &knownQObjectClasses,
+- const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile,
+- bool requireCompleteTypes)
+- : parser(moc),
+- out(outfile),
+- cdef(classDef),
+- metaTypes(metaTypes),
+- knownQObjectClasses(knownQObjectClasses),
+- knownGadgets(knownGadgets),
+- requireCompleteTypes(requireCompleteTypes)
+- {
+- if (cdef->superclassList.size())
+- purestSuperClass = cdef->superclassList.constFirst().classname;
++// -- 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().classname;
+ }
++// -- QtScxml
+
++#if 0 // -- QtScxml
+ static inline qsizetype lengthOfEscapeSequence(const QByteArray &s, qsizetype i)
+ {
+ if (s.at(i) != '\\' || i >= s.size() - 1)
+@@ -98,7 +126,7 @@
+
+ // Prints \a s to \a out, breaking it into lines of at most ColumnWidth. The
+ // opening and closing quotes are NOT included (it's up to the caller).
+-static void printStringWithIndentation(FILE *out, const QByteArray &s)
++static void printStringWithIndentation(QIODevice &out, const QByteArray &s) // -- QtScxml
+ {
+ static constexpr int ColumnWidth = 72;
+ const qsizetype len = s.size();
+@@ -116,6 +144,7 @@
+ idx += spanLen;
+ } while (idx < len);
+ }
++#endif // -- QtSxcml
+
+ void Generator::strreg(const QByteArray &s)
+ {
+@@ -270,12 +299,21 @@
+ qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
+ {
+ char comma = 0;
+- for (const QByteArray &str : strings) {
++// -- QtScxml
++ for (qsizetype i = 0, end = strings.size(); i < end; ++i) {
+ if (comma)
+ fputc(comma, out);
+- printStringWithIndentation(out, str);
++ fprintf(out, "\n {");
++ const QByteArray s = strings.at(i);
++ const qsizetype len = s.size();
++ for (qsizetype charPos = 0; charPos < len; ++charPos)
++ fprintf(out, "char(0x%.2x),", static_cast<quint8>(s.at(charPos)));
++ const bool isLast = (i == end - 1);
++ fprintf(out, "char(0)%s // %d: %s", isLast ? "}" : "},", i, s.constData());
+ comma = ',';
+ }
++// -- QtScxml
++
+ }
+ fprintf(out, "\n);\n"
+ "#else // !QT_MOC_HAS_STRINGDATA\n");
+@@ -298,8 +336,10 @@
+ qsizetype methodCount = 0;
+ if (qAddOverflow(cdef->signalList.size(), cdef->slotList.size(), &methodCount)
+ || qAddOverflow(cdef->methodList.size(), methodCount, &methodCount)) {
+- parser->error("internal limit exceeded: the total number of member functions"
++// -- QtScxml
++ qFatal("internal limit exceeded: the total number of member functions"
+ " (including signals and slots) is too big.");
++// -- QtScxml
+ }
+
+ fprintf(out, " %4" PRIdQSIZETYPE ", %4d, // methods\n", methodCount, methodCount ? index : 0);
+@@ -346,7 +386,9 @@
+ if (qAddOverflow(cdef->propertyList.size(), cdef->enumList.size(), &propEnumCount)
+ || qAddOverflow(propEnumCount, qsizetype(1), &propEnumCount)
+ || propEnumCount >= std::numeric_limits<int>::max()) {
+- parser->error("internal limit exceeded: number of property and enum metatypes is too big.");
++// -- QtScxml
++ qFatal("internal limit exceeded: number of property and enum metatypes is too big.");
++// -- QtScxml
+ }
+ int initialMetaTypeOffset = int(propEnumCount);
+
+@@ -585,7 +627,7 @@
+ 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",
++ " return static_cast<void*>(this);\n",
+ qualifiedClassNameIdentifier.constData());
+
+ // for all superclasses but the first one
+@@ -631,7 +673,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
+@@ -1100,6 +1144,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->");
+@@ -1178,6 +1229,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());
+@@ -1200,7 +1255,7 @@
+ else
+ fprintf(out, ");\n");
+ fprintf(out, " if (_t _q_method = &%s::%s; *reinterpret_cast<_t *>(_a[1]) == _q_method) {\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");
+@@ -1295,8 +1350,11 @@
+ fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s().value(); break;\n",
+ propindex, p.type.constData(), prefix.constData(), p.bind.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());
+@@ -1428,6 +1486,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());
+
+@@ -1476,10 +1538,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)
+@@ -1494,6 +1554,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 +1719,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..4fc3325
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/generator.h.patch
@@ -0,0 +1,51 @@
+--- .upstream/generator.h 2023-06-22 20:40:43.078529554 +0200
++++ generator.h 2024-02-05 14:06:04.258179059 +0100
+@@ -6,23 +6,34 @@
+
+ #include "moc.h"
+
++// -- QtScxml
++#include <QtCore/qhash.h>
++#include <QtCore/qlist.h>
++#include <QtCore/qiodevice.h>
++// -- QtScxml
++
+ QT_BEGIN_NAMESPACE
+
+ class Generator
+ {
+- Moc *parser = nullptr;
+- FILE *out;
++ QIODevice &out; // -- QtScxml
+ ClassDef *cdef;
+ QList<uint> meta_data;
+
+ public:
+- Generator(Moc *moc, ClassDef *classDef, const QList<QByteArray> &metaTypes,
++ 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();
+ qsizetype registeredStringsCount() { return strings.size(); };
+
++// -- QtScxml
++ void generateAccessorDefs();
++ void generateSignalDefs();
++// -- QtScxml
++
+ private:
+ bool registerableMetaType(const QByteArray &propertyType);
+ void registerClassInfoStrings();
+@@ -41,7 +52,9 @@
+ void generateMetacall();
+ void generateStaticMetacall();
+ void generateSignal(const FunctionDef *def, int index);
++#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.cpp.patch b/tools/qscxmlc/moc_patches/moc.cpp.patch
new file mode 100644
index 0000000..7b55c65
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/moc.cpp.patch
@@ -0,0 +1,29 @@
+--- .upstream/moc.cpp 2024-02-01 11:08:00.055494626 +0100
++++ moc.cpp 2024-02-05 14:06:04.258179059 +0100
+@@ -12,14 +12,15 @@
+ #include <QtCore/qdir.h>
+ #include <QtCore/qjsondocument.h>
+
+-// for normalizeTypeInternal
+-#include <private/qmetaobject_moc_p.h>
+-#include <private/qduplicatetracker_p.h>
++// -- QtScxml
++#include <QtCore/qjsonobject.h>
++// -- QtScxml
+
+ QT_BEGIN_NAMESPACE
+
+ using namespace Qt::StringLiterals;
+
++#if 0 // -- QtScxml
+ // only moc needs this function
+ static QByteArray normalizeType(const QByteArray &ba)
+ {
+@@ -1997,6 +1998,7 @@
+ }
+ }
+ }
++#endif // -- QtScxml
+
+ QJsonObject ClassDef::toJson() const
+ {
diff --git a/tools/qscxmlc/moc_patches/moc.h.patch b/tools/qscxmlc/moc_patches/moc.h.patch
new file mode 100644
index 0000000..dcdac6b
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/moc.h.patch
@@ -0,0 +1,94 @@
+--- .upstream/moc.h 2024-02-05 14:10:55.937714571 +0100
++++ moc.h 2024-02-05 14:12:52.133597464 +0100
+@@ -4,14 +4,12 @@
+ #ifndef MOC_H
+ #define MOC_H
+
+-#include "parser.h"
+-#include <qstringlist.h>
+-#include <qmap.h>
+-#include <qjsondocument.h>
+-#include <qjsonarray.h>
+-#include <qjsonobject.h>
+-#include <qtyperevision.h>
+-#include <stdio.h>
++// -- QtScxml
++#include <QtCore/qmap.h>
++#include <QtCore/qpair.h>
++#include <QtCore/qjsondocument.h>
++#include <QtCore/qjsonarray.h>
++// -- QtScxml
+
+ #include <private/qtools_p.h>
+
+@@ -23,16 +21,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);
+@@ -82,8 +82,9 @@
+ bool inlineCode = false;
+ bool wasCloned = false;
+
++#if 0 // -- QtScxml
+ bool returnTypeIsVolatile = false;
+-
++#endif // -- QtScxml
+ bool isCompat = false;
+ bool isInvokable = false;
+ bool isScriptable = false;
+@@ -97,6 +98,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);
+
+@@ -124,6 +130,10 @@
+ qsizetype location = -1; // token index, used for error reporting
+
+ QJsonObject toJson() const;
++
++// -- QtScxml
++ QByteArray mangledName;
++// -- QtScxml
+ };
+ Q_DECLARE_TYPEINFO(PropertyDef, Q_RELOCATABLE_TYPE);
+
+@@ -204,6 +214,7 @@
+ };
+ Q_DECLARE_TYPEINFO(NamespaceDef, Q_RELOCATABLE_TYPE);
+
++#if 0 // -- QtScxml
+ class Moc : public Parser
+ {
+ public:
+@@ -293,6 +304,7 @@
+
+ void checkListSizes(const ClassDef &def);
+ };
++#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..be3c2eb
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/outputrevision.h.patch
@@ -0,0 +1,16 @@
+--- .upstream/outputrevision.h 2022-05-23 08:46:14.490945334 +0200
++++ outputrevision.h 2024-02-05 14:06:04.254179068 +0100
+@@ -4,7 +4,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..410c9da
--- /dev/null
+++ b/tools/qscxmlc/moc_patches/update_moc.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+# Copyright (C) 2021 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+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.cpp" "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