diff options
Diffstat (limited to 'src/tools/moc')
-rw-r--r-- | src/tools/moc/generator.cpp | 1312 | ||||
-rw-r--r-- | src/tools/moc/generator.h | 81 | ||||
-rw-r--r-- | src/tools/moc/keywords.cpp | 979 | ||||
-rw-r--r-- | src/tools/moc/main.cpp | 459 | ||||
-rw-r--r-- | src/tools/moc/moc.cpp | 1230 | ||||
-rw-r--r-- | src/tools/moc/moc.h | 247 | ||||
-rw-r--r-- | src/tools/moc/moc.pri | 16 | ||||
-rw-r--r-- | src/tools/moc/moc.pro | 18 | ||||
-rw-r--r-- | src/tools/moc/mwerks_mac.cpp | 240 | ||||
-rw-r--r-- | src/tools/moc/mwerks_mac.h | 67 | ||||
-rw-r--r-- | src/tools/moc/outputrevision.h | 48 | ||||
-rw-r--r-- | src/tools/moc/parser.cpp | 81 | ||||
-rw-r--r-- | src/tools/moc/parser.h | 108 | ||||
-rw-r--r-- | src/tools/moc/ppkeywords.cpp | 248 | ||||
-rw-r--r-- | src/tools/moc/preprocessor.cpp | 983 | ||||
-rw-r--r-- | src/tools/moc/preprocessor.h | 102 | ||||
-rw-r--r-- | src/tools/moc/symbols.h | 147 | ||||
-rw-r--r-- | src/tools/moc/token.cpp | 222 | ||||
-rw-r--r-- | src/tools/moc/token.h | 274 | ||||
-rwxr-xr-x | src/tools/moc/util/generate.sh | 7 | ||||
-rw-r--r-- | src/tools/moc/util/generate_keywords.cpp | 468 | ||||
-rw-r--r-- | src/tools/moc/util/generate_keywords.pro | 13 | ||||
-rw-r--r-- | src/tools/moc/util/licenseheader.txt | 41 | ||||
-rw-r--r-- | src/tools/moc/utils.h | 111 |
24 files changed, 7502 insertions, 0 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp new file mode 100644 index 0000000..ae8a76e --- /dev/null +++ b/src/tools/moc/generator.cpp @@ -0,0 +1,1312 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "generator.h" +#include "outputrevision.h" +#include "utils.h" +#include <QtCore/qmetatype.h> +#include <stdio.h> + +QT_BEGIN_NAMESPACE + +// if the flags change, you MUST to change it in qmetaobject.cpp too +enum PropertyFlags { + Invalid = 0x00000000, + Readable = 0x00000001, + Writable = 0x00000002, + Resettable = 0x00000004, + EnumOrFlag = 0x00000008, + StdCppSet = 0x00000100, +// Override = 0x00000200, + Designable = 0x00001000, + ResolveDesignable = 0x00002000, + Scriptable = 0x00004000, + ResolveScriptable = 0x00008000, + Stored = 0x00010000, + ResolveStored = 0x00020000, + Editable = 0x00040000, + ResolveEditable = 0x00080000, + User = 0x00100000, + ResolveUser = 0x00200000, + Notify = 0x00400000 +}; +enum MethodFlags { + AccessPrivate = 0x00, + AccessProtected = 0x01, + AccessPublic = 0x02, + MethodMethod = 0x00, + MethodSignal = 0x04, + MethodSlot = 0x08, + MethodConstructor = 0x0c, + MethodCompatibility = 0x10, + MethodCloned = 0x20, + MethodScriptable = 0x40 +}; + +uint qvariant_nameToType(const char* name) +{ + if (!name) + return 0; + + if (strcmp(name, "QVariant") == 0) + return 0xffffffff; + if (strcmp(name, "QCString") == 0) + return QMetaType::QByteArray; + if (strcmp(name, "Q_LLONG") == 0) + return QMetaType::LongLong; + if (strcmp(name, "Q_ULLONG") == 0) + return QMetaType::ULongLong; + if (strcmp(name, "QIconSet") == 0) + return QMetaType::QIcon; + + uint tp = QMetaType::type(name); + return tp < QMetaType::User ? tp : 0; +} + +/* + Returns true if the type is a QVariant types. +*/ +bool isVariantType(const char* type) +{ + return qvariant_nameToType(type) != 0; +} + +Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile) + : out(outfile), cdef(classDef), metaTypes(metaTypes) +{ + if (cdef->superclassList.size()) + purestSuperClass = cdef->superclassList.first().first; +} + +static inline int lengthOfEscapeSequence(const QByteArray &s, int i) +{ + if (s.at(i) != '\\' || i >= s.length() - 1) + return 1; + const int startPos = i; + ++i; + char ch = s.at(i); + if (ch == 'x') { + ++i; + while (i < s.length() && is_hex_char(s.at(i))) + ++i; + } else if (is_octal_char(ch)) { + while (i < startPos + 4 + && i < s.length() + && is_octal_char(s.at(i))) { + ++i; + } + } else { // single character escape sequence + i = qMin(i + 1, s.length()); + } + return i - startPos; +} + +int Generator::strreg(const char *s) +{ + int idx = 0; + if (!s) + s = ""; + for (int i = 0; i < strings.size(); ++i) { + const QByteArray &str = strings.at(i); + if (str == s) + return idx; + idx += str.length() + 1; + for (int i = 0; i < str.length(); ++i) { + if (str.at(i) == '\\') { + int cnt = lengthOfEscapeSequence(str, i) - 1; + idx -= cnt; + i += cnt; + } + } + } + strings.append(s); + return idx; +} + +void Generator::generateCode() +{ + bool isQt = (cdef->classname == "Qt"); + bool isQObject = (cdef->classname == "QObject"); + bool isConstructible = !cdef->constructorList.isEmpty(); + +// +// build the data array +// + int i = 0; + + + // filter out undeclared enumerators and sets + { + QList<EnumDef> enumList; + for (i = 0; i < cdef->enumList.count(); ++i) { + EnumDef def = cdef->enumList.at(i); + if (cdef->enumDeclarations.contains(def.name)) { + enumList += def; + } + QByteArray alias = cdef->flagAliases.value(def.name); + if (cdef->enumDeclarations.contains(alias)) { + def.name = alias; + enumList += def; + } + } + cdef->enumList = enumList; + } + + + QByteArray qualifiedClassNameIdentifier = cdef->qualified; + qualifiedClassNameIdentifier.replace(':', '_'); + + int index = 12; + fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData()); + fprintf(out, "\n // content:\n"); + fprintf(out, " %4d, // revision\n", 2); + fprintf(out, " %4d, // classname\n", strreg(cdef->qualified)); + fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); + index += cdef->classInfoList.count() * 2; + + int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); + fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0); + index += methodCount * 5; + fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0); + index += cdef->propertyList.count() * 3; + if(cdef->notifyableProperties) + index += cdef->propertyList.count(); + fprintf(out, " %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0); + + int enumsIndex = index; + for (i = 0; i < cdef->enumList.count(); ++i) + index += 4 + (cdef->enumList.at(i).values.count() * 2); + fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0, + isConstructible ? index : 0); + +// +// Build classinfo array +// + generateClassInfos(); + +// +// Build signals array first, otherwise the signal indices would be wrong +// + generateFunctions(cdef->signalList, "signal", MethodSignal); + +// +// Build slots array +// + generateFunctions(cdef->slotList, "slot", MethodSlot); + +// +// Build method array +// + generateFunctions(cdef->methodList, "method", MethodMethod); + + +// +// Build property array +// + generateProperties(); + +// +// Build enums array +// + generateEnums(enumsIndex); + +// +// Build constructors array +// + if (isConstructible) + generateFunctions(cdef->constructorList, "constructor", MethodConstructor); + +// +// Terminate data array +// + fprintf(out, "\n 0 // eod\n};\n\n"); + +// +// Build stringdata array +// + fprintf(out, "static const char qt_meta_stringdata_%s[] = {\n", qualifiedClassNameIdentifier.constData()); + fprintf(out, " \""); + int col = 0; + int len = 0; + for (i = 0; i < strings.size(); ++i) { + QByteArray s = strings.at(i); + len = s.length(); + 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); + } + fwrite(s.constData() + idx, 1, spanLen, out); + idx += spanLen; + col += spanLen; + } + + fputs("\\0", out); + col += len + 2; + } + fprintf(out, "\"\n};\n\n"); + + +// +// Generate internal qt_static_metacall() function +// + if (isConstructible) + generateStaticMetacall(qualifiedClassNameIdentifier); + +// +// Build extra array +// + QList<QByteArray> extraList; + for (int i = 0; i < cdef->propertyList.count(); ++i) { + const PropertyDef &p = cdef->propertyList.at(i); + if (!isVariantType(p.type) && !metaTypes.contains(p.type)) { + int s = p.type.lastIndexOf("::"); + if (s > 0) { + QByteArray scope = p.type.left(s); + if (scope != "Qt" && scope != cdef->classname && !extraList.contains(scope)) + extraList += scope; + } + } + } + if (!extraList.isEmpty()) { + fprintf(out, "static const QMetaObject *qt_meta_extradata_%s[] = {\n ", qualifiedClassNameIdentifier.constData()); + for (int i = 0; i < extraList.count(); ++i) { + if (i) + fprintf(out, ",\n "); + fprintf(out, " &%s::staticMetaObject", extraList.at(i).constData()); + } + fprintf(out, ",0\n};\n\n"); + } + + if (isConstructible || !extraList.isEmpty()) { + fprintf(out, "static const QMetaObjectExtraData qt_meta_extradata2_%s = {\n ", + qualifiedClassNameIdentifier.constData()); + if (extraList.isEmpty()) + fprintf(out, "0, "); + else + fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData()); + if (!isConstructible) + fprintf(out, "0"); + else + fprintf(out, "%s_qt_static_metacall", qualifiedClassNameIdentifier.constData()); + fprintf(out, " \n};\n\n"); + } + +// +// Finally create and initialize the static meta object +// + + if (isQt) + fprintf(out, "const QMetaObject QObject::staticQtMetaObject = {\n"); + else + fprintf(out, "const QMetaObject %s::staticMetaObject = {\n", cdef->qualified.constData()); + + if (isQObject) + fprintf(out, " { 0, "); + else if (cdef->superclassList.size()) + fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData()); + else + fprintf(out, " { 0, "); + fprintf(out, "qt_meta_stringdata_%s,\n qt_meta_data_%s, ", + qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); + if (!isConstructible && extraList.isEmpty()) + fprintf(out, "0 }\n"); + else + fprintf(out, "&qt_meta_extradata2_%s }\n", qualifiedClassNameIdentifier.constData()); + fprintf(out, "};\n"); + + if (isQt || !cdef->hasQObject) + return; + + fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return &staticMetaObject;\n}\n", + cdef->qualified.constData()); +// +// Generate smart cast function +// + fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData()); + fprintf(out, " if (!_clname) return 0;\n"); + fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s))\n" + " return static_cast<void*>(const_cast< %s*>(this));\n", + qualifiedClassNameIdentifier.constData(), cdef->classname.constData()); + 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; + const char *cname = cdef->superclassList.at(i).first; + fprintf(out, " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(const_cast< %s*>(this));\n", + cname, cname, cdef->classname.constData()); + } + for (int i = 0; i < cdef->interfaceList.size(); ++i) { + const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i); + for (int j = 0; j < iface.size(); ++j) { + fprintf(out, " if (!strcmp(_clname, %s))\n return ", iface.at(j).interfaceId.constData()); + for (int k = j; k >= 0; --k) + fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData()); + fprintf(out, "const_cast< %s*>(this)%s;\n", + cdef->classname.constData(), QByteArray(j+1, ')').constData()); + } + } + if (!purestSuperClass.isEmpty() && !isQObject) { + QByteArray superClass = purestSuperClass; + // workaround for VC6 + if (superClass.contains("::")) { + fprintf(out, " typedef %s QMocSuperClass;\n", superClass.constData()); + superClass = "QMocSuperClass"; + } + fprintf(out, " return %s::qt_metacast(_clname);\n", superClass.constData()); + } else { + fprintf(out, " return 0;\n"); + } + fprintf(out, "}\n"); + +// +// Generate internal qt_metacall() function +// + generateMetacall(); + +// +// Generate internal signal functions +// + for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex) + generateSignal(&cdef->signalList[signalindex], signalindex); +} + + +void Generator::generateClassInfos() +{ + if (cdef->classInfoList.isEmpty()) + return; + + fprintf(out, "\n // classinfo: key, value\n"); + + for (int i = 0; i < cdef->classInfoList.size(); ++i) { + const ClassInfoDef &c = cdef->classInfoList.at(i); + fprintf(out, " %4d, %4d,\n", strreg(c.name), strreg(c.value)); + } +} + +void Generator::generateFunctions(QList<FunctionDef>& list, const char *functype, int type) +{ + if (list.isEmpty()) + return; + fprintf(out, "\n // %ss: signature, parameters, type, tag, flags\n", functype); + + for (int i = 0; i < list.count(); ++i) { + const FunctionDef &f = list.at(i); + + QByteArray sig = f.name + '('; + QByteArray arguments; + + for (int j = 0; j < f.arguments.count(); ++j) { + const ArgumentDef &a = f.arguments.at(j); + if (j) { + sig += ","; + arguments += ","; + } + sig += a.normalizedType; + arguments += a.name; + } + sig += ')'; + + char flags = type; + if (f.access == FunctionDef::Private) + flags |= AccessPrivate; + else if (f.access == FunctionDef::Public) + flags |= AccessPublic; + else if (f.access == FunctionDef::Protected) + flags |= AccessProtected; + if (f.access == FunctionDef::Private) + flags |= AccessPrivate; + else if (f.access == FunctionDef::Public) + flags |= AccessPublic; + else if (f.access == FunctionDef::Protected) + flags |= AccessProtected; + if (f.isCompat) + flags |= MethodCompatibility; + if (f.wasCloned) + flags |= MethodCloned; + if (f.isScriptable) + flags |= MethodScriptable; + fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", strreg(sig), + strreg(arguments), strreg(f.normalizedType), strreg(f.tag), flags); + } +} + +void Generator::generateProperties() +{ + // + // specify get function, for compatibiliy we accept functions + // returning pointers, or const char * for QByteArray. + // + for (int i = 0; i < cdef->propertyList.count(); ++i) { + PropertyDef &p = cdef->propertyList[i]; + if (p.read.isEmpty()) + continue; + for (int j = 0; j < cdef->publicList.count(); ++j) { + const FunctionDef &f = cdef->publicList.at(j); + if (f.name != p.read) + continue; + if (!f.isConst) // get functions must be const + continue; + if (f.arguments.size()) // and must not take any arguments + continue; + PropertyDef::Specification spec = PropertyDef::ValueSpec; + QByteArray tmp = f.normalizedType; + if (p.type == "QByteArray" && tmp == "const char *") + tmp = "QByteArray"; + if (tmp.left(6) == "const ") + tmp = tmp.mid(6); + if (p.type != tmp && tmp.endsWith('*')) { + tmp.chop(1); + spec = PropertyDef::PointerSpec; + } else if (f.type.name.endsWith('&')) { // raw type, not normalized type + spec = PropertyDef::ReferenceSpec; + } + if (p.type != tmp) + continue; + p.gspec = spec; + break; + } + if(!p.notify.isEmpty()) { + int notifyId = -1; + for (int j = 0; j < cdef->signalList.count(); ++j) { + const FunctionDef &f = cdef->signalList.at(j); + if(f.name != p.notify) { + continue; + } else { + notifyId = j /* Signal indexes start from 0 */; + break; + } + } + p.notifyId = notifyId; + } + } + + // + // Create meta data + // + + if (cdef->propertyList.count()) + fprintf(out, "\n // properties: name, type, flags\n"); + for (int i = 0; i < cdef->propertyList.count(); ++i) { + const PropertyDef &p = cdef->propertyList.at(i); + uint flags = Invalid; + if (!isVariantType(p.type)) { + flags |= EnumOrFlag; + } else { + flags |= qvariant_nameToType(p.type) << 24; + } + if (!p.read.isEmpty()) + flags |= Readable; + if (!p.write.isEmpty()) { + flags |= Writable; + if (p.stdCppSet()) + flags |= StdCppSet; + } + if (!p.reset.isEmpty()) + flags |= Resettable; + +// if (p.override) +// flags |= Override; + + if (p.designable.isEmpty()) + flags |= ResolveDesignable; + else if (p.designable != "false") + flags |= Designable; + + if (p.scriptable.isEmpty()) + flags |= ResolveScriptable; + else if (p.scriptable != "false") + flags |= Scriptable; + + if (p.stored.isEmpty()) + flags |= ResolveStored; + else if (p.stored != "false") + flags |= Stored; + + if (p.editable.isEmpty()) + flags |= ResolveEditable; + else if (p.editable != "false") + flags |= Editable; + + if (p.user.isEmpty()) + flags |= ResolveUser; + else if (p.user != "false") + flags |= User; + + if (p.notifyId != -1) + flags |= Notify; + + fprintf(out, " %4d, %4d, 0x%.8x,\n", + strreg(p.name), + strreg(p.type), + flags); + } + + if(cdef->notifyableProperties) { + fprintf(out, "\n // properties: notify_signal_id\n"); + for (int i = 0; i < cdef->propertyList.count(); ++i) { + const PropertyDef &p = cdef->propertyList.at(i); + if(p.notifyId == -1) + fprintf(out, " %4d,\n", + 0); + else + fprintf(out, " %4d,\n", + p.notifyId); + } + } +} + +void Generator::generateEnums(int index) +{ + if (cdef->enumDeclarations.isEmpty()) + return; + + fprintf(out, "\n // enums: name, flags, count, data\n"); + index += 4 * cdef->enumList.count(); + int i; + for (i = 0; i < cdef->enumList.count(); ++i) { + const EnumDef &e = cdef->enumList.at(i); + fprintf(out, " %4d, 0x%.1x, %4d, %4d,\n", + strreg(e.name), + cdef->enumDeclarations.value(e.name) ? 1 : 0, + e.values.count(), + index); + index += e.values.count() * 2; + } + + fprintf(out, "\n // enum data: key, value\n"); + for (i = 0; i < cdef->enumList.count(); ++i) { + const EnumDef &e = cdef->enumList.at(i); + for (int j = 0; j < e.values.count(); ++j) { + const QByteArray &val = e.values.at(j); + fprintf(out, " %4d, uint(%s::%s),\n", + strreg(val), + cdef->qualified.constData(), + val.constData()); + } + } +} + +void Generator::generateMetacall() +{ + bool isQObject = (cdef->classname == "QObject"); + + fprintf(out, "\nint %s::qt_metacall(QMetaObject::Call _c, int _id, void **_a)\n{\n", + cdef->qualified.constData()); + + if (!purestSuperClass.isEmpty() && !isQObject) { + QByteArray superClass = purestSuperClass; + // workaround for VC6 + if (superClass.contains("::")) { + fprintf(out, " typedef %s QMocSuperClass;\n", superClass.constData()); + superClass = "QMocSuperClass"; + } + fprintf(out, " _id = %s::qt_metacall(_c, _id, _a);\n", superClass.constData()); + } + + fprintf(out, " if (_id < 0)\n return _id;\n"); + fprintf(out, " "); + + bool needElse = false; + QList<FunctionDef> methodList; + methodList += cdef->signalList; + methodList += cdef->slotList; + methodList += cdef->methodList; + + if (methodList.size()) { + needElse = true; + fprintf(out, "if (_c == QMetaObject::InvokeMetaMethod) {\n "); + fprintf(out, "switch (_id) {\n"); + for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) { + const FunctionDef &f = methodList.at(methodindex); + fprintf(out, " case %d: ", methodindex); + if (f.normalizedType.size()) + fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData()); + if (f.inPrivateClass.size()) + fprintf(out, "%s->", f.inPrivateClass.constData()); + fprintf(out, "%s(", f.name.constData()); + int offset = 1; + for (int j = 0; j < f.arguments.count(); ++j) { + const ArgumentDef &a = f.arguments.at(j); + if (j) + fprintf(out, ","); + fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++); + } + fprintf(out, ");"); + if (f.normalizedType.size()) + fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ", + noRef(f.normalizedType).constData()); + fprintf(out, " break;\n"); + } + fprintf(out, " default: ;\n"); + fprintf(out, " }\n"); + } + if (methodList.size()) + fprintf(out, " _id -= %d;\n }", methodList.size()); + + if (cdef->propertyList.size()) { + bool needGet = false; + bool needTempVarForGet = false; + bool needSet = false; + bool needReset = false; + bool needDesignable = false; + bool needScriptable = false; + bool needStored = false; + bool needEditable = false; + bool needUser = false; + for (int i = 0; i < cdef->propertyList.size(); ++i) { + const PropertyDef &p = cdef->propertyList.at(i); + needGet |= !p.read.isEmpty(); + if (!p.read.isEmpty()) + needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec + && p.gspec != PropertyDef::ReferenceSpec); + + needSet |= !p.write.isEmpty(); + needReset |= !p.reset.isEmpty(); + needDesignable |= p.designable.endsWith(')'); + needScriptable |= p.scriptable.endsWith(')'); + needStored |= p.stored.endsWith(')'); + needEditable |= p.editable.endsWith(')'); + needUser |= p.user.endsWith(')'); + } + bool needAnything = needGet + | needSet + | needReset + | needDesignable + | needScriptable + | needStored + | needEditable + | needUser; + if (!needAnything) + goto skip_properties; + fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n "); + + if (needElse) + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n"); + if (needGet) { + if (needTempVarForGet) + fprintf(out, " void *_v = _a[0];\n"); + fprintf(out, " switch (_id) {\n"); + for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { + const PropertyDef &p = cdef->propertyList.at(propindex); + if (p.read.isEmpty()) + continue; + if (p.gspec == PropertyDef::PointerSpec) + fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s())); break;\n", + propindex, p.read.constData()); + else if (p.gspec == PropertyDef::ReferenceSpec) + fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s())); break;\n", + propindex, p.read.constData()); + else if (cdef->enumDeclarations.value(p.type, false)) + fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s()); break;\n", + propindex, p.read.constData()); + else + fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s(); break;\n", + propindex, p.type.constData(), p.read.constData()); + } + fprintf(out, " }\n"); + } + + fprintf(out, + " _id -= %d;\n" + " }", cdef->propertyList.count()); + + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::WriteProperty) {\n"); + + if (needSet) { + fprintf(out, " void *_v = _a[0];\n"); + fprintf(out, " switch (_id) {\n"); + for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { + const PropertyDef &p = cdef->propertyList.at(propindex); + if (p.write.isEmpty()) + continue; + if (cdef->enumDeclarations.value(p.type, false)) { + fprintf(out, " case %d: %s(QFlag(*reinterpret_cast<int*>(_v))); break;\n", + propindex, p.write.constData()); + } else { + fprintf(out, " case %d: %s(*reinterpret_cast< %s*>(_v)); break;\n", + propindex, p.write.constData(), p.type.constData()); + } + } + fprintf(out, " }\n"); + } + + fprintf(out, + " _id -= %d;\n" + " }", cdef->propertyList.count()); + + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::ResetProperty) {\n"); + if (needReset) { + fprintf(out, " switch (_id) {\n"); + for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { + const PropertyDef &p = cdef->propertyList.at(propindex); + if (!p.reset.endsWith(')')) + continue; + fprintf(out, " case %d: %s; break;\n", + propindex, p.reset.constData()); + } + fprintf(out, " }\n"); + } + fprintf(out, + " _id -= %d;\n" + " }", cdef->propertyList.count()); + + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::QueryPropertyDesignable) {\n"); + if (needDesignable) { + fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n"); + fprintf(out, " switch (_id) {\n"); + for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { + const PropertyDef &p = cdef->propertyList.at(propindex); + if (!p.designable.endsWith(')')) + continue; + fprintf(out, " case %d: *_b = %s; break;\n", + propindex, p.designable.constData()); + } + fprintf(out, " }\n"); + } + fprintf(out, + " _id -= %d;\n" + " }", cdef->propertyList.count()); + + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::QueryPropertyScriptable) {\n"); + if (needScriptable) { + fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n"); + fprintf(out, " switch (_id) {\n"); + for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { + const PropertyDef &p = cdef->propertyList.at(propindex); + if (!p.scriptable.endsWith(')')) + continue; + fprintf(out, " case %d: *_b = %s; break;\n", + propindex, p.scriptable.constData()); + } + fprintf(out, " }\n"); + } + fprintf(out, + " _id -= %d;\n" + " }", cdef->propertyList.count()); + + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::QueryPropertyStored) {\n"); + if (needStored) { + fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n"); + fprintf(out, " switch (_id) {\n"); + for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { + const PropertyDef &p = cdef->propertyList.at(propindex); + if (!p.stored.endsWith(')')) + continue; + fprintf(out, " case %d: *_b = %s; break;\n", + propindex, p.stored.constData()); + } + fprintf(out, " }\n"); + } + fprintf(out, + " _id -= %d;\n" + " }", cdef->propertyList.count()); + + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::QueryPropertyEditable) {\n"); + if (needEditable) { + fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n"); + fprintf(out, " switch (_id) {\n"); + for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { + const PropertyDef &p = cdef->propertyList.at(propindex); + if (!p.editable.endsWith(')')) + continue; + fprintf(out, " case %d: *_b = %s; break;\n", + propindex, p.editable.constData()); + } + fprintf(out, " }\n"); + } + fprintf(out, + " _id -= %d;\n" + " }", cdef->propertyList.count()); + + + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::QueryPropertyUser) {\n"); + if (needUser) { + fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n"); + fprintf(out, " switch (_id) {\n"); + for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { + const PropertyDef &p = cdef->propertyList.at(propindex); + if (!p.user.endsWith(')')) + continue; + fprintf(out, " case %d: *_b = %s; break;\n", + propindex, p.user.constData()); + } + fprintf(out, " }\n"); + } + fprintf(out, + " _id -= %d;\n" + " }", cdef->propertyList.count()); + + + fprintf(out, "\n#endif // QT_NO_PROPERTIES"); + } + skip_properties: + if (methodList.size() || cdef->signalList.size() || cdef->propertyList.size()) + fprintf(out, "\n "); + fprintf(out,"return _id;\n}\n"); +} + +void Generator::generateStaticMetacall(const QByteArray &prefix) +{ + bool isQObject = (cdef->classname == "QObject"); + + fprintf(out, "static int %s_qt_static_metacall(QMetaObject::Call _c, int _id, void **_a)\n{\n", + prefix.constData()); + + fprintf(out, " if (_c == QMetaObject::CreateInstance) {\n"); + fprintf(out, " switch (_id) {\n"); + for (int ctorindex = 0; ctorindex < cdef->constructorList.count(); ++ctorindex) { + fprintf(out, " case %d: { %s *_r = new %s(", ctorindex, + cdef->classname.constData(), cdef->classname.constData()); + const FunctionDef &f = cdef->constructorList.at(ctorindex); + int offset = 1; + for (int j = 0; j < f.arguments.count(); ++j) { + const ArgumentDef &a = f.arguments.at(j); + if (j) + fprintf(out, ","); + fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))", a.typeNameForCast.constData(), offset++); + } + fprintf(out, ");\n"); + fprintf(out, " if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;\n"); + } + fprintf(out, " }\n"); + fprintf(out, " _id -= %d;\n", cdef->constructorList.count()); + fprintf(out, " return _id;\n"); + fprintf(out, " }\n"); + + if (!isQObject) + fprintf(out, " _id = %s::staticMetaObject.superClass()->static_metacall(_c, _id, _a);\n", cdef->classname.constData()); + + fprintf(out, " if (_id < 0)\n return _id;\n"); + + fprintf(out, " return _id;\n"); + fprintf(out, "}\n\n"); +} + +void Generator::generateSignal(FunctionDef *def,int index) +{ + if (def->wasCloned || def->isAbstract) + return; + fprintf(out, "\n// SIGNAL %d\n%s %s::%s(", + index, def->type.name.constData(), cdef->qualified.constData(), def->name.constData()); + + QByteArray thisPtr = "this"; + const char *constQualifier = ""; + + if (def->isConst) { + thisPtr = "const_cast< "; + thisPtr += cdef->qualified; + thisPtr += " *>(this)"; + constQualifier = "const"; + } + + if (def->arguments.isEmpty() && def->normalizedType.isEmpty()) { + fprintf(out, ")%s\n{\n" + " QMetaObject::activate(%s, &staticMetaObject, %d, 0);\n" + "}\n", constQualifier, thisPtr.constData(), index); + return; + } + + int offset = 1; + for (int j = 0; j < def->arguments.count(); ++j) { + const ArgumentDef &a = def->arguments.at(j); + if (j) + fprintf(out, ", "); + fprintf(out, "%s _t%d%s", a.type.name.constData(), offset++, a.rightType.constData()); + } + fprintf(out, ")%s\n{\n", constQualifier); + if (def->type.name.size() && def->normalizedType.size()) + fprintf(out, " %s _t0;\n", noRef(def->normalizedType).constData()); + + fprintf(out, " void *_a[] = { "); + if (def->normalizedType.isEmpty()) { + fprintf(out, "0"); + } else { + if (def->returnTypeIsVolatile) + fprintf(out, "const_cast<void*>(reinterpret_cast<const volatile void*>(&_t0))"); + else + fprintf(out, "const_cast<void*>(reinterpret_cast<const void*>(&_t0))"); + } + int i; + for (i = 1; i < offset; ++i) + if (def->arguments.at(i - 1).type.isVolatile) + fprintf(out, ", const_cast<void*>(reinterpret_cast<const volatile void*>(&_t%d))", i); + else + fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(&_t%d))", i); + fprintf(out, " };\n"); + int n = 0; + for (i = 0; i < def->arguments.count(); ++i) + if (def->arguments.at(i).isDefault) + ++n; + if (n) + fprintf(out, " QMetaObject::activate(%s, &staticMetaObject, %d, %d, _a);\n", thisPtr.constData(), index, index + n); + else + fprintf(out, " QMetaObject::activate(%s, &staticMetaObject, %d, _a);\n", thisPtr.constData(), index); + if (def->normalizedType.size()) + fprintf(out, " return _t0;\n"); + fprintf(out, "}\n"); +} + +// +// Functions used when generating QMetaObject directly +// +// Much of this code is copied from the corresponding +// C++ code-generating functions; we can change the +// two generators so that more of the code is shared. +// The key difference from the C++ code generator is +// that instead of calling fprintf(), we append bytes +// to a buffer. +// + +QMetaObject *Generator::generateMetaObject(bool ignoreProperties) +{ +// +// build the data array +// + + // filter out undeclared enumerators and sets + { + QList<EnumDef> enumList; + for (int i = 0; i < cdef->enumList.count(); ++i) { + EnumDef def = cdef->enumList.at(i); + if (cdef->enumDeclarations.contains(def.name)) { + enumList += def; + } + QByteArray alias = cdef->flagAliases.value(def.name); + if (cdef->enumDeclarations.contains(alias)) { + def.name = alias; + enumList += def; + } + } + cdef->enumList = enumList; + } + + int index = 10; + meta_data + << 1 // revision + << strreg(cdef->qualified) // classname + << cdef->classInfoList.count() << (cdef->classInfoList.count() ? index : 0) // classinfo + ; + index += cdef->classInfoList.count() * 2; + + int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); + meta_data << methodCount << (methodCount ? index : 0); // methods + index += methodCount * 5; + if (!ignoreProperties) { + meta_data << cdef->propertyList.count() << (cdef->propertyList.count() ? index : 0); // properties + index += cdef->propertyList.count() * 3; + } else { + meta_data << 0 << 0; // properties + } + meta_data << cdef->enumList.count() << (cdef->enumList.count() ? index : 0); // enums/sets + +// +// Build classinfo array +// + _generateClassInfos(); + +// +// Build signals array first, otherwise the signal indices would be wrong +// + _generateFunctions(cdef->signalList, MethodSignal); + +// +// Build slots array +// + _generateFunctions(cdef->slotList, MethodSlot); + +// +// Build method array +// + _generateFunctions(cdef->methodList, MethodMethod); + + +// +// Build property array +// + if (!ignoreProperties) + _generateProperties(); + +// +// Build enums array +// + _generateEnums(index); + +// +// Terminate data array +// + meta_data << 0; + +// +// Build stringdata array +// + QVector<char> string_data; + for (int i = 0; i < strings.size(); ++i) { + const char *s = strings.at(i).constData(); + char c; + do { + c = *(s++); + string_data << c; + } while (c != '\0'); + } + +// +// Finally create and initialize the static meta object +// + const int meta_object_offset = 0; + const int meta_object_size = sizeof(QMetaObject); + const int meta_data_offset = meta_object_offset + meta_object_size; + const int meta_data_size = meta_data.count() * sizeof(uint); + const int string_data_offset = meta_data_offset + meta_data_size; + const int string_data_size = string_data.count(); + const int total_size = string_data_offset + string_data_size; + + char *blob = new char[total_size]; + + char *string_data_output = blob + string_data_offset; + const char *string_data_src = string_data.constData(); + for (int i = 0; i < string_data.count(); ++i) + string_data_output[i] = string_data_src[i]; + + uint *meta_data_output = reinterpret_cast<uint *>(blob + meta_data_offset); + const uint *meta_data_src = meta_data.constData(); + for (int i = 0; i < meta_data.count(); ++i) + meta_data_output[i] = meta_data_src[i]; + + QMetaObject *meta_object = new (blob + meta_object_offset)QMetaObject; + meta_object->d.superdata = 0; + meta_object->d.stringdata = string_data_output; + meta_object->d.data = meta_data_output; + meta_object->d.extradata = 0; + return meta_object; +} + +void Generator::_generateClassInfos() +{ + for (int i = 0; i < cdef->classInfoList.size(); ++i) { + const ClassInfoDef &c = cdef->classInfoList.at(i); + meta_data << strreg(c.name) << strreg(c.value); + } +} + +void Generator::_generateFunctions(QList<FunctionDef> &list, int type) +{ + for (int i = 0; i < list.count(); ++i) { + const FunctionDef &f = list.at(i); + + QByteArray sig = f.name + '('; + QByteArray arguments; + + for (int j = 0; j < f.arguments.count(); ++j) { + const ArgumentDef &a = f.arguments.at(j); + if (j) { + sig += ","; + arguments += ","; + } + sig += a.normalizedType; + arguments += a.name; + } + sig += ')'; + + char flags = type; + if (f.access == FunctionDef::Private) + flags |= AccessPrivate; + else if (f.access == FunctionDef::Public) + flags |= AccessPublic; + else if (f.access == FunctionDef::Protected) + flags |= AccessProtected; + if (f.access == FunctionDef::Private) + flags |= AccessPrivate; + else if (f.access == FunctionDef::Public) + flags |= AccessPublic; + else if (f.access == FunctionDef::Protected) + flags |= AccessProtected; + if (f.isCompat) + flags |= MethodCompatibility; + if (f.wasCloned) + flags |= MethodCloned; + if (f.isScriptable) + flags |= MethodScriptable; + + meta_data << strreg(sig) + << strreg(arguments) + << strreg(f.normalizedType) + << strreg(f.tag) + << flags; + } +} + +void Generator::_generateEnums(int index) +{ + index += 4 * cdef->enumList.count(); + int i; + for (i = 0; i < cdef->enumList.count(); ++i) { + const EnumDef &e = cdef->enumList.at(i); + meta_data << strreg(e.name) << (cdef->enumDeclarations.value(e.name) ? 1 : 0) + << e.values.count() << index; + index += e.values.count() * 2; + } + + for (i = 0; i < cdef->enumList.count(); ++i) { + const EnumDef &e = cdef->enumList.at(i); + for (int j = 0; j < e.values.count(); ++j) { + const QByteArray &val = e.values.at(j); + meta_data << strreg(val) << 0; // we don't know the value itself + } + } +} + +void Generator::_generateProperties() +{ + // + // specify get function, for compatibiliy we accept functions + // returning pointers, or const char * for QByteArray. + // + for (int i = 0; i < cdef->propertyList.count(); ++i) { + PropertyDef &p = cdef->propertyList[i]; + if (p.read.isEmpty()) + continue; + for (int j = 0; j < cdef->publicList.count(); ++j) { + const FunctionDef &f = cdef->publicList.at(j); + if (f.name != p.read) + continue; + if (!f.isConst) // get functions must be const + continue; + if (f.arguments.size()) // and must not take any arguments + continue; + PropertyDef::Specification spec = PropertyDef::ValueSpec; + QByteArray tmp = f.normalizedType; + if (p.type == "QByteArray" && tmp == "const char *") + tmp = "QByteArray"; + if (tmp.left(6) == "const ") + tmp = tmp.mid(6); + if (p.type != tmp && tmp.endsWith('*')) { + tmp.chop(1); + spec = PropertyDef::PointerSpec; + } else if (f.type.name.endsWith('&')) { // raw type, not normalized type + spec = PropertyDef::ReferenceSpec; + } + if (p.type != tmp) + continue; + p.gspec = spec; + break; + } + } + + + // + // Create meta data + // + + for (int i = 0; i < cdef->propertyList.count(); ++i) { + const PropertyDef &p = cdef->propertyList.at(i); + uint flags = Invalid; + if (!isVariantType(p.type)) { + flags |= EnumOrFlag; + } else { + flags |= qvariant_nameToType(p.type) << 24; + } + if (!p.read.isEmpty()) + flags |= Readable; + if (!p.write.isEmpty()) { + flags |= Writable; + if (p.stdCppSet()) + flags |= StdCppSet; + } + if (!p.reset.isEmpty()) + flags |= Resettable; + +// if (p.override) +// flags |= Override; + + if (p.designable.isEmpty()) + flags |= ResolveDesignable; + else if (p.designable != "false") + flags |= Designable; + + if (p.scriptable.isEmpty()) + flags |= ResolveScriptable; + else if (p.scriptable != "false") + flags |= Scriptable; + + if (p.stored.isEmpty()) + flags |= ResolveStored; + else if (p.stored != "false") + flags |= Stored; + + if (p.editable.isEmpty()) + flags |= ResolveEditable; + else if (p.editable != "false") + flags |= Editable; + + if (p.user.isEmpty()) + flags |= ResolveUser; + else if (p.user != "false") + flags |= User; + + meta_data << strreg(p.name) << strreg(p.type) << flags; + } +} + +QT_END_NAMESPACE diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h new file mode 100644 index 0000000..d64eddb --- /dev/null +++ b/src/tools/moc/generator.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GENERATOR_H +#define GENERATOR_H + +#include "moc.h" + +QT_BEGIN_NAMESPACE + +class Generator +{ + FILE *out; + ClassDef *cdef; + QVector<uint> meta_data; +public: + Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile = 0); + void generateCode(); + QMetaObject *generateMetaObject(bool ignoreProperties); +private: + void generateClassInfos(); + void generateFunctions(QList<FunctionDef> &list, const char *functype, int type); + void generateEnums(int index); + void generateProperties(); + void generateMetacall(); + void generateStaticMetacall(const QByteArray &prefix); + void generateSignal(FunctionDef *def, int index); + + // used by binary QMetaObject generator + void _generateClassInfos(); + void _generateFunctions(QList<FunctionDef> &list, int type); + void _generateEnums(int index); + void _generateProperties(); + + int strreg(const char *); // registers a string and returns its id + QList<QByteArray> strings; + QByteArray purestSuperClass; + QList<QByteArray> metaTypes; +}; + +QT_END_NAMESPACE + +#endif // GENERATOR_H diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp new file mode 100644 index 0000000..2a4fbf9 --- /dev/null +++ b/src/tools/moc/keywords.cpp @@ -0,0 +1,979 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// auto generated +// DO NOT EDIT. + +static const short keyword_trans[][128] = { + {0,0,0,0,0,0,0,0,0,525,522,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 525,252,523,526,0,38,239,524,25,26,236,234,30,235,27,237, + 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, + 8,21,8,8,8,8,8,8,8,8,8,31,527,32,238,8, + 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}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,192,0,173,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,287, + 0,0,341,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,109,0,0,0,0,0,0,280,0,0,0,121,0,0,80, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,229,0,0,0,0,0,0,0,0,0,312, + 0,0,0,0,0,0,0,0,0,44,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,327,0,133,0, + 0,0,0,0,0,0,0,0,168,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,308,0,0,339, + 0,0,116,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,326,0,0,0,0,0,0,0,198,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,125,0,0,0,227,0,0,0,0,0,0,0,0,0,253, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,150,0,0,163,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 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,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, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,97,0,0,94,0,0,0,0,0,0,0, + 0,0,107,0,0,0,0,0,0,89,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,0, + 0,0,0,194,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,144,0,0,0,0,0,208, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,283,0,0,0,0,335,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,33,0,263,272,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,273,264,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,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, + 530,530,530,530,530,530,530,530,530,530,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,40,0,0,0,32,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,259,37,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,56,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,136,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,176,0,66,0,0,0,0,0,0, + 0,0,0,0,353,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,249,81,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,82,345,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,113,0,0,0,0,92,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,95,0,0,0,0,0,0, + 0,0,104,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,319,110,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,141,0,0,0,0,0,0, + 0,0,0,302,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,151,0,0,0,0,0,156, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 169,0,0,0,182,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,203,0,0,170, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,199,0,0,0, + 0,0,0,0,294,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,317,0,0,209,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,298,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,223,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,321,0,0,0,0,0,230,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,276,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,277,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,256,278,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,528, + 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}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,274,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,261,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,242,0,0,0,0,0,0,0,0,0,0,0,0,0,246, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,262,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,275,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,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, + 370,0,0,436,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,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,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,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,437,0,0,0,465,0,0,471,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,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,506,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,497,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,486, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} +}; + +static const struct +{ + Token token; + short next; + char defchar; + short defnext; + Token ident; +} keywords[] = { + {NOTOKEN, 0, 0, 0, NOTOKEN}, + {CHARACTER, 1, 0, 0, NOTOKEN}, + {CHARACTER, 2, 0, 0, NOTOKEN}, + {CHARACTER, 3, 0, 0, NOTOKEN}, + {CHARACTER, 4, 0, 0, NOTOKEN}, + {CHARACTER, 5, 0, 0, NOTOKEN}, + {CHARACTER, 6, 0, 0, NOTOKEN}, + {CHARACTER, 0, 111, 350, NOTOKEN}, + {CHARACTER, 0, 0, 0, NOTOKEN}, + {CHARACTER, 7, 0, 0, NOTOKEN}, + {CHARACTER, 0, 111, 295, NOTOKEN}, + {CHARACTER, 0, 117, 186, NOTOKEN}, + {CHARACTER, 8, 0, 0, NOTOKEN}, + {CHARACTER, 0, 112, 215, NOTOKEN}, + {CHARACTER, 9, 0, 0, NOTOKEN}, + {CHARACTER, 0, 101, 65, NOTOKEN}, + {CHARACTER, 10, 0, 0, NOTOKEN}, + {CHARACTER, 11, 0, 0, NOTOKEN}, + {CHARACTER, 12, 0, 0, NOTOKEN}, + {CHARACTER, 13, 0, 0, NOTOKEN}, + {CHARACTER, 14, 0, 0, NOTOKEN}, + {CHARACTER, 15, 0, 0, NOTOKEN}, + {DIGIT, 0, 0, 0, NOTOKEN}, + {LANGLE, 16, 0, 0, NOTOKEN}, + {RANGLE, 17, 0, 0, NOTOKEN}, + {LPAREN, 0, 0, 0, NOTOKEN}, + {RPAREN, 0, 0, 0, NOTOKEN}, + {DOT, 18, 0, 0, NOTOKEN}, + {INCOMPLETE, 0, 46, 29, NOTOKEN}, + {ELIPSIS, 0, 0, 0, NOTOKEN}, + {COMMA, 0, 0, 0, NOTOKEN}, + {LBRACK, 0, 0, 0, NOTOKEN}, + {RBRACK, 0, 0, 0, NOTOKEN}, + {LBRACK, 0, 58, 35, NOTOKEN}, + {COLON, 19, 0, 0, NOTOKEN}, + {LANGLE_SCOPE, 0, 0, 0, NOTOKEN}, + {LBRACE, 0, 0, 0, NOTOKEN}, + {RBRACE, 0, 0, 0, NOTOKEN}, + {PERCENT, 20, 0, 0, NOTOKEN}, + {EQ, 0, 61, 267, NOTOKEN}, + {SCOPE, 0, 0, 0, NOTOKEN}, + {SEMIC, 0, 0, 0, NOTOKEN}, + {DOTSTAR, 0, 0, 0, NOTOKEN}, + {QUESTION, 0, 0, 0, NOTOKEN}, + {CHARACTER, 0, 110, 45, CHARACTER}, + {CHARACTER, 0, 97, 46, CHARACTER}, + {CHARACTER, 0, 109, 47, CHARACTER}, + {CHARACTER, 0, 105, 48, CHARACTER}, + {CHARACTER, 0, 99, 49, CHARACTER}, + {CHARACTER, 0, 95, 50, CHARACTER}, + {CHARACTER, 0, 99, 51, CHARACTER}, + {CHARACTER, 0, 97, 52, CHARACTER}, + {CHARACTER, 0, 115, 53, CHARACTER}, + {CHARACTER, 0, 116, 54, CHARACTER}, + {DYNAMIC_CAST, 0, 0, 0, CHARACTER}, + {CHARACTER, 21, 0, 0, CHARACTER}, + {CHARACTER, 0, 116, 57, CHARACTER}, + {CHARACTER, 0, 105, 58, CHARACTER}, + {CHARACTER, 0, 99, 59, CHARACTER}, + {STATIC, 0, 95, 60, CHARACTER}, + {CHARACTER, 0, 99, 61, CHARACTER}, + {CHARACTER, 0, 97, 62, CHARACTER}, + {CHARACTER, 0, 115, 63, CHARACTER}, + {CHARACTER, 0, 116, 64, CHARACTER}, + {STATIC_CAST, 0, 0, 0, CHARACTER}, + {CHARACTER, 22, 0, 0, CHARACTER}, + {CHARACTER, 0, 110, 67, CHARACTER}, + {CHARACTER, 0, 116, 68, CHARACTER}, + {CHARACTER, 0, 101, 69, CHARACTER}, + {CHARACTER, 0, 114, 70, CHARACTER}, + {CHARACTER, 0, 112, 71, CHARACTER}, + {CHARACTER, 0, 114, 72, CHARACTER}, + {CHARACTER, 0, 101, 73, CHARACTER}, + {CHARACTER, 0, 116, 74, CHARACTER}, + {CHARACTER, 0, 95, 75, CHARACTER}, + {CHARACTER, 0, 99, 76, CHARACTER}, + {CHARACTER, 0, 97, 77, CHARACTER}, + {CHARACTER, 0, 115, 78, CHARACTER}, + {CHARACTER, 0, 116, 79, CHARACTER}, + {REINTERPRET_CAST, 0, 0, 0, CHARACTER}, + {CHARACTER, 23, 0, 0, CHARACTER}, + {CHARACTER, 24, 0, 0, CHARACTER}, + {CHARACTER, 0, 116, 83, CHARACTER}, + {CONST, 0, 95, 84, CHARACTER}, + {CHARACTER, 0, 99, 85, CHARACTER}, + {CHARACTER, 0, 97, 86, CHARACTER}, + {CHARACTER, 0, 115, 87, CHARACTER}, + {CHARACTER, 0, 116, 88, CHARACTER}, + {CONST_CAST, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 112, 90, CHARACTER}, + {CHARACTER, 0, 101, 91, CHARACTER}, + {CHARACTER, 25, 0, 0, CHARACTER}, + {CHARACTER, 0, 100, 93, CHARACTER}, + {TYPEID, 0, 0, 0, CHARACTER}, + {CHARACTER, 26, 0, 0, CHARACTER}, + {CHARACTER, 0, 115, 96, CHARACTER}, + {THIS, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 109, 98, CHARACTER}, + {CHARACTER, 0, 112, 99, CHARACTER}, + {CHARACTER, 0, 108, 100, CHARACTER}, + {CHARACTER, 0, 97, 101, CHARACTER}, + {CHARACTER, 0, 116, 102, CHARACTER}, + {CHARACTER, 0, 101, 103, CHARACTER}, + {TEMPLATE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 111, 105, CHARACTER}, + {CHARACTER, 0, 119, 106, CHARACTER}, + {THROW, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 121, 108, CHARACTER}, + {TRY, 0, 0, 0, CHARACTER}, + {CHARACTER, 27, 0, 0, CHARACTER}, + {CHARACTER, 0, 99, 111, CHARACTER}, + {CHARACTER, 0, 104, 112, CHARACTER}, + {CATCH, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 101, 114, CHARACTER}, + {CHARACTER, 0, 102, 115, CHARACTER}, + {TYPEDEF, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 117, CHARACTER}, + {CHARACTER, 0, 101, 118, CHARACTER}, + {CHARACTER, 0, 110, 119, CHARACTER}, + {CHARACTER, 0, 100, 120, CHARACTER}, + {FRIEND, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 97, 122, CHARACTER}, + {CHARACTER, 0, 115, 123, CHARACTER}, + {CHARACTER, 0, 115, 124, CHARACTER}, + {CLASS, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 109, 126, CHARACTER}, + {CHARACTER, 0, 101, 127, CHARACTER}, + {CHARACTER, 0, 115, 128, CHARACTER}, + {CHARACTER, 0, 112, 129, CHARACTER}, + {CHARACTER, 0, 97, 130, CHARACTER}, + {CHARACTER, 0, 99, 131, CHARACTER}, + {CHARACTER, 0, 101, 132, CHARACTER}, + {NAMESPACE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 117, 134, CHARACTER}, + {CHARACTER, 0, 109, 135, CHARACTER}, + {ENUM, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 117, 137, CHARACTER}, + {CHARACTER, 0, 99, 138, CHARACTER}, + {CHARACTER, 0, 116, 139, CHARACTER}, + {STRUCT, 0, 0, 0, CHARACTER}, + {CHARACTER, 28, 0, 0, CHARACTER}, + {CHARACTER, 0, 111, 142, CHARACTER}, + {CHARACTER, 0, 110, 143, CHARACTER}, + {UNION, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 114, 145, CHARACTER}, + {CHARACTER, 0, 116, 146, CHARACTER}, + {CHARACTER, 0, 117, 147, CHARACTER}, + {CHARACTER, 0, 97, 148, CHARACTER}, + {CHARACTER, 0, 108, 149, CHARACTER}, + {VIRTUAL, 0, 0, 0, CHARACTER}, + {CHARACTER, 29, 0, 0, CHARACTER}, + {CHARACTER, 0, 118, 152, CHARACTER}, + {CHARACTER, 0, 97, 153, CHARACTER}, + {CHARACTER, 0, 116, 154, CHARACTER}, + {CHARACTER, 0, 101, 155, CHARACTER}, + {PRIVATE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 116, 157, CHARACTER}, + {CHARACTER, 0, 101, 158, CHARACTER}, + {CHARACTER, 0, 99, 159, CHARACTER}, + {CHARACTER, 0, 116, 160, CHARACTER}, + {CHARACTER, 0, 101, 161, CHARACTER}, + {CHARACTER, 0, 100, 162, CHARACTER}, + {PROTECTED, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 98, 164, CHARACTER}, + {CHARACTER, 0, 108, 165, CHARACTER}, + {CHARACTER, 0, 105, 166, CHARACTER}, + {CHARACTER, 0, 99, 167, CHARACTER}, + {PUBLIC, 0, 0, 0, CHARACTER}, + {CHARACTER, 30, 0, 0, CHARACTER}, + {CHARACTER, 31, 0, 0, CHARACTER}, + {CHARACTER, 0, 114, 171, CHARACTER}, + {CHARACTER, 0, 116, 172, CHARACTER}, + {EXPORT, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 116, 174, CHARACTER}, + {CHARACTER, 0, 111, 175, CHARACTER}, + {AUTO, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 177, CHARACTER}, + {CHARACTER, 0, 115, 178, CHARACTER}, + {CHARACTER, 0, 116, 179, CHARACTER}, + {CHARACTER, 0, 101, 180, CHARACTER}, + {CHARACTER, 0, 114, 181, CHARACTER}, + {REGISTER, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 101, 183, CHARACTER}, + {CHARACTER, 0, 114, 184, CHARACTER}, + {CHARACTER, 0, 110, 185, CHARACTER}, + {EXTERN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 116, 187, CHARACTER}, + {CHARACTER, 0, 97, 188, CHARACTER}, + {CHARACTER, 0, 98, 189, CHARACTER}, + {CHARACTER, 0, 108, 190, CHARACTER}, + {CHARACTER, 0, 101, 191, CHARACTER}, + {MUTABLE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 109, 193, CHARACTER}, + {ASM, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 195, CHARACTER}, + {CHARACTER, 0, 110, 196, CHARACTER}, + {CHARACTER, 0, 103, 197, CHARACTER}, + {USING, 0, 0, 0, CHARACTER}, + {CHARACTER, 32, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 200, CHARACTER}, + {CHARACTER, 0, 110, 201, CHARACTER}, + {CHARACTER, 0, 101, 202, CHARACTER}, + {INLINE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 204, CHARACTER}, + {CHARACTER, 0, 99, 205, CHARACTER}, + {CHARACTER, 0, 105, 206, CHARACTER}, + {CHARACTER, 0, 116, 207, CHARACTER}, + {EXPLICIT, 0, 0, 0, CHARACTER}, + {CHARACTER, 33, 0, 0, CHARACTER}, + {CHARACTER, 0, 97, 210, CHARACTER}, + {CHARACTER, 0, 116, 211, CHARACTER}, + {CHARACTER, 0, 105, 212, CHARACTER}, + {CHARACTER, 0, 108, 213, CHARACTER}, + {CHARACTER, 0, 101, 214, CHARACTER}, + {VOLATILE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 101, 216, CHARACTER}, + {CHARACTER, 0, 114, 217, CHARACTER}, + {CHARACTER, 0, 97, 218, CHARACTER}, + {CHARACTER, 0, 116, 219, CHARACTER}, + {CHARACTER, 0, 111, 220, CHARACTER}, + {CHARACTER, 0, 114, 221, CHARACTER}, + {OPERATOR, 0, 0, 0, CHARACTER}, + {CHARACTER, 34, 0, 0, CHARACTER}, + {CHARACTER, 0, 101, 224, CHARACTER}, + {CHARACTER, 0, 111, 225, CHARACTER}, + {CHARACTER, 0, 102, 226, CHARACTER}, + {SIZEOF, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 119, 228, CHARACTER}, + {NEW, 0, 0, 0, CHARACTER}, + {CHARACTER, 35, 0, 0, CHARACTER}, + {CHARACTER, 0, 101, 231, CHARACTER}, + {CHARACTER, 0, 116, 232, CHARACTER}, + {CHARACTER, 0, 101, 233, CHARACTER}, + {DELETE, 0, 0, 0, CHARACTER}, + {PLUS, 36, 0, 0, NOTOKEN}, + {MINUS, 37, 0, 0, NOTOKEN}, + {STAR, 0, 61, 257, NOTOKEN}, + {SLASH, 38, 0, 0, NOTOKEN}, + {HAT, 0, 61, 260, NOTOKEN}, + {AND, 39, 0, 0, NOTOKEN}, + {CHARACTER, 0, 116, 241, CHARACTER}, + {CHARACTER, 40, 0, 0, CHARACTER}, + {CHARACTER, 0, 110, 243, CHARACTER}, + {CHARACTER, 0, 100, 244, CHARACTER}, + {AND, 0, 0, 0, CHARACTER}, + {OR, 41, 0, 0, NOTOKEN}, + {CHARACTER, 0, 114, 247, CHARACTER}, + {OR, 0, 0, 0, CHARACTER}, + {TILDE, 0, 0, 0, NOTOKEN}, + {CHARACTER, 0, 112, 250, CHARACTER}, + {CHARACTER, 0, 108, 251, CHARACTER}, + {TILDE, 0, 0, 0, CHARACTER}, + {NOT, 0, 61, 268, NOTOKEN}, + {CHARACTER, 0, 116, 254, CHARACTER}, + {NOT, 0, 95, 269, CHARACTER}, + {PLUS_EQ, 0, 0, 0, NOTOKEN}, + {MINUS_EQ, 0, 0, 0, NOTOKEN}, + {STAR_EQ, 0, 0, 0, NOTOKEN}, + {SLASH_EQ, 0, 0, 0, NOTOKEN}, + {PERCENT_EQ, 0, 0, 0, NOTOKEN}, + {HAT_EQ, 0, 0, 0, NOTOKEN}, + {AND_EQ, 0, 0, 0, NOTOKEN}, + {OR_EQ, 0, 0, 0, NOTOKEN}, + {LTLT, 0, 61, 266, NOTOKEN}, + {GTGT, 0, 61, 265, NOTOKEN}, + {GTGT_EQ, 0, 0, 0, NOTOKEN}, + {LTLT_EQ, 0, 0, 0, NOTOKEN}, + {EQEQ, 0, 0, 0, NOTOKEN}, + {NE, 0, 0, 0, NOTOKEN}, + {CHARACTER, 0, 101, 270, CHARACTER}, + {CHARACTER, 0, 113, 271, CHARACTER}, + {NE, 0, 0, 0, CHARACTER}, + {LE, 0, 0, 0, NOTOKEN}, + {GE, 0, 0, 0, NOTOKEN}, + {ANDAND, 0, 0, 0, NOTOKEN}, + {OROR, 0, 0, 0, NOTOKEN}, + {INCR, 0, 0, 0, NOTOKEN}, + {DECR, 0, 0, 0, NOTOKEN}, + {ARROW, 0, 42, 279, NOTOKEN}, + {ARROW_STAR, 0, 0, 0, NOTOKEN}, + {CHARACTER, 0, 97, 281, CHARACTER}, + {CHARACTER, 0, 114, 282, CHARACTER}, + {CHAR, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 104, 284, CHARACTER}, + {CHARACTER, 0, 97, 285, CHARACTER}, + {CHARACTER, 0, 114, 286, CHARACTER}, + {WCHAR, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 111, 288, CHARACTER}, + {CHARACTER, 0, 108, 289, CHARACTER}, + {BOOL, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 111, 291, CHARACTER}, + {CHARACTER, 0, 114, 292, CHARACTER}, + {CHARACTER, 0, 116, 293, CHARACTER}, + {SHORT, 0, 0, 0, CHARACTER}, + {INT, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 110, 296, CHARACTER}, + {CHARACTER, 0, 103, 297, CHARACTER}, + {LONG, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 110, 299, CHARACTER}, + {CHARACTER, 42, 0, 0, CHARACTER}, + {CHARACTER, 0, 100, 301, CHARACTER}, + {SIGNED, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 303, CHARACTER}, + {CHARACTER, 0, 103, 304, CHARACTER}, + {CHARACTER, 0, 110, 305, CHARACTER}, + {CHARACTER, 0, 101, 306, CHARACTER}, + {CHARACTER, 0, 100, 307, CHARACTER}, + {UNSIGNED, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 111, 309, CHARACTER}, + {CHARACTER, 0, 97, 310, CHARACTER}, + {CHARACTER, 0, 116, 311, CHARACTER}, + {FLOAT, 0, 0, 0, CHARACTER}, + {DO, 0, 117, 313, CHARACTER}, + {CHARACTER, 0, 98, 314, CHARACTER}, + {CHARACTER, 0, 108, 315, CHARACTER}, + {CHARACTER, 0, 101, 316, CHARACTER}, + {DOUBLE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 100, 318, CHARACTER}, + {VOID, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 101, 320, CHARACTER}, + {CASE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 97, 322, CHARACTER}, + {CHARACTER, 0, 117, 323, CHARACTER}, + {CHARACTER, 0, 108, 324, CHARACTER}, + {CHARACTER, 0, 116, 325, CHARACTER}, + {DEFAULT, 0, 0, 0, CHARACTER}, + {IF, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 115, 328, CHARACTER}, + {CHARACTER, 0, 101, 329, CHARACTER}, + {ELSE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 331, CHARACTER}, + {CHARACTER, 0, 116, 332, CHARACTER}, + {CHARACTER, 0, 99, 333, CHARACTER}, + {CHARACTER, 0, 104, 334, CHARACTER}, + {SWITCH, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 336, CHARACTER}, + {CHARACTER, 0, 108, 337, CHARACTER}, + {CHARACTER, 0, 101, 338, CHARACTER}, + {WHILE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 114, 340, CHARACTER}, + {FOR, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 101, 342, CHARACTER}, + {CHARACTER, 0, 97, 343, CHARACTER}, + {CHARACTER, 0, 107, 344, CHARACTER}, + {BREAK, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 105, 346, CHARACTER}, + {CHARACTER, 0, 110, 347, CHARACTER}, + {CHARACTER, 0, 117, 348, CHARACTER}, + {CHARACTER, 0, 101, 349, CHARACTER}, + {CONTINUE, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 116, 351, CHARACTER}, + {CHARACTER, 0, 111, 352, CHARACTER}, + {GOTO, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 117, 354, CHARACTER}, + {CHARACTER, 0, 114, 355, CHARACTER}, + {CHARACTER, 0, 110, 356, CHARACTER}, + {RETURN, 0, 0, 0, CHARACTER}, + {CHARACTER, 43, 0, 0, CHARACTER}, + {CHARACTER, 0, 66, 359, CHARACTER}, + {CHARACTER, 0, 74, 360, CHARACTER}, + {CHARACTER, 0, 69, 361, CHARACTER}, + {CHARACTER, 0, 67, 362, CHARACTER}, + {CHARACTER, 0, 84, 363, CHARACTER}, + {Q_OBJECT_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 65, 365, CHARACTER}, + {CHARACTER, 0, 68, 366, CHARACTER}, + {CHARACTER, 0, 71, 367, CHARACTER}, + {CHARACTER, 0, 69, 368, CHARACTER}, + {CHARACTER, 0, 84, 369, CHARACTER}, + {Q_GADGET_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 82, 371, CHARACTER}, + {CHARACTER, 44, 0, 0, CHARACTER}, + {CHARACTER, 0, 80, 373, CHARACTER}, + {CHARACTER, 0, 69, 374, CHARACTER}, + {CHARACTER, 0, 82, 375, CHARACTER}, + {CHARACTER, 0, 84, 376, CHARACTER}, + {CHARACTER, 0, 89, 377, CHARACTER}, + {Q_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 78, 379, CHARACTER}, + {CHARACTER, 0, 85, 380, CHARACTER}, + {CHARACTER, 0, 77, 381, CHARACTER}, + {CHARACTER, 0, 83, 382, CHARACTER}, + {Q_ENUMS_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 76, 384, CHARACTER}, + {CHARACTER, 0, 65, 385, CHARACTER}, + {CHARACTER, 0, 71, 386, CHARACTER}, + {CHARACTER, 0, 83, 387, CHARACTER}, + {Q_FLAGS_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 69, 389, CHARACTER}, + {CHARACTER, 0, 67, 390, CHARACTER}, + {CHARACTER, 0, 76, 391, CHARACTER}, + {CHARACTER, 0, 65, 392, CHARACTER}, + {CHARACTER, 0, 82, 393, CHARACTER}, + {CHARACTER, 0, 69, 394, CHARACTER}, + {CHARACTER, 0, 95, 395, 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, 0, 84, 438, CHARACTER}, + {CHARACTER, 0, 83, 387, CHARACTER}, + {CHARACTER, 0, 76, 440, CHARACTER}, + {CHARACTER, 0, 65, 441, CHARACTER}, + {CHARACTER, 0, 83, 442, CHARACTER}, + {CHARACTER, 0, 83, 443, CHARACTER}, + {CHARACTER, 0, 73, 444, CHARACTER}, + {CHARACTER, 0, 78, 445, CHARACTER}, + {CHARACTER, 0, 70, 446, CHARACTER}, + {CHARACTER, 0, 79, 447, CHARACTER}, + {Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 78, 449, CHARACTER}, + {CHARACTER, 47, 0, 0, CHARACTER}, + {CHARACTER, 0, 69, 451, CHARACTER}, + {CHARACTER, 0, 82, 452, CHARACTER}, + {CHARACTER, 0, 70, 453, CHARACTER}, + {CHARACTER, 0, 65, 454, CHARACTER}, + {CHARACTER, 0, 67, 455, CHARACTER}, + {CHARACTER, 0, 69, 456, CHARACTER}, + {CHARACTER, 0, 83, 457, CHARACTER}, + {Q_INTERFACES_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 108, 459, CHARACTER}, + {CHARACTER, 0, 115, 460, CHARACTER}, + {SIGNALS, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 111, 462, CHARACTER}, + {CHARACTER, 0, 116, 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, 0, 83, 481, CHARACTER}, + {CHARACTER, 0, 76, 482, CHARACTER}, + {CHARACTER, 0, 79, 483, CHARACTER}, + {CHARACTER, 0, 84, 484, CHARACTER}, + {Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 48, 0, 0, CHARACTER}, + {CHARACTER, 0, 77, 487, CHARACTER}, + {CHARACTER, 0, 79, 488, CHARACTER}, + {CHARACTER, 0, 67, 489, CHARACTER}, + {CHARACTER, 0, 95, 490, CHARACTER}, + {CHARACTER, 0, 67, 491, CHARACTER}, + {CHARACTER, 0, 79, 492, CHARACTER}, + {CHARACTER, 0, 77, 493, CHARACTER}, + {CHARACTER, 0, 80, 494, CHARACTER}, + {CHARACTER, 0, 65, 495, CHARACTER}, + {CHARACTER, 0, 84, 496, CHARACTER}, + {Q_MOC_COMPAT_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 95, 498, CHARACTER}, + {CHARACTER, 0, 83, 499, CHARACTER}, + {CHARACTER, 0, 85, 500, CHARACTER}, + {CHARACTER, 0, 80, 501, CHARACTER}, + {CHARACTER, 0, 80, 502, CHARACTER}, + {CHARACTER, 0, 79, 503, CHARACTER}, + {CHARACTER, 0, 82, 504, CHARACTER}, + {CHARACTER, 0, 84, 505, CHARACTER}, + {Q_QT3_SUPPORT_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 79, 507, CHARACTER}, + {CHARACTER, 0, 75, 508, CHARACTER}, + {CHARACTER, 0, 65, 509, CHARACTER}, + {CHARACTER, 0, 66, 510, CHARACTER}, + {CHARACTER, 0, 76, 511, CHARACTER}, + {CHARACTER, 0, 69, 512, CHARACTER}, + {Q_INVOKABLE_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 82, 514, CHARACTER}, + {CHARACTER, 0, 73, 515, CHARACTER}, + {CHARACTER, 0, 80, 516, CHARACTER}, + {CHARACTER, 0, 84, 517, CHARACTER}, + {CHARACTER, 0, 65, 518, CHARACTER}, + {CHARACTER, 0, 66, 519, CHARACTER}, + {CHARACTER, 0, 76, 520, CHARACTER}, + {CHARACTER, 0, 69, 521, CHARACTER}, + {Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER}, + {NEWLINE, 0, 0, 0, NOTOKEN}, + {QUOTE, 0, 0, 0, NOTOKEN}, + {SINGLEQUOTE, 0, 0, 0, NOTOKEN}, + {WHITESPACE, 0, 0, 0, NOTOKEN}, + {HASH, 0, 0, 0, HASH}, + {BACKSLASH, 0, 0, 0, NOTOKEN}, + {CPP_COMMENT, 0, 0, 0, NOTOKEN}, + {C_COMMENT, 0, 0, 0, NOTOKEN}, + {FLOATING_LITERAL, 0, 0, 0, NOTOKEN} +}; diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp new file mode 100644 index 0000000..4aa362d --- /dev/null +++ b/src/tools/moc/main.cpp @@ -0,0 +1,459 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "preprocessor.h" +#include "moc.h" +#include "outputrevision.h" +#include "../../corelib/global/qconfig.cpp" +#include <QFile> +#include <QFileInfo> +#include <QDir> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +QT_BEGIN_NAMESPACE + +/* + This function looks at two file names and returns the name of the + infile with a path relative to outfile. + + Examples: + + /tmp/abc, /tmp/bcd -> abc + xyz/a/bc, xyz/b/ac -> ../a/bc + /tmp/abc, xyz/klm -> /tmp/abc + */ + +static QByteArray combinePath(const char *infile, const char *outfile) +{ + QFileInfo inFileInfo(QDir::current(), QFile::decodeName(infile)); + QFileInfo outFileInfo(QDir::current(), QFile::decodeName(outfile)); + int numCommonComponents = 0; + + QStringList inSplitted = inFileInfo.dir().canonicalPath().split(QLatin1Char('/')); + QStringList outSplitted = outFileInfo.dir().canonicalPath().split(QLatin1Char('/')); + + while (!inSplitted.isEmpty() && !outSplitted.isEmpty() && + inSplitted.first() == outSplitted.first()) { + inSplitted.removeFirst(); + outSplitted.removeFirst(); + numCommonComponents++; + } + + if (numCommonComponents < 2) + /* + The paths don't have the same drive, or they don't have the + same root directory. Use an absolute path. + */ + return QFile::encodeName(inFileInfo.absoluteFilePath()); + /* + The paths have something in common. Use a path relative to + the output file. + */ + while (!outSplitted.isEmpty()) { + outSplitted.removeFirst(); + inSplitted.prepend(QLatin1String("..")); + } + inSplitted.append(inFileInfo.fileName()); + return QFile::encodeName(inSplitted.join(QLatin1String("/"))); +} + + +void error(const char *msg = "Invalid argument") +{ + if (msg) + fprintf(stderr, "moc: %s\n", msg); + fprintf(stderr, "Usage: moc [options] <header-file>\n" + " -o<file> write output to file rather than stdout\n" + " -I<dir> add dir to the include path for header files\n" + " -E preprocess only; do not generate meta object code\n" + " -D<macro>[=<def>] define macro, with optional definition\n" + " -U<macro> undefine macro\n" + " -i do not generate an #include statement\n" + " -p<path> path prefix for included file\n" + " -f[<file>] force #include, optional file name\n" + " -nw do not display warnings\n" + " @<file> read additional options from file\n" + " -v display version of moc\n"); + exit(1); +} + + +static inline bool hasNext(const Symbols &symbols, int i) +{ return (i < symbols.size()); } + +static inline const Symbol &next(const Symbols &symbols, int &i) +{ return symbols.at(i++); } + + +QByteArray composePreprocessorOutput(const Symbols &symbols) { + QByteArray output; + int lineNum = 1; + Token last = PP_NOTOKEN; + Token secondlast = last; + int i = 0; + while (hasNext(symbols, i)) { + Symbol sym = next(symbols, i); + switch (sym.token) { + case PP_NEWLINE: + case PP_WHITESPACE: + if (last != PP_WHITESPACE) { + secondlast = last; + last = PP_WHITESPACE; + output += ' '; + } + continue; + case PP_STRING_LITERAL: + if (last == PP_STRING_LITERAL) + output.chop(1); + else if (secondlast == PP_STRING_LITERAL && last == PP_WHITESPACE) + output.chop(2); + else + break; + output += sym.lexem().mid(1); + secondlast = last; + last = PP_STRING_LITERAL; + continue; + case MOC_INCLUDE_BEGIN: + lineNum = 0; + continue; + case MOC_INCLUDE_END: + lineNum = sym.lineNum; + continue; + default: + break; + } + secondlast = last; + last = sym.token; + + const int padding = sym.lineNum - lineNum; + if (padding > 0) { + output.resize(output.size() + padding); + qMemSet(output.data() + output.size() - padding, '\n', padding); + lineNum = sym.lineNum; + } + + output += sym.lexem(); + } + + return output; +} + + +int runMoc(int _argc, char **_argv) +{ + bool autoInclude = true; + Preprocessor pp; + Moc moc; + pp.macros["Q_MOC_RUN"]; + pp.macros["__cplusplus"]; + QByteArray filename; + QByteArray output; + FILE *in = 0; + FILE *out = 0; + bool ignoreConflictingOptions = false; + + QVector<QByteArray> argv; + argv.resize(_argc - 1); + for (int n = 1; n < _argc; ++n) + argv[n - 1] = _argv[n]; + int argc = argv.count(); + + for (int n = 0; n < argv.count(); ++n) { + if (argv.at(n).startsWith('@')) { + QByteArray optionsFile = argv.at(n); + optionsFile.remove(0, 1); + if (optionsFile.isEmpty()) + error("The @ option requires an input file"); + QFile f(QString::fromLatin1(optionsFile.constData())); + if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) + error("Cannot open options file specified with @"); + argv.remove(n); + while (!f.atEnd()) { + QByteArray line = f.readLine().trimmed(); + if (!line.isEmpty()) + argv.insert(n++, line); + } + } + } + + // report Qt usage for commercial customers with a "metered license" (currently experimental) +#if QT_EDITION != QT_EDITION_OPENSOURCE +#ifdef QT_CONFIGURE_BINARIES_PATH + const char *binariesPath = QT_CONFIGURE_BINARIES_PATH; + QString reporterPath = QString::fromLocal8Bit(binariesPath) + QDir::separator() + + QLatin1String("qtusagereporter"); +#if defined(Q_OS_WIN) + reporterPath += QLatin1String(".exe"); +#endif + if (QFile::exists(reporterPath)) + system(qPrintable(reporterPath + QLatin1String(" moc"))); +#endif +#endif + + argc = argv.count(); + + for (int n = 0; n < argc; ++n) { + QByteArray arg(argv[n]); + if (arg[0] != '-') { + if (filename.isEmpty()) { + filename = arg; + continue; + } + error("Too many input files specified"); + } + QByteArray opt = arg.mid(1); + bool more = (opt.size() > 1); + switch (opt[0]) { + case 'o': // output redirection + if (!more) { + if (!(n < argc-1)) + error("Missing output file name"); + output = argv[++n]; + } else + output = opt.mid(1); + break; + case 'E': // only preprocessor + pp.preprocessOnly = true; + break; + case 'i': // no #include statement + if (more) + error(); + moc.noInclude = true; + autoInclude = false; + break; + case 'f': // produce #include statement + if (ignoreConflictingOptions) + break; + moc.noInclude = false; + autoInclude = false; + if (opt[1]) // -fsomething.h + moc.includeFiles.append(opt.mid(1)); + break; + case 'p': // include file path + if (ignoreConflictingOptions) + break; + if (!more) { + if (!(n < argc-1)) + error("Missing path name for the -p option."); + moc.includePath = argv[++n]; + } else { + moc.includePath = opt.mid(1); + } + break; + case 'I': // produce #include statement + if (!more) { + if (!(n < argc-1)) + error("Missing path name for the -I option."); + pp.includes += Preprocessor::IncludePath(argv[++n]); + } else { + pp.includes += Preprocessor::IncludePath(opt.mid(1)); + } + break; + case 'F': // minimalistic framework support for the mac + if (!more) { + if (!(n < argc-1)) + error("Missing path name for the -F option."); + Preprocessor::IncludePath p(argv[++n]); + p.isFrameworkPath = true; + pp.includes += p; + } else { + Preprocessor::IncludePath p(opt.mid(1)); + p.isFrameworkPath = true; + pp.includes += p; + } + break; + case 'D': // define macro + { + QByteArray name; + QByteArray value("1"); + if (!more) { + if (n < argc-1) + name = argv[++n]; + } else + name = opt.mid(1); + int eq = name.indexOf('='); + if (eq >= 0) { + value = name.mid(eq + 1); + name = name.left(eq); + } + if (name.isEmpty()) + error("Missing macro name"); + Macro macro; + macro.symbols += Symbol(0, PP_IDENTIFIER, value); + pp.macros.insert(name, macro); + + } + break; + case 'U': + { + QByteArray macro; + if (!more) { + if (n < argc-1) + macro = argv[++n]; + } else + macro = opt.mid(1); + if (macro.isEmpty()) + error("Missing macro name"); + pp.macros.remove(macro); + + } + break; + case 'v': // version number + if (more && opt != "version") + error(); + fprintf(stderr, "Qt Meta Object Compiler version %d (Qt %s)\n", + mocOutputRevision, QT_VERSION_STR); + return 1; + case 'n': // don't display warnings + if (ignoreConflictingOptions) + break; + if (opt != "nw") + error(); + moc.displayWarnings = false; + break; + case 'h': // help + if (more && opt != "help") + error(); + else + error(0); // 0 means usage only + break; + case '-': + if (more && arg == "--ignore-option-clashes") { + // -- ignore all following moc specific options that conflict + // with for example gcc, like -pthread conflicting with moc's + // -p option. + ignoreConflictingOptions = true; + break; + } + // fall through + default: + error(); + } + } + + + if (autoInclude) { + int ppos = filename.lastIndexOf('.'); + moc.noInclude = (ppos >= 0 + && tolower(filename[ppos + 1]) != 'h' + && tolower(filename[ppos + 1]) != QDir::separator().toLatin1() + ); + } + if (moc.includeFiles.isEmpty()) { + if (moc.includePath.isEmpty()) { + if (filename.size()) { + if (output.size()) + moc.includeFiles.append(combinePath(filename, output)); + else + moc.includeFiles.append(filename); + } + } else { + moc.includeFiles.append(combinePath(filename, filename)); + } + } + + if (filename.isEmpty()) { + filename = "standard input"; + in = stdin; + } else { +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (fopen_s(&in, filename.data(), "rb")) { +#else + in = fopen(filename.data(), "rb"); + if (!in) { +#endif + fprintf(stderr, "moc: %s: No such file\n", (const char*)filename); + return 1; + } + moc.filename = filename; + } + + moc.currentFilenames.push(filename); + + // 1. preprocess + moc.symbols = pp.preprocessed(moc.filename, in); + fclose(in); + + if (!pp.preprocessOnly) { + // 2. parse + moc.parse(); + } + + // 3. and output meta object code + + if (output.size()) { // output file specified +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (fopen_s(&out, output.data(), "w")) +#else + out = fopen(output.data(), "w"); // create output file + if (!out) +#endif + { + fprintf(stderr, "moc: Cannot create %s\n", (const char*)output); + return 1; + } + } else { // use stdout + out = stdout; + } + + if (pp.preprocessOnly) { + fprintf(out, "%s\n", composePreprocessorOutput(moc.symbols).constData()); + } else { + if (moc.classList.isEmpty()) + moc.warning("No relevant classes found. No output generated."); + else + moc.generate(out); + } + + if (output.size()) + fclose(out); + + return 0; +} + +QT_END_NAMESPACE + +int main(int _argc, char **_argv) +{ + return QT_PREPEND_NAMESPACE(runMoc)(_argc, _argv); +} diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp new file mode 100644 index 0000000..a6a0ba1 --- /dev/null +++ b/src/tools/moc/moc.cpp @@ -0,0 +1,1230 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "moc.h" +#include "generator.h" +#include "qdatetime.h" +#include "utils.h" +#include "outputrevision.h" + +// for normalizeTypeInternal +#include <private/qmetaobject_p.h> + +QT_BEGIN_NAMESPACE + +// only moc needs this function +static QByteArray normalizeType(const char *s, bool fixScope = false) +{ + int len = qstrlen(s); + char stackbuf[64]; + char *buf = (len >= 64 ? new char[len + 1] : stackbuf); + char *d = buf; + char last = 0; + while(*s && is_space(*s)) + s++; + while (*s) { + while (*s && !is_space(*s)) + last = *d++ = *s++; + while (*s && is_space(*s)) + s++; + if (*s && ((is_ident_char(*s) && is_ident_char(last)) + || ((*s == ':') && (last == '<')))) { + last = *d++ = ' '; + } + } + *d = '\0'; + QByteArray result; + if (strncmp("void", buf, d - buf) != 0) + result = normalizeTypeInternal(buf, d, fixScope); + if (buf != stackbuf) + delete [] buf; + return result; +} + +bool Moc::parseClassHead(ClassDef *def) +{ + // figure out whether this is a class declaration, or only a + // forward or variable declaration. + int i = 0; + Token token; + do { + token = lookup(i++); + if (token == COLON || token == LBRACE) + break; + if (token == SEMIC || token == RANGLE) + return false; + } while (token); + + if (!test(IDENTIFIER)) // typedef struct { ... } + return false; + QByteArray name = lexem(); + + // support "class IDENT name" and "class IDENT(IDENT) name" + if (test(LPAREN)) { + until(RPAREN); + if (!test(IDENTIFIER)) + return false; + name = lexem(); + } else if (test(IDENTIFIER)) { + name = lexem(); + } + + def->qualified += name; + while (test(SCOPE)) { + def->qualified += lexem(); + if (test(IDENTIFIER)) { + name = lexem(); + def->qualified += name; + } + } + def->classname = name; + if (test(COLON)) { + do { + test(VIRTUAL); + FunctionDef::Access access = FunctionDef::Public; + if (test(PRIVATE)) + access = FunctionDef::Private; + else if (test(PROTECTED)) + access = FunctionDef::Protected; + else + test(PUBLIC); + test(VIRTUAL); + const QByteArray type = parseType().name; + // ignore the 'class Foo : BAR(Baz)' case + if (test(LPAREN)) { + until(RPAREN); + } else { + def->superclassList += qMakePair(type, access); + } + } while (test(COMMA)); + } + if (!test(LBRACE)) + return false; + def->begin = index - 1; + bool foundRBrace = until(RBRACE); + def->end = index; + index = def->begin + 1; + return foundRBrace; +} + +Type Moc::parseType() +{ + Type type; + bool hasSignedOrUnsigned = false; + bool isVoid = false; + type.firstToken = lookup(); + for (;;) { + switch (next()) { + case SIGNED: + case UNSIGNED: + hasSignedOrUnsigned = true; + // fall through + case CONST: + case VOLATILE: + type.name += lexem(); + type.name += ' '; + if (lookup(0) == VOLATILE) + type.isVolatile = true; + continue; + case Q_MOC_COMPAT_TOKEN: + case Q_QT3_SUPPORT_TOKEN: + case Q_INVOKABLE_TOKEN: + case Q_SCRIPTABLE_TOKEN: + case Q_SIGNALS_TOKEN: + case Q_SLOTS_TOKEN: + case Q_SIGNAL_TOKEN: + case Q_SLOT_TOKEN: + type.name += lexem(); + return type; + default: + prev(); + break; + } + break; + } + test(ENUM) || test(CLASS) || test(STRUCT); + for(;;) { + switch (next()) { + case IDENTIFIER: + // void mySlot(unsigned myArg) + if (hasSignedOrUnsigned) { + prev(); + break; + } + case CHAR: + case SHORT: + case INT: + case LONG: + type.name += lexem(); + // preserve '[unsigned] long long', 'short int', 'long int', 'long double' + if (test(LONG) || test(INT) || test(DOUBLE)) { + type.name += ' '; + prev(); + continue; + } + break; + case FLOAT: + case DOUBLE: + case VOID: + case BOOL: + type.name += lexem(); + isVoid |= (lookup(0) == VOID); + break; + default: + prev(); + ; + } + if (test(LANGLE)) { + QByteArray templ = lexemUntil(RANGLE); + for (int i = 0; i < templ.size(); ++i) { + type.name += templ.at(i); + if ((templ.at(i) == '<' && i < templ.size()-1 && templ.at(i+1) == ':') + || (templ.at(i) == '>' && i < templ.size()-1 && templ.at(i+1) == '>')) { + type.name += ' '; + } + } + } + if (test(SCOPE)) { + type.name += lexem(); + type.isScoped = true; + } else { + break; + } + } + while (test(CONST) || test(VOLATILE) || test(SIGNED) || test(UNSIGNED) + || test(STAR) || test(AND)) { + type.name += ' '; + type.name += lexem(); + if (lookup(0) == AND) + type.referenceType = Type::Reference; + else if (lookup(0) == STAR) + type.referenceType = Type::Pointer; + } + // transform stupid things like 'const void' or 'void const' into 'void' + if (isVoid && type.referenceType == Type::NoReference) { + type.name = "void"; + } + return type; +} + +bool Moc::parseEnum(EnumDef *def) +{ + bool isTypdefEnum = false; // typedef enum { ... } Foo; + + if (test(IDENTIFIER)) { + def->name = lexem(); + } else { + if (lookup(-1) != TYPEDEF) + return false; // anonymous enum + isTypdefEnum = true; + } + if (!test(LBRACE)) + return false; + do { + if (lookup() == RBRACE) // accept trailing comma + break; + next(IDENTIFIER); + def->values += lexem(); + } while (test(EQ) ? until(COMMA) : test(COMMA)); + next(RBRACE); + if (isTypdefEnum) { + if (!test(IDENTIFIER)) + return false; + def->name = lexem(); + } + return true; +} + +void Moc::parseFunctionArguments(FunctionDef *def) +{ + Q_UNUSED(def); + while (hasNext()) { + ArgumentDef arg; + arg.type = parseType(); + if (arg.type.name == "void") + break; + if (test(IDENTIFIER)) + arg.name = lexem(); + while (test(LBRACK)) { + arg.rightType += lexemUntil(RBRACK); + } + if (test(CONST) || test(VOLATILE)) { + arg.rightType += ' '; + arg.rightType += lexem(); + } + arg.normalizedType = normalizeType(arg.type.name + ' ' + arg.rightType); + arg.typeNameForCast = normalizeType(noRef(arg.type.name) + "(*)" + arg.rightType); + if (test(EQ)) + arg.isDefault = true; + def->arguments += arg; + if (!until(COMMA)) + break; + } +} + +bool Moc::testFunctionAttribute(FunctionDef *def) +{ + if (index < symbols.size() && testFunctionAttribute(symbols.at(index).token, def)) { + ++index; + return true; + } + return false; +} + +bool Moc::testFunctionAttribute(Token tok, FunctionDef *def) +{ + switch (tok) { + case Q_MOC_COMPAT_TOKEN: + case Q_QT3_SUPPORT_TOKEN: + def->isCompat = true; + return true; + case Q_INVOKABLE_TOKEN: + def->isInvokable = true; + return true; + case Q_SIGNAL_TOKEN: + def->isSignal = true; + return true; + case Q_SLOT_TOKEN: + def->isSlot = true; + return true; + case Q_SCRIPTABLE_TOKEN: + def->isInvokable = def->isScriptable = true; + return true; + default: break; + } + return false; +} + +// returns false if the function should be ignored +bool Moc::parseFunction(FunctionDef *def, bool inMacro) +{ + def->isVirtual = false; + while (test(INLINE) || test(STATIC) || test(VIRTUAL) + || testFunctionAttribute(def)) { + if (lookup() == VIRTUAL) + def->isVirtual = true; + } + bool templateFunction = (lookup() == TEMPLATE); + def->type = parseType(); + if (def->type.name.isEmpty()) { + if (templateFunction) + error("Template function as signal or slot"); + else + error(); + } + bool scopedFunctionName = false; + if (test(LPAREN)) { + def->name = def->type.name; + scopedFunctionName = def->type.isScoped; + def->type = Type("int"); + } else { + Type tempType = parseType();; + while (!tempType.name.isEmpty() && lookup() != LPAREN) { + if (testFunctionAttribute(def->type.firstToken, def)) + ; // fine + else if (def->type.firstToken == Q_SIGNALS_TOKEN) + error(); + else if (def->type.firstToken == Q_SLOTS_TOKEN) + error(); + else { + if (!def->tag.isEmpty()) + def->tag += ' '; + def->tag += def->type.name; + } + def->type = tempType; + tempType = parseType(); + } + next(LPAREN, "Not a signal or slot declaration"); + def->name = tempType.name; + scopedFunctionName = tempType.isScoped; + } + + // we don't support references as return types, it's too dangerous + if (def->type.referenceType == Type::Reference) + def->type = Type("void"); + + def->normalizedType = normalizeType(def->type.name); + + if (!test(RPAREN)) { + parseFunctionArguments(def); + next(RPAREN); + } + + // support optional macros with compiler specific options + while (test(IDENTIFIER)) + ; + + def->isConst = test(CONST); + + while (test(IDENTIFIER)) + ; + + if (inMacro) { + next(RPAREN); + prev(); + } else { + if (test(THROW)) { + next(LPAREN); + until(RPAREN); + } + if (test(SEMIC)) + ; + else if ((def->inlineCode = test(LBRACE))) + until(RBRACE); + else if ((def->isAbstract = test(EQ))) + until(SEMIC); + else + error(); + } + + if (scopedFunctionName) { + QByteArray msg("Function declaration "); + msg += def->name; + msg += " contains extra qualification. Ignoring as signal or slot."; + warning(msg.constData()); + return false; + } + return true; +} + +// like parseFunction, but never aborts with an error +bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) +{ + def->isVirtual = false; + while (test(EXPLICIT) || test(INLINE) || test(STATIC) || test(VIRTUAL) + || testFunctionAttribute(def)) { + if (lookup() == VIRTUAL) + def->isVirtual = true; + } + bool tilde = test(TILDE); + def->type = parseType(); + if (def->type.name.isEmpty()) + return false; + bool scopedFunctionName = false; + if (test(LPAREN)) { + def->name = def->type.name; + scopedFunctionName = def->type.isScoped; + if (def->name == cdef->classname) { + def->isDestructor = tilde; + def->isConstructor = !tilde; + def->type = Type(); + } else { + def->type = Type("int"); + } + } else { + Type tempType = parseType();; + while (!tempType.name.isEmpty() && lookup() != LPAREN) { + if (testFunctionAttribute(def->type.firstToken, def)) + ; // fine + else if (def->type.name == "Q_SIGNAL") + def->isSignal = true; + else if (def->type.name == "Q_SLOT") + def->isSlot = true; + else { + if (!def->tag.isEmpty()) + def->tag += ' '; + def->tag += def->type.name; + } + def->type = tempType; + tempType = parseType(); + } + if (!test(LPAREN)) + return false; + def->name = tempType.name; + scopedFunctionName = tempType.isScoped; + } + + // we don't support references as return types, it's too dangerous + if (def->type.referenceType == Type::Reference) + def->type = Type("void"); + + def->normalizedType = normalizeType(def->type.name); + + if (!test(RPAREN)) { + parseFunctionArguments(def); + if (!test(RPAREN)) + return false; + } + def->isConst = test(CONST); + if (scopedFunctionName + && (def->isSignal || def->isSlot || def->isInvokable)) { + QByteArray msg("parsemaybe: Function declaration "); + msg += def->name; + msg += " contains extra qualification. Ignoring as signal or slot."; + warning(msg.constData()); + return false; + } + return true; +} + + +void Moc::parse() +{ + QList<NamespaceDef> namespaceList; + bool templateClass = false; + while (hasNext()) { + Token t = next(); + switch (t) { + case NAMESPACE: { + int rewind = index; + if (test(IDENTIFIER)) { + if (test(EQ)) { + // namespace Foo = Bar::Baz; + until(SEMIC); + } else if (!test(SEMIC)) { + NamespaceDef def; + def.name = lexem(); + next(LBRACE); + def.begin = index - 1; + until(RBRACE); + def.end = index; + index = def.begin + 1; + namespaceList += def; + index = rewind; + } + } + break; + } + case SEMIC: + case RBRACE: + templateClass = false; + break; + case TEMPLATE: + templateClass = true; + break; + case MOC_INCLUDE_BEGIN: + currentFilenames.push(symbol().unquotedLexem()); + break; + case MOC_INCLUDE_END: + currentFilenames.pop(); + break; + case Q_DECLARE_INTERFACE_TOKEN: + parseDeclareInterface(); + break; + case Q_DECLARE_METATYPE_TOKEN: + parseDeclareMetatype(); + break; + case USING: + if (test(NAMESPACE)) { + while (test(SCOPE) || test(IDENTIFIER)) + ; + next(SEMIC); + } + break; + case CLASS: + case STRUCT: { + if (currentFilenames.size() <= 1) + break; + + ClassDef def; + if (!parseClassHead(&def)) + continue; + + while (inClass(&def) && hasNext()) { + if (next() == Q_OBJECT_TOKEN) { + def.hasQObject = true; + break; + } + } + + if (!def.hasQObject) + continue; + + for (int i = namespaceList.size() - 1; i >= 0; --i) + if (inNamespace(&namespaceList.at(i))) + def.qualified.prepend(namespaceList.at(i).name + "::"); + + knownQObjectClasses.insert(def.classname); + knownQObjectClasses.insert(def.qualified); + + continue; } + default: break; + } + if ((t != CLASS && t != STRUCT)|| currentFilenames.size() > 1) + continue; + ClassDef def; + if (parseClassHead(&def)) { + FunctionDef::Access access = FunctionDef::Private; + for (int i = namespaceList.size() - 1; i >= 0; --i) + if (inNamespace(&namespaceList.at(i))) + def.qualified.prepend(namespaceList.at(i).name + "::"); + while (inClass(&def) && hasNext()) { + switch ((t = next())) { + case PRIVATE: + access = FunctionDef::Private; + if (test(Q_SIGNALS_TOKEN)) + error("Signals cannot have access specifier"); + break; + case PROTECTED: + access = FunctionDef::Protected; + if (test(Q_SIGNALS_TOKEN)) + error("Signals cannot have access specifier"); + break; + case PUBLIC: + access = FunctionDef::Public; + if (test(Q_SIGNALS_TOKEN)) + error("Signals cannot have access specifier"); + break; + case CLASS: { + ClassDef nestedDef; + if (parseClassHead(&nestedDef)) { + while (inClass(&nestedDef) && inClass(&def)) { + t = next(); + if (t >= Q_META_TOKEN_BEGIN && t < Q_META_TOKEN_END) + error("Meta object features not supported for nested classes"); + } + } + } break; + case Q_SIGNALS_TOKEN: + parseSignals(&def); + break; + case Q_SLOTS_TOKEN: + switch (lookup(-1)) { + case PUBLIC: + case PROTECTED: + case PRIVATE: + parseSlots(&def, access); + break; + default: + error("Missing access specifier for slots"); + } + break; + case Q_OBJECT_TOKEN: + def.hasQObject = true; + if (templateClass) + error("Template classes not supported by Q_OBJECT"); + if (def.classname != "Qt" && def.classname != "QObject" && def.superclassList.isEmpty()) + error("Class contains Q_OBJECT macro but does not inherit from QObject"); + break; + case Q_GADGET_TOKEN: + def.hasQGadget = true; + if (templateClass) + error("Template classes not supported by Q_GADGET"); + break; + case Q_PROPERTY_TOKEN: + parseProperty(&def); + break; + case Q_ENUMS_TOKEN: + parseEnumOrFlag(&def, false); + break; + case Q_FLAGS_TOKEN: + parseEnumOrFlag(&def, true); + break; + case Q_DECLARE_FLAGS_TOKEN: + parseFlag(&def); + break; + case Q_CLASSINFO_TOKEN: + parseClassInfo(&def); + break; + case Q_INTERFACES_TOKEN: + parseInterfaces(&def); + break; + case Q_PRIVATE_SLOT_TOKEN: + parseSlotInPrivate(&def, access); + break; + case ENUM: { + EnumDef enumDef; + if (parseEnum(&enumDef)) + def.enumList += enumDef; + } break; + default: + FunctionDef funcDef; + funcDef.access = access; + int rewind = index; + if (parseMaybeFunction(&def, &funcDef)) { + if (funcDef.isConstructor) { + if ((access == FunctionDef::Public) && funcDef.isInvokable) { + def.constructorList += funcDef; + while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + funcDef.wasCloned = true; + funcDef.arguments.removeLast(); + def.constructorList += funcDef; + } + } + } else if (funcDef.isDestructor) { + // don't care about destructors + } else { + if (access == FunctionDef::Public) + def.publicList += funcDef; + if (funcDef.isSlot) { + def.slotList += funcDef; + while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + funcDef.wasCloned = true; + funcDef.arguments.removeLast(); + def.slotList += funcDef; + } + } else if (funcDef.isSignal) { + def.signalList += funcDef; + while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + funcDef.wasCloned = true; + funcDef.arguments.removeLast(); + def.signalList += funcDef; + } + } else if (funcDef.isInvokable) { + def.methodList += funcDef; + while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + funcDef.wasCloned = true; + funcDef.arguments.removeLast(); + def.methodList += funcDef; + } + } + } + } else { + index = rewind; + } + } + } + + next(RBRACE); + + if (!def.hasQObject && !def.hasQGadget && def.signalList.isEmpty() && def.slotList.isEmpty() + && def.propertyList.isEmpty() && def.enumDeclarations.isEmpty()) + continue; // no meta object code required + + + if (!def.hasQObject && !def.hasQGadget) + error("Class declarations lacks Q_OBJECT macro."); + + checkSuperClasses(&def); + + classList += def; + knownQObjectClasses.insert(def.classname); + knownQObjectClasses.insert(def.qualified); + } + } +} + +void Moc::generate(FILE *out) +{ + + QDateTime dt = QDateTime::currentDateTime(); + QByteArray dstr = dt.toString().toLatin1(); + QByteArray fn = filename; + int i = filename.length()-1; + while (i>0 && filename[i-1] != '/' && filename[i-1] != '\\') + --i; // skip path + if (i >= 0) + fn = filename.mid(i); + fprintf(out, "/****************************************************************************\n" + "** Meta object code from reading C++ file '%s'\n**\n" , (const char*)fn); + fprintf(out, "** Created: %s\n" + "** by: The Qt Meta Object Compiler version %d (Qt %s)\n**\n" , dstr.data(), mocOutputRevision, QT_VERSION_STR); + fprintf(out, "** WARNING! All changes made in this file will be lost!\n" + "*****************************************************************************/\n\n"); + + + if (!noInclude) { + if (includePath.size() && includePath.right(1) != "/") + includePath += "/"; + for (int i = 0; i < includeFiles.size(); ++i) { + QByteArray inc = includeFiles.at(i); + if (inc[0] != '<' && inc[0] != '"') { + if (includePath.size() && includePath != "./") + inc.prepend(includePath); + inc = "\"" + inc + "\""; + } + fprintf(out, "#include %s\n", inc.constData()); + } + } + if (classList.size() && classList.first().classname == "Qt") + fprintf(out, "#include <QtCore/qobject.h>\n"); + + fprintf(out, "#if !defined(Q_MOC_OUTPUT_REVISION)\n" + "#error \"The header file '%s' doesn't include <QObject>.\"\n", (const char *)fn); + fprintf(out, "#elif Q_MOC_OUTPUT_REVISION != %d\n", mocOutputRevision); + fprintf(out, "#error \"This file was generated using the moc from %s." + " It\"\n#error \"cannot be used with the include files from" + " this version of Qt.\"\n#error \"(The moc has changed too" + " much.)\"\n", QT_VERSION_STR); + fprintf(out, "#endif\n\n"); + + fprintf(out, "QT_BEGIN_MOC_NAMESPACE\n"); + + for (i = 0; i < classList.size(); ++i) { + Generator generator(&classList[i], metaTypes, out); + generator.generateCode(); + } + + fprintf(out, "QT_END_MOC_NAMESPACE\n"); +} + + +QList<QMetaObject*> Moc::generate(bool ignoreProperties) +{ + QList<QMetaObject*> result; + for (int i = 0; i < classList.size(); ++i) { + Generator generator(&classList[i], metaTypes); + result << generator.generateMetaObject(ignoreProperties); + } + return result; +} + +void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) +{ + next(COLON); + while (inClass(def) && hasNext()) { + switch (next()) { + case PUBLIC: + case PROTECTED: + case PRIVATE: + case Q_SIGNALS_TOKEN: + case Q_SLOTS_TOKEN: + prev(); + return; + case SEMIC: + continue; + case FRIEND: + until(SEMIC); + continue; + case USING: + error("'using' directive not supported in 'slots' section"); + default: + prev(); + } + + FunctionDef funcDef; + funcDef.access = access; + if (!parseFunction(&funcDef)) + continue; + def->slotList += funcDef; + while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + funcDef.wasCloned = true; + funcDef.arguments.removeLast(); + def->slotList += funcDef; + } + } +} + +void Moc::parseSignals(ClassDef *def) +{ + next(COLON); + while (inClass(def) && hasNext()) { + switch (next()) { + case PUBLIC: + case PROTECTED: + case PRIVATE: + case Q_SIGNALS_TOKEN: + case Q_SLOTS_TOKEN: + prev(); + return; + case SEMIC: + continue; + case FRIEND: + until(SEMIC); + continue; + case USING: + error("'using' directive not supported in 'signals' section"); + default: + prev(); + } + FunctionDef funcDef; + funcDef.access = FunctionDef::Protected; + parseFunction(&funcDef); + if (funcDef.isVirtual) + error("Signals cannot be declared virtual"); + if (funcDef.inlineCode) + error("Not a signal declaration"); + def->signalList += funcDef; + while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + funcDef.wasCloned = true; + funcDef.arguments.removeLast(); + def->signalList += funcDef; + } + } +} + + +void Moc::parseProperty(ClassDef *def) +{ + next(LPAREN); + PropertyDef propDef; + QByteArray type = parseType().name; + if (type.isEmpty()) + error(); + propDef.designable = propDef.scriptable = propDef.stored = "true"; + propDef.user = "false"; + /* + The Q_PROPERTY construct cannot contain any commas, since + commas separate macro arguments. We therefore expect users + to type "QMap" instead of "QMap<QString, QVariant>". For + coherence, we also expect the same for + QValueList<QVariant>, the other template class supported by + QVariant. + */ + type = normalizeType(type); + if (type == "QMap") + type = "QMap<QString,QVariant>"; + else if (type == "QValueList") + type = "QValueList<QVariant>"; + else if (type == "LongLong") + type = "qlonglong"; + else if (type == "ULongLong") + type = "qulonglong"; + propDef.type = type; + + next(); + propDef.name = lexem(); + while (test(IDENTIFIER)) { + QByteArray l = lexem(); + QByteArray v, v2; + if (test(LPAREN)) { + v = lexemUntil(RPAREN); + } else { + next(IDENTIFIER); + v = lexem(); + if (test(LPAREN)) + v2 = lexemUntil(RPAREN); + else if (v != "true" && v != "false") + v2 = "()"; + } + switch (l[0]) { + case 'R': + if (l == "READ") + propDef.read = v; + else if (l == "RESET") + propDef.reset = v + v2; + else + error(2); + break; + case 'S': + if (l == "SCRIPTABLE") + propDef.scriptable = v + v2; + else if (l == "STORED") + propDef.stored = v + v2; + else + error(2); + break; + case 'W': if (l != "WRITE") error(2); + propDef.write = v; + break; + case 'D': if (l != "DESIGNABLE") error(2); + propDef.designable = v + v2; + break; + case 'E': if (l != "EDITABLE") error(2); + propDef.editable = v + v2; + break; + case 'N': if (l != "NOTIFY") error(2); + propDef.notify = v; + break; + case 'U': if (l != "USER") error(2); + propDef.user = v + v2; + break; + default: + error(2); + } + } + next(RPAREN); + if (propDef.read.isNull()) { + QByteArray msg; + msg += "Property declaration "; + msg += propDef.name; + msg += " has no READ accessor function. The property will be invalid."; + warning(msg.constData()); + } + if(!propDef.notify.isEmpty()) + def->notifyableProperties++; + + def->propertyList += propDef; +} + +void Moc::parseEnumOrFlag(ClassDef *def, bool isFlag) +{ + next(LPAREN); + QByteArray identifier; + while (test(IDENTIFIER)) { + identifier = lexem(); + while (test(SCOPE) && test(IDENTIFIER)) { + identifier += "::"; + identifier += lexem(); + } + def->enumDeclarations[identifier] = isFlag; + } + next(RPAREN); +} + +void Moc::parseFlag(ClassDef *def) +{ + next(LPAREN); + QByteArray flagName, enumName; + while (test(IDENTIFIER)) { + flagName = lexem(); + while (test(SCOPE) && test(IDENTIFIER)) { + flagName += "::"; + flagName += lexem(); + } + } + next(COMMA); + while (test(IDENTIFIER)) { + enumName = lexem(); + while (test(SCOPE) && test(IDENTIFIER)) { + enumName += "::"; + enumName += lexem(); + } + } + + def->flagAliases.insert(enumName, flagName); + next(RPAREN); +} + +void Moc::parseClassInfo(ClassDef *def) +{ + next(LPAREN); + ClassInfoDef infoDef; + next(STRING_LITERAL); + infoDef.name = symbol().unquotedLexem(); + next(COMMA); + if (test(STRING_LITERAL)) { + infoDef.value = symbol().unquotedLexem(); + } else { + // support Q_CLASSINFO("help", QT_TR_NOOP("blah")) + next(IDENTIFIER); + next(LPAREN); + next(STRING_LITERAL); + infoDef.value = symbol().unquotedLexem(); + next(RPAREN); + } + next(RPAREN); + def->classInfoList += infoDef; +} + +void Moc::parseInterfaces(ClassDef *def) +{ + next(LPAREN); + while (test(IDENTIFIER)) { + QList<ClassDef::Interface> iface; + iface += ClassDef::Interface(lexem()); + while (test(SCOPE)) { + iface.last().className += lexem(); + next(IDENTIFIER); + iface.last().className += lexem(); + } + while (test(COLON)) { + next(IDENTIFIER); + iface += ClassDef::Interface(lexem()); + while (test(SCOPE)) { + iface.last().className += lexem(); + next(IDENTIFIER); + iface.last().className += lexem(); + } + } + // resolve from classnames to interface ids + for (int i = 0; i < iface.count(); ++i) { + const QByteArray iid = interface2IdMap.value(iface.at(i).className); + if (iid.isEmpty()) + error("Undefined interface"); + + iface[i].interfaceId = iid; + } + def->interfaceList += iface; + } + next(RPAREN); +} + +void Moc::parseDeclareInterface() +{ + next(LPAREN); + QByteArray interface; + next(IDENTIFIER); + interface += lexem(); + while (test(SCOPE)) { + interface += lexem(); + next(IDENTIFIER); + interface += lexem(); + } + next(COMMA); + QByteArray iid; + if (test(STRING_LITERAL)) { + iid = lexem(); + } else { + next(IDENTIFIER); + iid = lexem(); + } + interface2IdMap.insert(interface, iid); + next(RPAREN); +} + +void Moc::parseDeclareMetatype() +{ + next(LPAREN); + QByteArray typeName = lexemUntil(RPAREN); + typeName.remove(0, 1); + typeName.chop(1); + metaTypes.append(typeName); +} + +void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access) +{ + next(LPAREN); + FunctionDef funcDef; + next(IDENTIFIER); + funcDef.inPrivateClass = lexem(); + // also allow void functions + if (test(LPAREN)) { + next(RPAREN); + funcDef.inPrivateClass += "()"; + } + next(COMMA); + funcDef.access = access; + parseFunction(&funcDef, true); + def->slotList += funcDef; + while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { + funcDef.wasCloned = true; + funcDef.arguments.removeLast(); + def->slotList += funcDef; + } +} + +QByteArray Moc::lexemUntil(Token target) +{ + int from = index; + until(target); + QByteArray s; + while (from <= index) { + QByteArray n = symbols.at(from++-1).lexem(); + if (s.size() && n.size() + && is_ident_char(s.at(s.size()-1)) + && is_ident_char(n.at(0))) + s += ' '; + s += n; + } + return s; +} + +bool Moc::until(Token target) { + int braceCount = 0; + int brackCount = 0; + int parenCount = 0; + int angleCount = 0; + if (index) { + switch(symbols.at(index-1).token) { + case LBRACE: ++braceCount; break; + case LBRACK: ++brackCount; break; + case LPAREN: ++parenCount; break; + case LANGLE: ++angleCount; break; + default: break; + } + } + while (index < symbols.size()) { + Token t = symbols.at(index++).token; + switch (t) { + case LBRACE: ++braceCount; break; + case RBRACE: --braceCount; break; + case LBRACK: ++brackCount; break; + case RBRACK: --brackCount; break; + case LPAREN: ++parenCount; break; + case RPAREN: --parenCount; break; + case LANGLE: ++angleCount; break; + case RANGLE: --angleCount; break; + case GTGT: angleCount -= 2; t = RANGLE; break; + default: break; + } + if (t == target + && braceCount <= 0 + && brackCount <= 0 + && parenCount <= 0 + && (target != RANGLE || angleCount <= 0)) + return true; + + if (braceCount < 0 || brackCount < 0 || parenCount < 0 + || (target == RANGLE && angleCount < 0)) { + --index; + break; + } + } + return false; +} + +void Moc::checkSuperClasses(ClassDef *def) +{ + const QByteArray firstSuperclass = def->superclassList.value(0).first; + + if (!knownQObjectClasses.contains(firstSuperclass)) { + // enable once we /require/ include paths +#if 0 + QByteArray msg; + msg += "Class "; + msg += def->className; + msg += " contains the Q_OBJECT macro and inherits from "; + msg += def->superclassList.value(0); + msg += " but that is not a known QObject subclass. You may get compilation errors."; + warning(msg.constData()); +#endif + return; + } + for (int i = 1; i < def->superclassList.count(); ++i) { + const QByteArray superClass = def->superclassList.at(i).first; + if (knownQObjectClasses.contains(superClass)) { + QByteArray msg; + msg += "Class "; + msg += def->classname; + msg += " inherits from two QObject subclasses "; + msg += firstSuperclass; + msg += " and "; + msg += superClass; + msg += ". This is not supported!"; + warning(msg.constData()); + } + + if (interface2IdMap.contains(superClass)) { + bool registeredInterface = false; + for (int i = 0; i < def->interfaceList.count(); ++i) + if (def->interfaceList.at(i).first().className == superClass) { + registeredInterface = true; + break; + } + + if (!registeredInterface) { + QByteArray msg; + msg += "Class "; + msg += def->classname; + msg += " implements the interface "; + msg += superClass; + msg += " but does not list it in Q_INTERFACES. qobject_cast to "; + msg += superClass; + msg += " will not work!"; + warning(msg.constData()); + } + } + } +} + + +QT_END_NAMESPACE diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h new file mode 100644 index 0000000..689104c --- /dev/null +++ b/src/tools/moc/moc.h @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MOC_H +#define MOC_H + +#include "parser.h" +#include <QStringList> +#include <QMap> +#include <QPair> +#include <stdio.h> +#include <ctype.h> + +QT_BEGIN_NAMESPACE + +struct QMetaObject; + +struct Type +{ + enum ReferenceType { NoReference, Reference, Pointer }; + + inline Type() : isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {} + inline explicit Type(const QByteArray &_name) : name(_name), isVolatile(false), firstToken(NOTOKEN), referenceType(NoReference) {} + QByteArray name; + uint isVolatile : 1; + uint isScoped : 1; + Token firstToken; + ReferenceType referenceType; +}; + +struct EnumDef +{ + QByteArray name; + QList<QByteArray> values; +}; + +struct ArgumentDef +{ + ArgumentDef() : isDefault(false) {} + Type type; + QByteArray rightType, normalizedType, name; + QByteArray typeNameForCast; // type name to be used in cast from void * in metacall + bool isDefault; +}; + +struct FunctionDef +{ + FunctionDef(): returnTypeIsVolatile(false), access(Private), isConst(false), isVirtual(false), + inlineCode(false), wasCloned(false), isCompat(false), isInvokable(false), + isScriptable(false), isSlot(false), isSignal(false), + isConstructor(false), isDestructor(false), isAbstract(false) {} + Type type; + QByteArray normalizedType; + QByteArray tag; + QByteArray name; + bool returnTypeIsVolatile; + + QList<ArgumentDef> arguments; + + enum Access { Private, Protected, Public }; + Access access; + bool isConst; + bool isVirtual; + bool inlineCode; + bool wasCloned; + + QByteArray inPrivateClass; + bool isCompat; + bool isInvokable; + bool isScriptable; + bool isSlot; + bool isSignal; + bool isConstructor; + bool isDestructor; + bool isAbstract; +}; + +struct PropertyDef +{ + PropertyDef():notifyId(-1), gspec(ValueSpec){} + QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify; + int notifyId; + enum Specification { ValueSpec, ReferenceSpec, PointerSpec }; + Specification gspec; + bool stdCppSet() const { + QByteArray s("set"); + s += toupper(name[0]); + s += name.mid(1); + return (s == write); + } +}; + + +struct ClassInfoDef +{ + QByteArray name; + QByteArray value; +}; + +struct ClassDef { + ClassDef(): + hasQObject(false), hasQGadget(false), notifyableProperties(0){} + QByteArray classname; + QByteArray qualified; + QList<QPair<QByteArray, FunctionDef::Access> > superclassList; + + struct Interface + { + inline explicit Interface(const QByteArray &_className) + : className(_className) {} + QByteArray className; + QByteArray interfaceId; + }; + QList<QList<Interface> >interfaceList; + + bool hasQObject; + bool hasQGadget; + + QList<FunctionDef> constructorList; + QList<FunctionDef> signalList, slotList, methodList, publicList; + int notifyableProperties; + QList<PropertyDef> propertyList; + QList<ClassInfoDef> classInfoList; + QMap<QByteArray, bool> enumDeclarations; + QList<EnumDef> enumList; + QMap<QByteArray, QByteArray> flagAliases; + + int begin; + int end; +}; + +struct NamespaceDef { + QByteArray name; + int begin; + int end; +}; + +class Moc : public Parser +{ +public: + Moc() + : noInclude(false), generatedCode(false) + {} + + QByteArray filename; + + bool noInclude; + bool generatedCode; + QByteArray includePath; + QList<QByteArray> includeFiles; + QList<ClassDef> classList; + QMap<QByteArray, QByteArray> interface2IdMap; + QList<QByteArray> metaTypes; + QSet<QByteArray> knownQObjectClasses; + + void parse(); + void generate(FILE *out); + QList<QMetaObject*> generate(bool ignoreProperties); + + bool parseClassHead(ClassDef *def); + inline bool inClass(const ClassDef *def) const { + return index > def->begin && index < def->end - 1; + } + + inline bool inNamespace(const NamespaceDef *def) const { + return index > def->begin && index < def->end - 1; + } + + Type parseType(); + + bool parseEnum(EnumDef *def); + + bool parseFunction(FunctionDef *def, bool inMacro = false); + bool parseMaybeFunction(const ClassDef *cdef, FunctionDef *def); + + void parseSlots(ClassDef *def, FunctionDef::Access access); + void parseSignals(ClassDef *def); + void parseProperty(ClassDef *def); + void parseEnumOrFlag(ClassDef *def, bool isFlag); + void parseFlag(ClassDef *def); + void parseClassInfo(ClassDef *def); + void parseInterfaces(ClassDef *def); + void parseDeclareInterface(); + void parseDeclareMetatype(); + void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access); + + void parseFunctionArguments(FunctionDef *def); + + QByteArray lexemUntil(Token); + bool until(Token); + + // test for Q_INVOCABLE, Q_SCRIPTABLE, etc. and set the flags + // in FunctionDef accordingly + bool testFunctionAttribute(FunctionDef *def); + bool testFunctionAttribute(Token tok, FunctionDef *def); + + void checkSuperClasses(ClassDef *def); +}; + +inline QByteArray noRef(const QByteArray &type) +{ + if (type.endsWith('&')) + return type.left(type.length()-1); + return type; +} + +QT_END_NAMESPACE + +#endif // MOC_H diff --git a/src/tools/moc/moc.pri b/src/tools/moc/moc.pri new file mode 100644 index 0000000..b689a35 --- /dev/null +++ b/src/tools/moc/moc.pri @@ -0,0 +1,16 @@ + +INCLUDEPATH += $$PWD + +HEADERS = $$PWD/moc.h \ + $$PWD/preprocessor.h \ + $$PWD/parser.h \ + $$PWD/symbols.h \ + $$PWD/token.h \ + $$PWD/utils.h \ + $$PWD/generator.h \ + $$PWD/outputrevision.h +SOURCES = $$PWD/moc.cpp \ + $$PWD/preprocessor.cpp \ + $$PWD/generator.cpp \ + $$PWD/parser.cpp \ + $$PWD/token.cpp diff --git a/src/tools/moc/moc.pro b/src/tools/moc/moc.pro new file mode 100644 index 0000000..0b8ddbe --- /dev/null +++ b/src/tools/moc/moc.pro @@ -0,0 +1,18 @@ +TEMPLATE = app +TARGET = moc + +DEFINES += QT_MOC +DESTDIR = ../../../bin +INCLUDEPATH += . +DEPENDPATH += . +LIBS = +OBJECTS_DIR = . + +include(moc.pri) +HEADERS += qdatetime_p.h +SOURCES += main.cpp +include(../bootstrap/bootstrap.pri) + +target.path=$$[QT_INSTALL_BINS] +INSTALLS += target +include(../../qt_targets.pri) diff --git a/src/tools/moc/mwerks_mac.cpp b/src/tools/moc/mwerks_mac.cpp new file mode 100644 index 0000000..ae8defa --- /dev/null +++ b/src/tools/moc/mwerks_mac.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifdef MOC_MWERKS_PLUGIN + +#include "mwerks_mac.h" +#include "qt_mac.h" + +/* compiler headers */ +#include "DropInCompilerLinker.h" +#include "CompilerMapping.h" +#include "CWPluginErrors.h" + +/* standard headers */ +#include <stdio.h> +#include <string.h> + +QT_BEGIN_NAMESPACE + +//qglobal.cpp +const unsigned char * p_str(const char * c); +QCString pstring2qstring(const unsigned char *c); + +#if CW_USE_PRAGMA_EXPORT +#pragma export on +#endif + +CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize) +{ + static const DropInFlags sFlags = { + kCurrentDropInFlagsVersion, + CWDROPINCOMPILERTYPE, + DROPINCOMPILERLINKERAPIVERSION_7, + kCompAlwaysReload|kCompRequiresProjectBuildStartedMsg, + Lang_C_CPP, + DROPINCOMPILERLINKERAPIVERSION + }; + *flags = &sFlags; + *flagsSize = sizeof(sFlags); + return cwNoErr; +} + + + +CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName) +{ + static const char sDropInName[] = "McMoc"; + *dropinName = sDropInName; + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName) +{ + static const char sDisplayName[] = "McMoc"; + *displayName = sDisplayName; + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList) +{ + static CWDataType sCPU = targetCPUAny; + static CWDataType sOS = targetOSMacintosh; + static CWTargetList sTargetList = {kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS}; + *targetList = &sTargetList; + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList) +{ + static CWExtensionMapping sExtension[] = { {'TEXT', ".mocs", kPrecompile } }; + static CWExtMapList sExtensionMapList = {kCurrentCWExtMapListVersion, 3, sExtension}; + *defaultMappingList = &sExtensionMapList; + return cwNoErr; +} + +#if CW_USE_PRAGMA_EXPORT +#pragma export off +#endif +typedef short CWFileRef; + +static int line_count = 0; +moc_status do_moc(CWPluginContext, const QCString &, const QCString &, CWFileSpec *, bool); + +static CWResult mocify(CWPluginContext context, const QCString &source) +{ + CWDisplayLines(context, line_count++); + + source.stripWhiteSpace(); + + CWResult err; + bool dotmoc=false; + QCString stem = source, ext; + int dotpos = stem.findRev('.'); + if(dotpos != -1) { + ext = stem.right(stem.length() - (dotpos+1)); + stem = stem.left(dotpos); + if(ext == "cpp") + dotmoc = true; + } else { + //whoa! + } + QCString dest; + if(dotmoc) + dest = stem + ".moc"; + else + dest = "moc_" + stem + ".cpp"; + + //moc it + CWFileSpec destSpec; + moc_status mocd = do_moc(context, source, dest, &destSpec, dotmoc); + +#if 0 + QCString derr = "Weird"; + switch(mocd) { + case moc_success: derr = "Success"; break; + case moc_parse_error: derr = "Parser Error"; break; + case moc_no_qobject:derr = "No QOBJECT"; break; + case moc_not_time: derr = "Not Time"; break; + case moc_no_source: derr = "No Source"; break; + case moc_general_error: derr = "General Error"; break; + } + char dmsg[200]; + sprintf(dmsg, "\"%s\" %s", source.data(), derr.data()); + CWReportMessage(context, NULL, dmsg, NULL, messagetypeError, 0); +#endif + + //handle project + if(mocd == moc_no_qobject) { + char msg[400]; + sprintf(msg, "\"%s\" No relevant classes found. No output generated.", source.data()); + CWReportMessage(context, NULL, msg, NULL, messagetypeWarning, 0); + } else if ((mocd == moc_success || mocd == moc_not_time) && !dotmoc) + { + long whichFile; + CWNewProjectEntryInfo ei; + memset(&ei, '\0', sizeof(ei)); + ei.groupPath = "QtGenerated"; + err = CWAddProjectEntry(context, &destSpec, true, &ei, &whichFile); + if (!CWSUCCESS(err)) + { + char msg[200]; + sprintf(msg, "\"%s\" not added", dest.data()); + CWReportMessage(context, NULL, msg, NULL, messagetypeWarning, 0); + } + if(mocd == moc_success) + CWSetModDate(context, &destSpec, NULL, true); + } + return cwNoErr; +} + +pascal short main(CWPluginContext context) +{ + short result; + long request; + + if (CWGetPluginRequest(context, &request) != cwNoErr) + return cwErrRequestFailed; + result = cwErrInvalidParameter; + + /* dispatch on compiler request */ + switch (request) + { + case reqInitCompiler: + case reqTermCompiler: + result = cwNoErr; + break; + + case reqCompile: + { + line_count = 0; + const char *files = NULL; + long filelen; + CWGetMainFileText(context, &files, &filelen); + const char *beg = files; + for(int x = 0; x < filelen; x++) { + if(*(files++) == '\r') { + char file[1024]; + memcpy(file, beg, files - beg); + file[(files-beg)-1] = '\0'; + mocify(context, file); + beg = files; + } + } + if(beg != files) { + char file[1024]; + memcpy(file, beg, files - beg); + file[(files-beg)] = '\0'; + mocify(context, file); + } + + result = cwNoErr; + break; + } + } + + /* return result code */ + return result; +} + +#endif + +QT_END_NAMESPACE diff --git a/src/tools/moc/mwerks_mac.h b/src/tools/moc/mwerks_mac.h new file mode 100644 index 0000000..bca0829 --- /dev/null +++ b/src/tools/moc/mwerks_mac.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MWERKS_MAC_H +#define MWERKS_MAC_H + +#include <QtGlobal> + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_MAC + +#define macintosh + +/*make moc a plugin*/ +enum moc_status { + moc_success = 1, + moc_parse_error = 2, + moc_no_qobject = 3, + moc_not_time = 4, + moc_no_source = 5, + moc_general_error = 6 +}; + +#endif + +QT_END_NAMESPACE + +#endif // MWERKS_MAC_H diff --git a/src/tools/moc/outputrevision.h b/src/tools/moc/outputrevision.h new file mode 100644 index 0000000..1e1d640 --- /dev/null +++ b/src/tools/moc/outputrevision.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OUTPUTREVISION_H +#define OUTPUTREVISION_H + +// if the output revision changes, you MUST change it in qobjectdefs.h too +enum { mocOutputRevision = 61 }; // moc format output revision + +#endif // OUTPUTREVISION_H diff --git a/src/tools/moc/parser.cpp b/src/tools/moc/parser.cpp new file mode 100644 index 0000000..b6c3f63 --- /dev/null +++ b/src/tools/moc/parser.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "parser.h" +#include "utils.h" +#include <stdio.h> +#include <stdlib.h> + +QT_BEGIN_NAMESPACE + +#ifdef USE_LEXEM_STORE +Symbol::LexemStore Symbol::lexemStore; +#endif + +static const char *error_msg = 0; + +#ifdef Q_CC_MSVC +#define ErrorFormatString "%s(%d): " +#else +#define ErrorFormatString "%s:%d: " +#endif + +void Parser::error(int rollback) { + index -= rollback; + error(); +} +void Parser::error(const char *msg) { + if (msg || error_msg) + qWarning(ErrorFormatString "Error: %s", + currentFilenames.top().constData(), symbol().lineNum, msg?msg:error_msg); + else + qWarning(ErrorFormatString "Parse error at \"%s\"", + currentFilenames.top().constData(), symbol().lineNum, symbol().lexem().data()); + exit(EXIT_FAILURE); +} + +void Parser::warning(const char *msg) { + if (displayWarnings && msg) + fprintf(stderr, ErrorFormatString "Warning: %s\n", + currentFilenames.top().constData(), qMax(0, index > 0 ? symbol().lineNum : 0), msg); +} + +QT_END_NAMESPACE diff --git a/src/tools/moc/parser.h b/src/tools/moc/parser.h new file mode 100644 index 0000000..c49f3cf --- /dev/null +++ b/src/tools/moc/parser.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PARSER_H +#define PARSER_H + +#include <QStack> +#include "symbols.h" + +QT_BEGIN_NAMESPACE + +class Parser +{ +public: + Parser():index(0), displayWarnings(true){} + Symbols symbols; + int index; + bool displayWarnings; + + QStack<QByteArray> currentFilenames; + + inline bool hasNext() const { return (index < symbols.size()); } + inline Token next() { if (index >= symbols.size()) return NOTOKEN; return symbols.at(index++).token; } + bool test(Token); + void next(Token); + void next(Token, const char *msg); + inline void prev() {--index;} + inline Token lookup(int k = 1); + inline const Symbol &symbol_lookup(int k = 1) { return symbols.at(index-1+k);} + inline Token token() { return symbols.at(index-1).token;} + inline QByteArray lexem() { return symbols.at(index-1).lexem();} + inline QByteArray unquotedLexem() { return symbols.at(index-1).unquotedLexem();} + inline const Symbol &symbol() { return symbols.at(index-1);} + + void error(int rollback); + void error(const char *msg = 0); + void warning(const char * = 0); + +}; + +inline bool Parser::test(Token token) +{ + if (index < symbols.size() && symbols.at(index).token == token) { + ++index; + return true; + } + return false; +} + +inline Token Parser::lookup(int k) +{ + const int l = index - 1 + k; + return l < symbols.size() ? symbols.at(l).token : NOTOKEN; +} + +inline void Parser::next(Token token) +{ + if (!test(token)) + error(); +} + +inline void Parser::next(Token token, const char *msg) +{ + if (!test(token)) + error(msg); +} + +QT_END_NAMESPACE + +#endif diff --git a/src/tools/moc/ppkeywords.cpp b/src/tools/moc/ppkeywords.cpp new file mode 100644 index 0000000..1e4f063 --- /dev/null +++ b/src/tools/moc/ppkeywords.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// auto generated +// DO NOT EDIT. + +static const short pp_keyword_trans[][128] = { + {0,0,0,0,0,0,0,0,0,98,12,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 98,76,96,13,0,60,62,97,9,10,58,56,11,57,102,59, + 6,6,6,6,6,6,6,6,6,6,92,0,7,81,8,91, + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,0,101,0,61,1, + 0,1,2,3,4,1,1,1,1,1,1,1,1,1,5,1, + 1,1,1,1,1,1,1,1,1,1,1,0,68,0,71,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,79,87,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,88,80,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,93,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,14,34,0,0,0,20,0,0,0,0,0,0, + 0,0,0,0,0,22,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,21,0,0,0,0,0,0,0,44,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,27,0,0,0,0,0,0,0,0,0,30,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,35,0,40,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0, + 0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,65,0,0,0,0,0,0,0,0,0,0,0,0,0,69, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 103,103,103,103,103,103,103,103,103,103,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} +}; + +static const struct +{ + PP_Token token; + short next; + char defchar; + short defnext; + PP_Token ident; +} pp_keywords[] = { + {PP_NOTOKEN, 0, 0, 0, PP_NOTOKEN}, + {PP_CHARACTER, 0, 0, 0, PP_NOTOKEN}, + {PP_CHARACTER, 0, 105, 63, PP_NOTOKEN}, + {PP_CHARACTER, 0, 111, 72, PP_NOTOKEN}, + {PP_CHARACTER, 0, 101, 50, PP_NOTOKEN}, + {PP_CHARACTER, 0, 111, 77, PP_NOTOKEN}, + {PP_DIGIT, 0, 0, 0, PP_NOTOKEN}, + {PP_LANGLE, 1, 0, 0, PP_NOTOKEN}, + {PP_RANGLE, 2, 0, 0, PP_NOTOKEN}, + {PP_LPAREN, 0, 0, 0, PP_NOTOKEN}, + {PP_RPAREN, 0, 0, 0, PP_NOTOKEN}, + {PP_COMMA, 0, 0, 0, PP_NOTOKEN}, + {PP_NEWLINE, 0, 0, 0, PP_NOTOKEN}, + {PP_HASH, 3, 0, 0, PP_HASH}, + {PP_HASH, 0, 101, 15, PP_HASH}, + {PP_HASH, 0, 102, 16, PP_HASH}, + {PP_HASH, 0, 105, 17, PP_HASH}, + {PP_HASH, 0, 110, 18, PP_HASH}, + {PP_HASH, 0, 101, 19, PP_HASH}, + {PP_DEFINE, 0, 0, 0, PP_HASH}, + {PP_HASH, 4, 0, 0, PP_HASH}, + {PP_IF, 5, 0, 0, PP_HASH}, + {PP_HASH, 0, 110, 23, PP_HASH}, + {PP_HASH, 0, 100, 24, PP_HASH}, + {PP_HASH, 0, 101, 25, PP_HASH}, + {PP_HASH, 0, 102, 26, PP_HASH}, + {PP_UNDEF, 0, 0, 0, PP_HASH}, + {PP_HASH, 0, 101, 28, PP_HASH}, + {PP_HASH, 0, 102, 29, PP_HASH}, + {PP_IFDEF, 0, 0, 0, PP_HASH}, + {PP_HASH, 0, 100, 31, PP_HASH}, + {PP_HASH, 0, 101, 32, PP_HASH}, + {PP_HASH, 0, 102, 33, PP_HASH}, + {PP_IFNDEF, 0, 0, 0, PP_HASH}, + {PP_HASH, 6, 0, 0, PP_HASH}, + {PP_HASH, 7, 0, 0, PP_HASH}, + {PP_HASH, 0, 102, 37, PP_HASH}, + {PP_ELIF, 0, 0, 0, PP_HASH}, + {PP_HASH, 0, 101, 39, PP_HASH}, + {PP_ELSE, 0, 0, 0, PP_HASH}, + {PP_HASH, 0, 100, 41, PP_HASH}, + {PP_HASH, 0, 105, 42, PP_HASH}, + {PP_HASH, 0, 102, 43, PP_HASH}, + {PP_ENDIF, 0, 0, 0, PP_HASH}, + {PP_HASH, 0, 99, 45, PP_HASH}, + {PP_HASH, 0, 108, 46, PP_HASH}, + {PP_HASH, 0, 117, 47, PP_HASH}, + {PP_HASH, 0, 100, 48, PP_HASH}, + {PP_HASH, 0, 101, 49, PP_HASH}, + {PP_INCLUDE, 0, 0, 0, PP_HASH}, + {PP_CHARACTER, 0, 102, 51, PP_CHARACTER}, + {PP_CHARACTER, 0, 105, 52, PP_CHARACTER}, + {PP_CHARACTER, 0, 110, 53, PP_CHARACTER}, + {PP_CHARACTER, 0, 101, 54, PP_CHARACTER}, + {PP_CHARACTER, 0, 100, 55, PP_CHARACTER}, + {PP_DEFINED, 0, 0, 0, PP_CHARACTER}, + {PP_PLUS, 0, 0, 0, PP_NOTOKEN}, + {PP_MINUS, 0, 0, 0, PP_NOTOKEN}, + {PP_STAR, 0, 0, 0, PP_NOTOKEN}, + {PP_SLASH, 8, 0, 0, PP_NOTOKEN}, + {PP_PERCENT, 0, 58, 94, PP_NOTOKEN}, + {PP_HAT, 0, 0, 0, PP_NOTOKEN}, + {PP_AND, 0, 38, 89, PP_NOTOKEN}, + {PP_CHARACTER, 0, 116, 64, PP_CHARACTER}, + {PP_CHARACTER, 9, 0, 0, PP_CHARACTER}, + {PP_CHARACTER, 0, 110, 66, PP_CHARACTER}, + {PP_CHARACTER, 0, 100, 67, PP_CHARACTER}, + {PP_AND, 0, 0, 0, PP_CHARACTER}, + {PP_OR, 0, 124, 90, PP_NOTOKEN}, + {PP_CHARACTER, 0, 114, 70, PP_CHARACTER}, + {PP_OR, 0, 0, 0, PP_CHARACTER}, + {PP_TILDE, 0, 0, 0, PP_NOTOKEN}, + {PP_CHARACTER, 0, 109, 73, PP_CHARACTER}, + {PP_CHARACTER, 0, 112, 74, PP_CHARACTER}, + {PP_CHARACTER, 0, 108, 75, PP_CHARACTER}, + {PP_TILDE, 0, 0, 0, PP_CHARACTER}, + {PP_NOT, 0, 61, 83, PP_NOTOKEN}, + {PP_CHARACTER, 0, 116, 78, PP_CHARACTER}, + {PP_NOT, 0, 95, 84, PP_CHARACTER}, + {PP_LTLT, 0, 0, 0, PP_NOTOKEN}, + {PP_GTGT, 0, 0, 0, PP_NOTOKEN}, + {PP_INCOMPLETE, 0, 61, 82, PP_NOTOKEN}, + {PP_EQEQ, 0, 0, 0, PP_NOTOKEN}, + {PP_NE, 0, 0, 0, PP_NOTOKEN}, + {PP_CHARACTER, 0, 101, 85, PP_CHARACTER}, + {PP_CHARACTER, 0, 113, 86, PP_CHARACTER}, + {PP_NE, 0, 0, 0, PP_CHARACTER}, + {PP_LE, 0, 0, 0, PP_NOTOKEN}, + {PP_GE, 0, 0, 0, PP_NOTOKEN}, + {PP_ANDAND, 0, 0, 0, PP_NOTOKEN}, + {PP_OROR, 0, 0, 0, PP_NOTOKEN}, + {PP_QUESTION, 0, 0, 0, PP_NOTOKEN}, + {PP_COLON, 0, 0, 0, PP_NOTOKEN}, + {PP_HASHHASH, 0, 0, 0, PP_NOTOKEN}, + {PP_INCOMPLETE, 0, 37, 95, PP_NOTOKEN}, + {PP_INCOMPLETE, 0, 58, 93, PP_NOTOKEN}, + {PP_QUOTE, 0, 0, 0, PP_NOTOKEN}, + {PP_SINGLEQUOTE, 0, 0, 0, PP_NOTOKEN}, + {PP_WHITESPACE, 0, 0, 0, PP_NOTOKEN}, + {PP_CPP_COMMENT, 0, 0, 0, PP_NOTOKEN}, + {PP_C_COMMENT, 0, 0, 0, PP_NOTOKEN}, + {PP_BACKSLASH, 0, 0, 0, PP_NOTOKEN}, + {PP_INCOMPLETE, 10, 0, 0, PP_NOTOKEN}, + {PP_FLOATING_LITERAL, 0, 0, 0, PP_NOTOKEN} +}; diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp new file mode 100644 index 0000000..d1703c8 --- /dev/null +++ b/src/tools/moc/preprocessor.cpp @@ -0,0 +1,983 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "preprocessor.h" +#include "utils.h" +#include <QStringList> +#include <QFile> +#include <QDir> +#include <QFileInfo> + +QT_BEGIN_NAMESPACE + +#include "ppkeywords.cpp" +#include "keywords.cpp" + +// transform \r\n into \n +// \r into \n (os9 style) +// backslash-newlines into newlines +static QByteArray cleaned(const QByteArray &input) +{ + QByteArray result; + result.reserve(input.size()); + const char *data = input; + char *output = result.data(); + + int newlines = 0; + while (*data) { + while (*data && is_space(*data)) + ++data; + bool takeLine = (*data == '#'); + if (*data == '%' && *(data+1) == ':') { + takeLine = true; + ++data; + } + if (takeLine) { + *output = '#'; + ++output; + do ++data; while (*data && is_space(*data)); + } + while (*data) { + // handle \\\n, \\\r\n and \\\r + if (*data == '\\') { + if (*(data + 1) == '\r') { + ++data; + } + if (*data && (*(data + 1) == '\n' || (*data) == '\r')) { + ++newlines; + data += 1; + if (*data != '\r') + data += 1; + continue; + } + } else if (*data == '\r' && *(data + 1) == '\n') { // reduce \r\n to \n + ++data; + } + + char ch = *data; + if (ch == '\r') // os9: replace \r with \n + ch = '\n'; + *output = ch; + ++output; + + if (*data == '\n') { + // output additional newlines to keep the correct line-numbering + // for the lines following the backslash-newline sequence(s) + while (newlines) { + *output = '\n'; + ++output; + --newlines; + } + ++data; + break; + } + ++data; + } + } + result.resize(output - result.constData()); + return result; +} + +bool Preprocessor::preprocessOnly = false; +void Preprocessor::skipUntilEndif() +{ + while(index < symbols.size() - 1 && symbols.at(index).token != PP_ENDIF){ + switch (symbols.at(index).token) { + case PP_IF: + case PP_IFDEF: + case PP_IFNDEF: + ++index; + skipUntilEndif(); + break; + default: + ; + } + ++index; + } +} + +bool Preprocessor::skipBranch() +{ + while (index < symbols.size() - 1 + && (symbols.at(index).token != PP_ENDIF + && symbols.at(index).token != PP_ELIF + && symbols.at(index).token != PP_ELSE) + ){ + switch (symbols.at(index).token) { + case PP_IF: + case PP_IFDEF: + case PP_IFNDEF: + ++index; + skipUntilEndif(); + break; + default: + ; + } + ++index; + } + return (index < symbols.size() - 1); +} + + +enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude }; +static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeCpp) +{ + Symbols symbols; + const char *begin = input; + const char *data = begin; + while (*data) { + if (mode == TokenizeCpp) { + int column = 0; + + const char *lexem = data; + int state = 0; + Token token = NOTOKEN; + for (;;) { + if (static_cast<signed char>(*data) < 0) { + ++data; + continue; + } + int nextindex = keywords[state].next; + int next = 0; + if (*data == keywords[state].defchar) + next = keywords[state].defnext; + else if (!state || nextindex) + next = keyword_trans[nextindex][(int)*data]; + if (!next) + break; + state = next; + token = keywords[state].token; + ++data; + } + + // suboptimal, is_ident_char should use a table + if (keywords[state].ident && is_ident_char(*data)) + token = keywords[state].ident; + + if (token == NOTOKEN) { + // an error really + ++data; + continue; + } + + ++column; + + if (token > SPECIAL_TREATMENT_MARK) { + switch (token) { + case QUOTE: + data = skipQuote(data); + token = STRING_LITERAL; + // concatenate multi-line strings for easier + // STRING_LITERAAL handling in moc + if (!Preprocessor::preprocessOnly + && !symbols.isEmpty() + && symbols.last().token == STRING_LITERAL) { + + QByteArray newString = symbols.last().unquotedLexem(); + newString += input.mid(lexem - begin + 1, data - lexem - 2); + newString.prepend('\"'); + newString.append('\"'); + symbols.last() = Symbol(symbols.last().lineNum, + STRING_LITERAL, + newString); + continue; + } + break; + case SINGLEQUOTE: + while (*data && (*data != '\'' + || (*(data-1)=='\\' + && *(data-2)!='\\'))) + ++data; + if (*data) + ++data; + token = CHARACTER_LITERAL; + break; + case LANGLE_SCOPE: + // split <:: into two tokens, < and :: + token = LANGLE; + data -= 2; + break; + case DIGIT: + while (is_digit_char(*data)) + ++data; + if (!*data || *data != '.') { + token = INTEGER_LITERAL; + if (data - lexem == 1 && + (*data == 'x' || *data == 'X') + && *lexem == '0') { + ++data; + while (is_hex_char(*data)) + ++data; + } + break; + } + token = FLOATING_LITERAL; + ++data; + // fall through + case FLOATING_LITERAL: + while (is_digit_char(*data)) + ++data; + if (*data == '+' || *data == '-') + ++data; + if (*data == 'e' || *data == 'E') { + ++data; + while (is_digit_char(*data)) + ++data; + } + if (*data == 'f' || *data == 'F' + || *data == 'l' || *data == 'L') + ++data; + break; + case HASH: + if (column == 1) { + mode = PreparePreprocessorStatement; + while (*data && (*data == ' ' || *data == '\t')) + ++data; + if (is_ident_char(*data)) + mode = TokenizePreprocessorStatement; + continue; + } + break; + case NEWLINE: + ++lineNum; + continue; + case BACKSLASH: + { + const char *rewind = data; + while (*data && (*data == ' ' || *data == '\t')) + ++data; + if (*data && *data == '\n') { + ++data; + continue; + } + data = rewind; + } break; + case CHARACTER: + while (is_ident_char(*data)) + ++data; + token = IDENTIFIER; + break; + case C_COMMENT: + if (*data) { + if (*data == '\n') + ++lineNum; + ++data; + if (*data) { + if (*data == '\n') + ++lineNum; + ++data; + } + } + while (*data && (*(data-1) != '/' || *(data-2) != '*')) { + if (*data == '\n') + ++lineNum; + ++data; + } + token = WHITESPACE; // one comment, one whitespace + // fall through; + case WHITESPACE: + if (column == 1) + column = 0; + while (*data && (*data == ' ' || *data == '\t')) + ++data; + if (Preprocessor::preprocessOnly) // tokenize whitespace + break; + continue; + case CPP_COMMENT: + while (*data && *data != '\n') + ++data; + continue; // ignore safely, the newline is a separator + default: + continue; //ignore + } + } +#ifdef USE_LEXEM_STORE + if (!Preprocessor::preprocessOnly + && token != IDENTIFIER + && token != STRING_LITERAL + && token != FLOATING_LITERAL + && token != INTEGER_LITERAL) + symbols += Symbol(lineNum, token); + else +#endif + symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem); + + } else { // Preprocessor + + const char *lexem = data; + int state = 0; + Token token = NOTOKEN; + if (mode == TokenizePreprocessorStatement) { + state = pp_keyword_trans[0][(int)'#']; + mode = TokenizePreprocessor; + } + for (;;) { + if (static_cast<signed char>(*data) < 0) { + ++data; + continue; + } + + int nextindex = pp_keywords[state].next; + int next = 0; + if (*data == pp_keywords[state].defchar) + next = pp_keywords[state].defnext; + else if (!state || nextindex) + next = pp_keyword_trans[nextindex][(int)*data]; + if (!next) + break; + state = next; + token = pp_keywords[state].token; + ++data; + } + // suboptimal, is_ident_char should use a table + if (pp_keywords[state].ident && is_ident_char(*data)) + token = pp_keywords[state].ident; + + switch (token) { + case NOTOKEN: + ++data; + break; + case PP_IFDEF: + symbols += Symbol(lineNum, PP_IF); + symbols += Symbol(lineNum, PP_DEFINED); + continue; + case PP_IFNDEF: + symbols += Symbol(lineNum, PP_IF); + symbols += Symbol(lineNum, PP_NOT); + symbols += Symbol(lineNum, PP_DEFINED); + continue; + case PP_INCLUDE: + mode = TokenizeInclude; + break; + case PP_QUOTE: + data = skipQuote(data); + token = PP_STRING_LITERAL; + break; + case PP_SINGLEQUOTE: + while (*data && (*data != '\'' + || (*(data-1)=='\\' + && *(data-2)!='\\'))) + ++data; + if (*data) + ++data; + token = PP_CHARACTER_LITERAL; + break; + case PP_DIGIT: + while (is_digit_char(*data)) + ++data; + if (!*data || *data != '.') { + token = PP_INTEGER_LITERAL; + if (data - lexem == 1 && + (*data == 'x' || *data == 'X') + && *lexem == '0') { + ++data; + while (is_hex_char(*data)) + ++data; + } + break; + } + token = PP_FLOATING_LITERAL; + ++data; + // fall through + case PP_FLOATING_LITERAL: + while (is_digit_char(*data)) + ++data; + if (*data == '+' || *data == '-') + ++data; + if (*data == 'e' || *data == 'E') { + ++data; + while (is_digit_char(*data)) + ++data; + } + if (*data == 'f' || *data == 'F' + || *data == 'l' || *data == 'L') + ++data; + break; + case PP_CHARACTER: + if (mode == PreparePreprocessorStatement) { + // rewind entire token to begin + data = lexem; + mode = TokenizePreprocessorStatement; + continue; + } + while (is_ident_char(*data)) + ++data; + token = PP_IDENTIFIER; + break; + case PP_C_COMMENT: + if (*data) { + if (*data == '\n') + ++lineNum; + ++data; + if (*data) { + if (*data == '\n') + ++lineNum; + ++data; + } + } + while (*data && (*(data-1) != '/' || *(data-2) != '*')) { + if (*data == '\n') + ++lineNum; + ++data; + } + token = PP_WHITESPACE; // one comment, one whitespace + // fall through; + case PP_WHITESPACE: + while (*data && (*data == ' ' || *data == '\t')) + ++data; + continue; // the preprocessor needs no whitespace + case PP_CPP_COMMENT: + while (*data && *data != '\n') + ++data; + continue; // ignore safely, the newline is a separator + case PP_NEWLINE: + ++lineNum; + mode = TokenizeCpp; + break; + case PP_BACKSLASH: + { + const char *rewind = data; + while (*data && (*data == ' ' || *data == '\t')) + ++data; + if (*data && *data == '\n') { + ++data; + continue; + } + data = rewind; + } break; + case PP_LANGLE: + if (mode != TokenizeInclude) + break; + token = PP_STRING_LITERAL; + while (*data && *data != '\n' && *(data-1) != '>') + ++data; + break; + default: + break; + } + if (mode == PreparePreprocessorStatement) + continue; +#ifdef USE_LEXEM_STORE + if (token != PP_IDENTIFIER + && token != PP_STRING_LITERAL + && token != PP_FLOATING_LITERAL + && token != PP_INTEGER_LITERAL) + symbols += Symbol(lineNum, token); + else +#endif + symbols += Symbol(lineNum, token, input, lexem-begin, data-lexem); + } + } + symbols += Symbol(); // eof symbol + return symbols; +} + +void Preprocessor::substituteMacro(const MacroName ¯o, Symbols &substituted, MacroSafeSet safeset) +{ + Symbols saveSymbols = symbols; + int saveIndex = index; + + // This is a workaround for a compiler bug that did not like the QHash::value function that + // simply did: "return T();" This code should essentially do the same thing but declares the + // default instance outside and calls the other QHash::value() implementation that returns + // 'dummy' as the default value now. + Macro dummy; + symbols = macros.value(macro, dummy).symbols; + index = 0; + + safeset += macro; + substituteUntilNewline(substituted, safeset); + + symbols = saveSymbols; + index = saveIndex; +} + + + +void Preprocessor::substituteUntilNewline(Symbols &substituted, MacroSafeSet safeset) +{ + while (hasNext()) { + Token token = next(); + if (token == PP_IDENTIFIER) { + MacroName macro = symbol(); + if (macros.contains(macro) && !safeset.contains(macro)) { + substituteMacro(macro, substituted, safeset); + continue; + } + } else if (token == PP_DEFINED) { + test(PP_LPAREN); + next(PP_IDENTIFIER); + Symbol definedOrNotDefined = symbol(); + definedOrNotDefined.token = macros.contains(definedOrNotDefined)? PP_MOC_TRUE : PP_MOC_FALSE; + substituted += definedOrNotDefined; + test(PP_RPAREN); + continue; + } else if (token == PP_NEWLINE) { + substituted += symbol(); + break; + } + substituted += symbol(); + } +} + + +class PP_Expression : public Parser +{ +public: + int value() { index = 0; return unary_expression_lookup() ? conditional_expression() : 0; } + + int conditional_expression(); + int logical_OR_expression(); + int logical_AND_expression(); + int inclusive_OR_expression(); + int exclusive_OR_expression(); + int AND_expression(); + int equality_expression(); + int relational_expression(); + int shift_expression(); + int additive_expression(); + int multiplicative_expression(); + int unary_expression(); + bool unary_expression_lookup(); + int primary_expression(); + bool primary_expression_lookup(); +}; + +int PP_Expression::conditional_expression() +{ + int value = logical_OR_expression(); + if (test(PP_QUESTION)) { + int alt1 = conditional_expression(); + int alt2 = test(PP_COLON) ? conditional_expression() : 0; + return value ? alt1 : alt2; + } + return value; +} + +int PP_Expression::logical_OR_expression() +{ + int value = logical_AND_expression(); + if (test(PP_OROR)) + return logical_OR_expression() || value; + return value; +} + +int PP_Expression::logical_AND_expression() +{ + int value = inclusive_OR_expression(); + if (test(PP_ANDAND)) + return logical_AND_expression() && value; + return value; +} + +int PP_Expression::inclusive_OR_expression() +{ + int value = exclusive_OR_expression(); + if (test(PP_OR)) + return value | inclusive_OR_expression(); + return value; +} + +int PP_Expression::exclusive_OR_expression() +{ + int value = AND_expression(); + if (test(PP_HAT)) + return value ^ exclusive_OR_expression(); + return value; +} + +int PP_Expression::AND_expression() +{ + int value = equality_expression(); + if (test(PP_AND)) + return value & AND_expression(); + return value; +} + +int PP_Expression::equality_expression() +{ + int value = relational_expression(); + switch (next()) { + case PP_EQEQ: + return value == equality_expression(); + case PP_NE: + return value != equality_expression(); + default: + prev(); + return value; + } +} + +int PP_Expression::relational_expression() +{ + int value = shift_expression(); + switch (next()) { + case PP_LANGLE: + return value < relational_expression(); + case PP_RANGLE: + return value > relational_expression(); + case PP_LE: + return value <= relational_expression(); + case PP_GE: + return value >= relational_expression(); + default: + prev(); + return value; + } +} + +int PP_Expression::shift_expression() +{ + int value = additive_expression(); + switch (next()) { + case PP_LTLT: + return value << shift_expression(); + case PP_GTGT: + return value >> shift_expression(); + default: + prev(); + return value; + } +} + +int PP_Expression::additive_expression() +{ + int value = multiplicative_expression(); + switch (next()) { + case PP_PLUS: + return value + additive_expression(); + case PP_MINUS: + return value - additive_expression(); + default: + prev(); + return value; + } +} + +int PP_Expression::multiplicative_expression() +{ + int value = unary_expression(); + switch (next()) { + case PP_STAR: + return value * multiplicative_expression(); + case PP_PERCENT: + { + int remainder = multiplicative_expression(); + return remainder ? value % remainder : 0; + } + case PP_SLASH: + { + int div = multiplicative_expression(); + return div ? value / div : 0; + } + default: + prev(); + return value; + }; +} + +int PP_Expression::unary_expression() +{ + switch (next()) { + case PP_PLUS: + return unary_expression(); + case PP_MINUS: + return -unary_expression(); + case PP_NOT: + return !unary_expression(); + case PP_TILDE: + return ~unary_expression(); + case PP_MOC_TRUE: + return 1; + case PP_MOC_FALSE: + return 0; + default: + prev(); + return primary_expression(); + } +} + +bool PP_Expression::unary_expression_lookup() +{ + Token t = lookup(); + return (primary_expression_lookup() + || t == PP_PLUS + || t == PP_MINUS + || t == PP_NOT + || t == PP_TILDE + || t == PP_DEFINED); +} + +int PP_Expression::primary_expression() +{ + int value; + if (test(PP_LPAREN)) { + value = conditional_expression(); + test(PP_RPAREN); + } else { + next(); + value = lexem().toInt(0, 0); + } + return value; +} + +bool PP_Expression::primary_expression_lookup() +{ + Token t = lookup(); + return (t == PP_IDENTIFIER + || t == PP_INTEGER_LITERAL + || t == PP_FLOATING_LITERAL + || t == PP_MOC_TRUE + || t == PP_MOC_FALSE + || t == PP_LPAREN); +} + +int Preprocessor::evaluateCondition() +{ + PP_Expression expression; + expression.currentFilenames = currentFilenames; + + substituteUntilNewline(expression.symbols); + + return expression.value(); +} + +void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed) +{ + currentFilenames.push(filename); + preprocessed.reserve(preprocessed.size() + symbols.size()); + while (hasNext()) { + Token token = next(); + + switch (token) { + case PP_INCLUDE: + { + int lineNum = symbol().lineNum; + QByteArray include; + bool local = false; + if (test(PP_STRING_LITERAL)) { + local = lexem().startsWith('\"'); + include = unquotedLexem(); + } else + continue; + until(PP_NEWLINE); + + // #### stringery + QFileInfo fi; + if (local) + fi.setFile(QFileInfo(QString::fromLocal8Bit(filename)).dir(), QString::fromLocal8Bit(include)); + for (int j = 0; j < Preprocessor::includes.size() && !fi.exists(); ++j) { + const IncludePath &p = Preprocessor::includes.at(j); + if (p.isFrameworkPath) { + const int slashPos = include.indexOf('/'); + if (slashPos == -1) + continue; + QByteArray frameworkCandidate = include.left(slashPos); + frameworkCandidate.append(".framework/Headers/"); + fi.setFile(QString::fromLocal8Bit(p.path + "/" + frameworkCandidate), QString::fromLocal8Bit(include.mid(slashPos + 1))); + } else { + fi.setFile(QString::fromLocal8Bit(p.path), QString::fromLocal8Bit(include)); + } + // try again, maybe there's a file later in the include paths with the same name + // (186067) + if (fi.isDir()) { + fi = QFileInfo(); + continue; + } + } + + if (!fi.exists() || fi.isDir()) + continue; + include = fi.canonicalFilePath().toLocal8Bit(); + + if (Preprocessor::preprocessedIncludes.contains(include)) + continue; + Preprocessor::preprocessedIncludes.insert(include); + + QFile file(QString::fromLocal8Bit(include)); + if (!file.open(QFile::ReadOnly)) + continue; + + QByteArray input = file.readAll(); + file.close(); + if (input.isEmpty()) + continue; + + Symbols saveSymbols = symbols; + int saveIndex = index; + + // phase 1: get rid of backslash-newlines + input = cleaned(input); + + // phase 2: tokenize for the preprocessor + symbols = tokenize(input); + input.clear(); + + index = 0; + + // phase 3: preprocess conditions and substitute macros + preprocessed += Symbol(0, MOC_INCLUDE_BEGIN, include); + preprocess(include, preprocessed); + preprocessed += Symbol(lineNum, MOC_INCLUDE_END, include); + + symbols = saveSymbols; + index = saveIndex; + continue; + } + case PP_DEFINE: + { + next(IDENTIFIER); + QByteArray name = lexem(); + int start = index; + until(PP_NEWLINE); + Macro macro; + macro.symbols.reserve(index - start - 1); + for (int i = start; i < index - 1; ++i) + macro.symbols += symbols.at(i); + macros.insert(name, macro); + continue; + } + case PP_UNDEF: { + next(IDENTIFIER); + QByteArray name = lexem(); + until(PP_NEWLINE); + macros.remove(name); + continue; + } + case PP_IDENTIFIER: + { +// if (macros.contains(symbol())) +// ; + } + // we _could_ easily substitute macros by the following + // four lines, but we choose not to. + /* + if (macros.contains(sym.lexem())) { + preprocessed += substitute(macros, symbols, i); + continue; + } + */ + break; + case PP_HASH: + until(PP_NEWLINE); + continue; // skip unknown preprocessor statement + case PP_IFDEF: + case PP_IFNDEF: + case PP_IF: + while (!evaluateCondition()) { + if (!skipBranch()) + break; + if (test(PP_ELIF)) { + } else { + until(PP_NEWLINE); + break; + } + } + continue; + case PP_ELIF: + case PP_ELSE: + skipUntilEndif(); + // fall through + case PP_ENDIF: + until(PP_NEWLINE); + continue; + case SIGNALS: + case SLOTS: { + Symbol sym = symbol(); + if (macros.contains("QT_NO_KEYWORDS")) + sym.token = IDENTIFIER; + else + sym.token = (token == SIGNALS ? Q_SIGNALS_TOKEN : Q_SLOTS_TOKEN); + preprocessed += sym; + } continue; + default: + break; + } + preprocessed += symbol(); + } + + currentFilenames.pop(); +} + +Symbols Preprocessor::preprocessed(const QByteArray &filename, FILE *file) +{ + QFile qfile; + qfile.open(file, QFile::ReadOnly); + QByteArray input = qfile.readAll(); + if (input.isEmpty()) + return symbols; + + // phase 1: get rid of backslash-newlines + input = cleaned(input); + + // phase 2: tokenize for the preprocessor + symbols = tokenize(input); + +#if 0 + for (int j = 0; j < symbols.size(); ++j) + fprintf(stderr, "line %d: %s(%s)\n", + symbols[j].lineNum, + symbols[j].lexem().constData(), + tokenTypeName(symbols[j].token)); +#endif + + // phase 3: preprocess conditions and substitute macros + Symbols result; + preprocess(filename, result); + +#if 0 + for (int j = 0; j < result.size(); ++j) + fprintf(stderr, "line %d: %s(%s)\n", + result[j].lineNum, + result[j].lexem().constData(), + tokenTypeName(result[j].token)); +#endif + + return result; +} + +void Preprocessor::until(Token t) +{ + while(hasNext() && next() != t) + ; +} + +QT_END_NAMESPACE diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h new file mode 100644 index 0000000..cb713d2 --- /dev/null +++ b/src/tools/moc/preprocessor.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PREPROCESSOR_H +#define PREPROCESSOR_H + +#include "parser.h" +#include <QList> +#include <QSet> +#include <stdio.h> + +QT_BEGIN_NAMESPACE + +struct Macro +{ + Symbols symbols; +}; + +#ifdef USE_LEXEM_STORE +typedef QByteArray MacroName; +#else +typedef SubArray MacroName; +#endif +typedef QHash<MacroName, Macro> Macros; +typedef QVector<MacroName> MacroSafeSet; + + +class Preprocessor : public Parser +{ +public: + Preprocessor(){} + static bool preprocessOnly; + struct IncludePath + { + inline explicit IncludePath(const QByteArray &_path) + : path(_path), isFrameworkPath(false) {} + QByteArray path; + bool isFrameworkPath; + }; + QList<IncludePath> includes; + QList<QByteArray> frameworks; + QSet<QByteArray> preprocessedIncludes; + Macros macros; + Symbols preprocessed(const QByteArray &filename, FILE *file); + + + void skipUntilEndif(); + bool skipBranch(); + + void substituteMacro(const MacroName ¯o, Symbols &substituted, MacroSafeSet safeset = MacroSafeSet()); + void substituteUntilNewline(Symbols &substituted, MacroSafeSet safeset = MacroSafeSet()); + + int evaluateCondition(); + + +private: + void until(Token); + + void preprocess(const QByteArray &filename, Symbols &preprocessed); +}; + +QT_END_NAMESPACE + +#endif // PREPROCESSOR_H diff --git a/src/tools/moc/symbols.h b/src/tools/moc/symbols.h new file mode 100644 index 0000000..b8ccf78 --- /dev/null +++ b/src/tools/moc/symbols.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SYMBOLS_H +#define SYMBOLS_H + +#include "token.h" +#include <QString> +#include <QHash> +#include <QVector> +#include <QDebug> + +QT_BEGIN_NAMESPACE + +//#define USE_LEXEM_STORE + +struct SubArray +{ + inline SubArray():from(0),len(-1){} + inline SubArray(const QByteArray &a):array(a),from(0), len(a.size()){} + inline SubArray(const char *s):array(s),from(0) { len = array.size(); } + inline SubArray(const QByteArray &a, int from, int len):array(a), from(from), len(len){} + QByteArray array; + int from, len; + inline bool operator==(const SubArray &other) const { + if (len != other.len) + return false; + for (int i = 0; i < len; ++i) + if (array.at(from + i) != other.array.at(other.from + i)) + return false; + return true; + } +}; + +inline uint qHash(const SubArray &key) +{ + const uchar *p = reinterpret_cast<const uchar *>(key.array.data() + key.from); + int n = key.len; + uint h = 0; + uint g; + + while (n--) { + h = (h << 4) + *p++; + if ((g = (h & 0xf0000000)) != 0) + h ^= g >> 23; + h &= ~g; + } + return h; +} + + +struct Symbol +{ + +#ifdef USE_LEXEM_STORE + typedef QHash<SubArray, QHashDummyValue> LexemStore; + static LexemStore lexemStore; + + inline Symbol() : lineNum(-1),token(NOTOKEN){} + inline Symbol(int lineNum, Token token): + lineNum(lineNum), token(token){} + inline Symbol(int lineNum, Token token, const QByteArray &lexem): + lineNum(lineNum), token(token),lex(lexem){} + inline Symbol(int lineNum, Token token, const QByteArray &lexem, int from, int len): + lineNum(lineNum), token(token){ + LexemStore::const_iterator it = lexemStore.constFind(SubArray(lexem, from, len)); + + if (it != lexemStore.constEnd()) { + lex = it.key().array; + } else { + lex = lexem.mid(from, len); + lexemStore.insert(lex, QHashDummyValue()); + } + } + int lineNum; + Token token; + inline QByteArray unquotedLexem() const { return lex.mid(1, lex.length()-2); } + inline QByteArray lexem() const { return lex; } + inline operator QByteArray() const { return lex; } + QByteArray lex; + +#else + + inline Symbol() : lineNum(-1),token(NOTOKEN), from(0),len(-1) {} + inline Symbol(int lineNum, Token token): + lineNum(lineNum), token(token), from(0), len(-1) {} + inline Symbol(int lineNum, Token token, const QByteArray &lexem): + lineNum(lineNum), token(token), lex(lexem), from(0) { len = lex.size(); } + inline Symbol(int lineNum, Token token, const QByteArray &lexem, int from, int len): + lineNum(lineNum), token(token),lex(lexem),from(from), len(len){} + int lineNum; + Token token; + inline QByteArray lexem() const { return lex.mid(from, len); } + inline QByteArray unquotedLexem() const { return lex.mid(from+1, len-2); } + inline operator QByteArray() const { return lex.mid(from, len); } + inline operator SubArray() const { return SubArray(lex, from, len); } + QByteArray lex; + int from, len; + +#endif +}; +Q_DECLARE_TYPEINFO(Symbol, Q_MOVABLE_TYPE); + + +typedef QVector<Symbol> Symbols; + +QT_END_NAMESPACE + +#endif // SYMBOLS_H diff --git a/src/tools/moc/token.cpp b/src/tools/moc/token.cpp new file mode 100644 index 0000000..46345e7 --- /dev/null +++ b/src/tools/moc/token.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "token.h" + +QT_BEGIN_NAMESPACE + +#if defined(DEBUG_MOC) +const char *tokenTypeName(Token t) +{ + switch (t) { + case NOTOKEN: return "NOTOKEN"; + case IDENTIFIER: return "IDENTIFIER"; + case INTEGER_LITERAL: return "INTEGER_LITERAL"; + case CHARACTER_LITERAL: return "CHARACTER_LITERAL"; + case STRING_LITERAL: return "STRING_LITERAL"; + case BOOLEAN_LITERAL: return "BOOLEAN_LITERAL"; + case HEADER_NAME: return "HEADER_NAME"; + case LANGLE: return "LANGLE"; + case RANGLE: return "RANGLE"; + case LPAREN: return "LPAREN"; + case RPAREN: return "RPAREN"; + case ELIPSIS: return "ELIPSIS"; + case LBRACK: return "LBRACK"; + case RBRACK: return "RBRACK"; + case LBRACE: return "LBRACE"; + case RBRACE: return "RBRACE"; + case EQ: return "EQ"; + case SCOPE: return "SCOPE"; + case SEMIC: return "SEMIC"; + case COLON: return "COLON"; + case DOTSTAR: return "DOTSTAR"; + case QUESTION: return "QUESTION"; + case DOT: return "DOT"; + case DYNAMIC_CAST: return "DYNAMIC_CAST"; + case STATIC_CAST: return "STATIC_CAST"; + case REINTERPRET_CAST: return "REINTERPRET_CAST"; + case CONST_CAST: return "CONST_CAST"; + case TYPEID: return "TYPEID"; + case THIS: return "THIS"; + case TEMPLATE: return "TEMPLATE"; + case THROW: return "THROW"; + case TRY: return "TRY"; + case CATCH: return "CATCH"; + case TYPEDEF: return "TYPEDEF"; + case FRIEND: return "FRIEND"; + case CLASS: return "CLASS"; + case NAMESPACE: return "NAMESPACE"; + case ENUM: return "ENUM"; + case STRUCT: return "STRUCT"; + case UNION: return "UNION"; + case VIRTUAL: return "VIRTUAL"; + case PRIVATE: return "PRIVATE"; + case PROTECTED: return "PROTECTED"; + case PUBLIC: return "PUBLIC"; + case EXPORT: return "EXPORT"; + case AUTO: return "AUTO"; + case REGISTER: return "REGISTER"; + case EXTERN: return "EXTERN"; + case MUTABLE: return "MUTABLE"; + case ASM: return "ASM"; + case USING: return "USING"; + case INLINE: return "INLINE"; + case EXPLICIT: return "EXPLICIT"; + case STATIC: return "STATIC"; + case CONST: return "CONST"; + case VOLATILE: return "VOLATILE"; + case OPERATOR: return "OPERATOR"; + case SIZEOF: return "SIZEOF"; + case NEW: return "NEW"; + case DELETE: return "DELETE"; + case PLUS: return "PLUS"; + case MINUS: return "MINUS"; + case STAR: return "STAR"; + case SLASH: return "SLASH"; + case PERCENT: return "PERCENT"; + case HAT: return "HAT"; + case AND: return "AND"; + case OR: return "OR"; + case TILDE: return "TILDE"; + case NOT: return "NOT"; + case PLUS_EQ: return "PLUS_EQ"; + case MINUS_EQ: return "MINUS_EQ"; + case STAR_EQ: return "STAR_EQ"; + case SLASH_EQ: return "SLASH_EQ"; + case PERCENT_EQ: return "PERCENT_EQ"; + case HAT_EQ: return "HAT_EQ"; + case AND_EQ: return "AND_EQ"; + case OR_EQ: return "OR_EQ"; + case LTLT: return "LTLT"; + case GTGT: return "GTGT"; + case GTGT_EQ: return "GTGT_EQ"; + case LTLT_EQ: return "LTLT_EQ"; + case EQEQ: return "EQEQ"; + case NE: return "NE"; + case LE: return "LE"; + case GE: return "GE"; + case ANDAND: return "ANDAND"; + case OROR: return "OROR"; + case INCR: return "INCR"; + case DECR: return "DECR"; + case COMMA: return "COMMA"; + case ARROW_STAR: return "ARROW_STAR"; + case ARROW: return "ARROW"; + case CHAR: return "CHAR"; + case WCHAR: return "WCHAR"; + case BOOL: return "BOOL"; + case SHORT: return "SHORT"; + case INT: return "INT"; + case LONG: return "LONG"; + case SIGNED: return "SIGNED"; + case UNSIGNED: return "UNSIGNED"; + case FLOAT: return "FLOAT"; + case DOUBLE: return "DOUBLE"; + case VOID: return "VOID"; + case CASE: return "CASE"; + case DEFAULT: return "DEFAULT"; + case IF: return "IF"; + case ELSE: return "ELSE"; + case SWITCH: return "SWITCH"; + case WHILE: return "WHILE"; + case DO: return "DO"; + case FOR: return "FOR"; + case BREAK: return "BREAK"; + case CONTINUE: return "CONTINUE"; + case GOTO: return "GOTO"; + case SIGNALS: return "SIGNALS"; + case SLOTS: return "SLOTS"; + case RETURN: return "RETURN"; + case Q_OBJECT_TOKEN: return "Q_OBJECT_TOKEN"; + case Q_GADGET_TOKEN: return "Q_GADGET_TOKEN"; + case Q_PROPERTY_TOKEN: return "Q_PROPERTY_TOKEN"; + case Q_ENUMS_TOKEN: return "Q_ENUMS_TOKEN"; + case Q_FLAGS_TOKEN: return "Q_FLAGS_TOKEN"; + case Q_DECLARE_FLAGS_TOKEN: return "Q_DECLARE_FLAGS_TOKEN"; + case Q_DECLARE_INTERFACE_TOKEN: return "Q_DECLARE_INTERFACE_TOKEN"; + case Q_CLASSINFO_TOKEN: return "Q_CLASSINFO_TOKEN"; + case Q_INTERFACES_TOKEN: return "Q_INTERFACES_TOKEN"; + case Q_SIGNALS_TOKEN: return "Q_SIGNALS_TOKEN"; + case Q_SLOTS_TOKEN: return "Q_SLOTS_TOKEN"; + case Q_SIGNAL_TOKEN: return "Q_SIGNAL_TOKEN"; + case Q_SLOT_TOKEN: return "Q_SLOT_TOKEN"; + case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN"; + case SPECIAL_TREATMENT_MARK: return "SPECIAL_TREATMENT_MARK"; + case MOC_INCLUDE_BEGIN: return "MOC_INCLUDE_BEGIN"; + case MOC_INCLUDE_END: return "MOC_INCLUDE_END"; + case CPP_COMMENT: return "CPP_COMMENT"; + case C_COMMENT: return "C_COMMENT"; + case FLOATING_LITERAL: return "FLOATING_LITERAL"; + case HASH: return "HASH"; + case QUOTE: return "QUOTE"; + case SINGLEQUOTE: return "SINGLEQUOTE"; + case DIGIT: return "DIGIT"; + case CHARACTER: return "CHARACTER"; + case NEWLINE: return "NEWLINE"; + case WHITESPACE: return "WHITESPACE"; + case BACKSLASH: return "BACKSLASH"; + case INCOMPLETE: return "INCOMPLETE"; + case PP_DEFINE: return "PP_DEFINE"; + case PP_UNDEF: return "PP_UNDEF"; + case PP_IF: return "PP_IF"; + case PP_IFDEF: return "PP_IFDEF"; + case PP_IFNDEF: return "PP_IFNDEF"; + case PP_ELIF: return "PP_ELIF"; + case PP_ELSE: return "PP_ELSE"; + case PP_ENDIF: return "PP_ENDIF"; + case PP_INCLUDE: return "PP_INCLUDE"; + case PP_HASHHASH: return "PP_HASHHASH"; + case PP_HASH: return "PP_HASH"; + case PP_DEFINED: return "PP_DEFINED"; + case PP_INCOMPLETE: return "PP_INCOMPLETE"; + case PP_MOC_TRUE: return "PP_MOC_TRUE"; + case PP_MOC_FALSE: return "PP_MOC_FALSE"; + case Q_DECLARE_METATYPE_TOKEN: return "Q_DECLARE_METATYPE_TOKEN"; + case Q_MOC_COMPAT_TOKEN: return "Q_MOC_COMPAT_TOKEN"; + case Q_QT3_SUPPORT_TOKEN: return "Q_QT3_SUPPORT_TOKEN"; + case Q_INVOKABLE_TOKEN: return "Q_INVOKABLE_TOKEN"; + case Q_SCRIPTABLE_TOKEN: return "Q_SCRIPTABLE_TOKEN"; + } + return ""; +} +#endif + +QT_END_NAMESPACE diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h new file mode 100644 index 0000000..13c9a1d --- /dev/null +++ b/src/tools/moc/token.h @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TOKEN_H +#define TOKEN_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +enum Token { + NOTOKEN, + IDENTIFIER, + INTEGER_LITERAL, + CHARACTER_LITERAL, + STRING_LITERAL, + BOOLEAN_LITERAL, + HEADER_NAME, + LANGLE, + RANGLE, + LPAREN, + RPAREN, + ELIPSIS, + LBRACK, + RBRACK, + LBRACE, + RBRACE, + EQ, + SCOPE, + SEMIC, + COLON, + DOTSTAR, + QUESTION, + DOT, + DYNAMIC_CAST, + STATIC_CAST, + REINTERPRET_CAST, + CONST_CAST, + TYPEID, + THIS, + TEMPLATE, + THROW, + TRY, + CATCH, + TYPEDEF, + FRIEND, + CLASS, + NAMESPACE, + ENUM, + STRUCT, + UNION, + VIRTUAL, + PRIVATE, + PROTECTED, + PUBLIC, + EXPORT, + AUTO, + REGISTER, + EXTERN, + MUTABLE, + ASM, + USING, + INLINE, + EXPLICIT, + STATIC, + CONST, + VOLATILE, + OPERATOR, + SIZEOF, + NEW, + DELETE, + PLUS, + MINUS, + STAR, + SLASH, + PERCENT, + HAT, + AND, + OR, + TILDE, + NOT, + PLUS_EQ, + MINUS_EQ, + STAR_EQ, + SLASH_EQ, + PERCENT_EQ, + HAT_EQ, + AND_EQ, + OR_EQ, + LTLT, + GTGT, + GTGT_EQ, + LTLT_EQ, + EQEQ, + NE, + LE, + GE, + ANDAND, + OROR, + INCR, + DECR, + COMMA, + ARROW_STAR, + ARROW, + CHAR, + WCHAR, + BOOL, + SHORT, + INT, + LONG, + SIGNED, + UNSIGNED, + FLOAT, + DOUBLE, + VOID, + CASE, + DEFAULT, + IF, + ELSE, + SWITCH, + WHILE, + DO, + FOR, + BREAK, + CONTINUE, + GOTO, + SIGNALS, + SLOTS, + RETURN, + Q_META_TOKEN_BEGIN, + Q_OBJECT_TOKEN = Q_META_TOKEN_BEGIN, + Q_GADGET_TOKEN, + Q_PROPERTY_TOKEN, + Q_ENUMS_TOKEN, + Q_FLAGS_TOKEN, + Q_DECLARE_FLAGS_TOKEN, + Q_DECLARE_INTERFACE_TOKEN, + Q_DECLARE_METATYPE_TOKEN, + Q_CLASSINFO_TOKEN, + Q_INTERFACES_TOKEN, + Q_SIGNALS_TOKEN, + Q_SLOTS_TOKEN, + Q_SIGNAL_TOKEN, + Q_SLOT_TOKEN, + Q_PRIVATE_SLOT_TOKEN, + Q_MOC_COMPAT_TOKEN, + Q_QT3_SUPPORT_TOKEN, + Q_INVOKABLE_TOKEN, + Q_SCRIPTABLE_TOKEN, + Q_META_TOKEN_END, + SPECIAL_TREATMENT_MARK = Q_META_TOKEN_END, + MOC_INCLUDE_BEGIN, + MOC_INCLUDE_END, + CPP_COMMENT, + C_COMMENT, + FLOATING_LITERAL, + HASH, + QUOTE, + SINGLEQUOTE, + LANGLE_SCOPE, + DIGIT, + CHARACTER, + NEWLINE, + WHITESPACE, + BACKSLASH, + INCOMPLETE, + + PP_DEFINE, + PP_UNDEF, + PP_IF, + PP_IFDEF, + PP_IFNDEF, + PP_ELIF, + PP_ELSE, + PP_ENDIF, + PP_INCLUDE, + PP_HASHHASH, + PP_HASH, + PP_DEFINED, + PP_INCOMPLETE, + + PP_MOC_TRUE, + PP_MOC_FALSE, + + PP_NOTOKEN = NOTOKEN, + PP_IDENTIFIER = IDENTIFIER, + PP_INTEGER_LITERAL = INTEGER_LITERAL, + PP_CHARACTER_LITERAL = CHARACTER_LITERAL, + PP_STRING_LITERAL = STRING_LITERAL, + PP_LANGLE = LANGLE, + PP_RANGLE = RANGLE, + PP_LPAREN = LPAREN, + PP_RPAREN = RPAREN, + PP_COMMA = COMMA, + PP_PLUS = PLUS, + PP_MINUS = MINUS, + PP_STAR = STAR, + PP_SLASH = SLASH, + PP_PERCENT = PERCENT, + PP_HAT = HAT, + PP_AND = AND, + PP_OR = OR, + PP_TILDE = TILDE, + PP_NOT = NOT, + PP_LTLT = LTLT, + PP_GTGT = GTGT, + PP_EQEQ = EQEQ, + PP_NE = NE, + PP_LE = LE, + PP_GE = GE, + PP_ANDAND = ANDAND, + PP_OROR = OROR, + PP_QUESTION = QUESTION, + PP_COLON = COLON, + PP_FLOATING_LITERAL = FLOATING_LITERAL, + PP_QUOTE = QUOTE, + PP_SINGLEQUOTE = SINGLEQUOTE, + PP_DIGIT = DIGIT, + PP_CHARACTER = CHARACTER, + PP_WHITESPACE = WHITESPACE, + PP_NEWLINE = NEWLINE, + PP_CPP_COMMENT = CPP_COMMENT, + PP_C_COMMENT = C_COMMENT, + PP_BACKSLASH = BACKSLASH +}; + +// for debugging only +#if defined(DEBUG_MOC) +const char *tokenTypeName(Token t); +#endif + +typedef Token PP_Token; + +QT_END_NAMESPACE + +#endif // TOKEN_H diff --git a/src/tools/moc/util/generate.sh b/src/tools/moc/util/generate.sh new file mode 100755 index 0000000..215b8cb --- /dev/null +++ b/src/tools/moc/util/generate.sh @@ -0,0 +1,7 @@ +#!/bin/sh +qmake +make +cat licenseheader.txt > ../keywords.cpp +cat licenseheader.txt > ../ppkeywords.cpp +./generate_keywords >> ../keywords.cpp +./generate_keywords preprocessor >> ../ppkeywords.cpp diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp new file mode 100644 index 0000000..116be2b --- /dev/null +++ b/src/tools/moc/util/generate_keywords.cpp @@ -0,0 +1,468 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <stdio.h> +#include <string.h> +#include <qbytearray.h> +#include <qlist.h> + +struct Keyword +{ + const char *lexem; + const char *token; +}; + +static const Keyword pp_keywords[] = { + { "<", "PP_LANGLE" }, + { ">", "PP_RANGLE" }, + { "(", "PP_LPAREN"}, + { ")", "PP_RPAREN"}, + { ",", "PP_COMMA"}, + { "\n", "PP_NEWLINE"}, + { "#define", "PP_DEFINE"}, + { "#if", "PP_IF"}, + { "#undef", "PP_UNDEF"}, + { "#ifdef", "PP_IFDEF"}, + { "#ifndef", "PP_IFNDEF"}, + { "#elif", "PP_ELIF"}, + { "#else", "PP_ELSE"}, + { "#endif", "PP_ENDIF"}, + { "#include", "PP_INCLUDE"}, + { "defined", "PP_DEFINED"}, + { "+", "PP_PLUS" }, + { "-", "PP_MINUS" }, + { "*", "PP_STAR" }, + { "/", "PP_SLASH" }, + { "%", "PP_PERCENT" }, + { "^", "PP_HAT" }, + { "&", "PP_AND" }, + { "bitand", "PP_AND" }, + { "|", "PP_OR" }, + { "bitor", "PP_OR" }, + { "~", "PP_TILDE" }, + { "compl", "PP_TILDE" }, + { "!", "PP_NOT" }, + { "not", "PP_NOT" }, + { "<<", "PP_LTLT" }, + { ">>", "PP_GTGT" }, + { "==", "PP_EQEQ" }, + { "!=", "PP_NE" }, + { "not_eq", "PP_NE" }, + { "<=", "PP_LE" }, + { ">=", "PP_GE" }, + { "&&", "PP_ANDAND" }, + { "||", "PP_OROR" }, + { "?", "PP_QUESTION" }, + { ":", "PP_COLON" }, + { "##", "PP_HASHHASH"}, + { "%:%:", "PP_HASHHASH"}, + { "#", "PP_HASH"}, + { "\"", "PP_QUOTE"}, + { "\'", "PP_SINGLEQUOTE"}, + { " ", "PP_WHITESPACE" }, + { "\t", "PP_WHITESPACE" }, + { "//", "PP_CPP_COMMENT" }, + { "/*", "PP_C_COMMENT" }, + { "\\", "PP_BACKSLASH" }, + { 0, "PP_NOTOKEN"} +}; + +static const Keyword keywords[] = { + { "<", "LANGLE" }, + { ">", "RANGLE" }, + { "(", "LPAREN" }, + { ")", "RPAREN" }, + { "...", "ELIPSIS" }, + { ",", "COMMA" }, + { "[", "LBRACK" }, + { "]", "RBRACK" }, + { "<:", "LBRACK" }, + { ":>", "RBRACK" }, + { "<::", "LANGLE_SCOPE" }, + { "{", "LBRACE" }, + { "<%", "LBRACE" }, + { "}", "RBRACE" }, + { "%>", "RBRACE" }, + { "=", "EQ" }, + { "::", "SCOPE" }, + { ";", "SEMIC" }, + { ":", "COLON" }, + { ".*", "DOTSTAR" }, + { "?", "QUESTION" }, + { ".", "DOT" }, + { "dynamic_cast", "DYNAMIC_CAST" }, + { "static_cast", "STATIC_CAST" }, + { "reinterpret_cast", "REINTERPRET_CAST" }, + { "const_cast", "CONST_CAST" }, + { "typeid", "TYPEID" }, + { "this", "THIS" }, + { "template", "TEMPLATE" }, + { "throw", "THROW" }, + { "try", "TRY" }, + { "catch", "CATCH" }, + { "typedef", "TYPEDEF" }, + { "friend", "FRIEND" }, + { "class", "CLASS" }, + { "namespace", "NAMESPACE" }, + { "enum", "ENUM" }, + { "struct", "STRUCT" }, + { "union", "UNION" }, + { "virtual", "VIRTUAL" }, + { "private", "PRIVATE" }, + { "protected", "PROTECTED" }, + { "public", "PUBLIC" }, + { "export", "EXPORT" }, + { "auto", "AUTO" }, + { "register", "REGISTER" }, + { "extern", "EXTERN" }, + { "mutable", "MUTABLE" }, + { "asm", "ASM" }, + { "using", "USING" }, + { "inline", "INLINE" }, + { "explicit", "EXPLICIT" }, + { "static", "STATIC" }, + { "const", "CONST" }, + { "volatile", "VOLATILE" }, + { "operator", "OPERATOR" }, + { "sizeof", "SIZEOF" }, + { "new", "NEW" }, + { "delete", "DELETE" }, + { "+", "PLUS" }, + { "-", "MINUS" }, + { "*", "STAR" }, + { "/", "SLASH" }, + { "%", "PERCENT" }, + { "^", "HAT" }, + { "&", "AND" }, + { "bitand", "AND" }, + { "|", "OR" }, + { "bitor", "OR" }, + { "~", "TILDE" }, + { "compl", "TILDE" }, + { "!", "NOT" }, + { "not", "NOT" }, + { "+=", "PLUS_EQ" }, + { "-=", "MINUS_EQ" }, + { "*=", "STAR_EQ" }, + { "/=", "SLASH_EQ" }, + { "%=", "PERCENT_EQ" }, + { "^=", "HAT_EQ" }, + { "&=", "AND_EQ" }, + { "|=", "OR_EQ" }, + { "<<", "LTLT" }, + { ">>", "GTGT" }, + { ">>=", "GTGT_EQ" }, + { "<<=", "LTLT_EQ" }, + { "==", "EQEQ" }, + { "!=", "NE" }, + { "not_eq", "NE" }, + { "<=", "LE" }, + { ">=", "GE" }, + { "&&", "ANDAND" }, + { "||", "OROR" }, + { "++", "INCR" }, + { "--", "DECR" }, + { ",", "COMMA" }, + { "->*", "ARROW_STAR" }, + { "->", "ARROW" }, + { "char", "CHAR" }, + { "wchar", "WCHAR" }, + { "bool", "BOOL" }, + { "short", "SHORT" }, + { "int", "INT" }, + { "long", "LONG" }, + { "signed", "SIGNED" }, + { "unsigned", "UNSIGNED" }, + { "float", "FLOAT" }, + { "double", "DOUBLE" }, + { "void", "VOID" }, + { "case", "CASE" }, + { "default", "DEFAULT" }, + { "if", "IF" }, + { "else", "ELSE" }, + { "switch", "SWITCH" }, + { "while", "WHILE" }, + { "do", "DO" }, + { "for", "FOR" }, + { "break", "BREAK" }, + { "continue", "CONTINUE" }, + { "goto", "GOTO" }, + { "return", "RETURN" }, + { "Q_OBJECT", "Q_OBJECT_TOKEN" }, + { "Q_GADGET", "Q_GADGET_TOKEN" }, + { "Q_PROPERTY", "Q_PROPERTY_TOKEN" }, + { "Q_ENUMS", "Q_ENUMS_TOKEN" }, + { "Q_FLAGS", "Q_FLAGS_TOKEN" }, + { "Q_DECLARE_FLAGS", "Q_DECLARE_FLAGS_TOKEN" }, + { "Q_DECLARE_INTERFACE", "Q_DECLARE_INTERFACE_TOKEN" }, + { "Q_DECLARE_METATYPE", "Q_DECLARE_METATYPE_TOKEN" }, + { "Q_DECLARE_EXTENSION_INTERFACE", "Q_DECLARE_INTERFACE_TOKEN" }, + { "Q_SETS", "Q_FLAGS_TOKEN" }, + { "Q_CLASSINFO", "Q_CLASSINFO_TOKEN" }, + { "Q_INTERFACES", "Q_INTERFACES_TOKEN" }, + { "signals", "SIGNALS" }, + { "slots", "SLOTS" }, + { "Q_SIGNALS", "Q_SIGNALS_TOKEN" }, + { "Q_SLOTS", "Q_SLOTS_TOKEN" }, + { "Q_PRIVATE_SLOT", "Q_PRIVATE_SLOT_TOKEN" }, + { "QT_MOC_COMPAT", "Q_MOC_COMPAT_TOKEN" }, + { "QT3_SUPPORT", "Q_QT3_SUPPORT_TOKEN" }, + { "Q_INVOKABLE", "Q_INVOKABLE_TOKEN" }, + { "Q_SIGNAL", "Q_SIGNAL_TOKEN" }, + { "Q_SLOT", "Q_SLOT_TOKEN" }, + { "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" }, + + { "\n", "NEWLINE" }, + { "\"", "QUOTE" }, + { "\'", "SINGLEQUOTE" }, + { " ", "WHITESPACE" }, + { "\t", "WHITESPACE" }, + { "#", "HASH" }, + { "\\", "BACKSLASH" }, + { "//", "CPP_COMMENT" }, + { "/*", "C_COMMENT" }, + { 0, "NOTOKEN"} +}; + + +inline bool is_ident_start(char s) +{ + return ((s >= 'a' && s <= 'z') + || (s >= 'A' && s <= 'Z') + || s == '_' + ); +} + +inline bool is_ident_char(char s) +{ + return ((s >= 'a' && s <= 'z') + || (s >= 'A' && s <= 'Z') + || (s >= '0' && s <= '9') + || s == '_' + ); +} +struct State +{ + State(const char* token):token(token), nextindex(0), + defchar(0), defnext(0), ident(0) { + memset( next, 0, sizeof(next)); + } + QByteArray token; + int next[128]; + int nextindex; + + char defchar; + int defnext; + + const char *ident; + + bool operator==(const State& o) const + { + return (token == o.token + && nextindex == o.nextindex + && defchar == o.defchar + && defnext == o.defnext + && ident == o.ident); + } +}; + +void newState(QList<State> &states, const char *token, const char *lexem, bool pre) +{ + const char * ident = 0; + if (is_ident_start(*lexem)) + ident = pre?"PP_CHARACTER" : "CHARACTER"; + else if (*lexem == '#') + ident = pre?"PP_HASH" : "HASH"; + + int state = 0; + while (*lexem) { + int next = states[state].next[(int)*lexem]; + if (!next) { + const char * t = 0; + if (ident) + t = ident; + else + t = pre?"PP_INCOMPLETE":"INCOMPLETE"; + next = states.size(); + states += State(t); + states[state].next[(int)*lexem] = next; + states[next].ident = ident; + } + state = next; + ++lexem; + if (ident && !is_ident_char(*lexem)) + ident = 0; + } + states[state].token = token; +} + +void newState(QList<State> &states, const char *token, char lexem) +{ + int next = states[0].next[(int)lexem]; + if (!next) { + next = states.size(); + states += State(token); + states[0].next[(int)lexem] = next; + } else { + states[next].token = token; + } +} + + +void makeTable(const Keyword keywords[]) +{ + int i,c; + bool pre = (keywords == pp_keywords); + QList<State> states; + states += State(pre?"PP_NOTOKEN":"NOTOKEN"); + + // identifiers + for (c = 'a'; c <= 'z'; ++c) + newState(states, pre?"PP_CHARACTER":"CHARACTER", c); + for (c = 'A'; c <= 'Z'; ++c) + newState(states, pre?"PP_CHARACTER":"CHARACTER", c); + c = '_'; + newState(states, pre?"PP_CHARACTER":"CHARACTER", c); + + // add digits + for (c = '0'; c <= '9'; ++c) + newState(states, pre?"PP_DIGIT":"DIGIT", c); + + // keywords + for (i = 0; keywords[i].lexem; ++i) + newState(states, keywords[i].token, keywords[i].lexem, pre); + + // some floats + for (c = '0'; c <= '9'; ++c) + newState(states, pre?"PP_FLOATING_LITERAL":"FLOATING_LITERAL", + QByteArray(".") + char(c), pre); + + // simplify table with default transitions + int transindex = -1; + for (i = 0; i < states.size(); ++i) { + int n = 0; + int defchar = -1; + for (c = 0; c < 128; ++c) + if (states[i].next[c]) { + ++n; + defchar = c; + } + if (!n) + continue; + if (n == 1) { + states[i].defnext = states[i].next[defchar]; + states[i].defchar = defchar; + continue; + } + states[i].nextindex = ++transindex; + } + +#if 1 + // compress table + int j, k; + for (i = 0; i < states.size(); ++i) { + for (j = i + 1; j < states.size(); ++j) { + if ( states[i] == states[j] ) { + for (k = 0; k < states.size(); ++k) { + if (states[k].defnext == j) + states[k].defnext = i; + if (states[k].defnext > j) + --states[k].defnext; + for (c = 0; c < 128; ++c) { + if (states[k].next[c] == j) + states[k].next[c] = i; + if (states[k].next[c] > j) + --states[k].next[c]; + } + } + states.removeAt(j); + --j; + } + } + } +#endif + printf("static const short %skeyword_trans[][128] = {\n", + pre?"pp_":""); + for (i = 0; i < states.size(); ++i) { + if (i && !states[i].nextindex) + continue; + printf("%s {", i?",\n":""); + for (c = 0; c < 128; ++c) + printf("%s%s%d", + c?",":"", + (!c || c%16)?"":"\n ", + states[i].next[c] + ); + printf("}"); + } + printf("\n};\n\n"); + + printf("static const struct\n{\n" + " %sToken token;\n" + " short next;\n" + " char defchar;\n" + " short defnext;\n" + " %sToken ident;\n" + "} %skeywords[] = {\n", + pre ? "PP_":"", + pre ? "PP_":"", + pre ? "pp_":""); + for (i = 0; i < states.size(); ++i) { + printf("%s {%s, %d, %d, %d, %s}", + i?",\n":"", + states[i].token.data(), + states[i].nextindex, + states[i].defchar, + states[i].defnext, + states[i].ident?states[i].ident:(pre?"PP_NOTOKEN":"NOTOKEN")); + } + printf("\n};\n"); +} + +int main(int argc, char **) +{ + printf("// auto generated\n" + "// DO NOT EDIT.\n\n"); + if ( argc > 1 ) + makeTable(pp_keywords); + else + makeTable(keywords); + return 0; +} diff --git a/src/tools/moc/util/generate_keywords.pro b/src/tools/moc/util/generate_keywords.pro new file mode 100644 index 0000000..8dff744 --- /dev/null +++ b/src/tools/moc/util/generate_keywords.pro @@ -0,0 +1,13 @@ +###################################################################### +# Automatically generated by qmake (1.08a) Mon Feb 23 13:08:28 2004 +###################################################################### + +TEMPLATE = app +CONFIG -= moc +mac:CONFIG -= app_bundle +INCLUDEPATH += . + +# Input +SOURCES += generate_keywords.cpp +CONFIG += qt create_prl link_prl +OBJECTS_DIR=.obj/debug-shared diff --git a/src/tools/moc/util/licenseheader.txt b/src/tools/moc/util/licenseheader.txt new file mode 100644 index 0000000..6812109 --- /dev/null +++ b/src/tools/moc/util/licenseheader.txt @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + diff --git a/src/tools/moc/utils.h b/src/tools/moc/utils.h new file mode 100644 index 0000000..2dffc43 --- /dev/null +++ b/src/tools/moc/utils.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef UTILS_H +#define UTILS_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +inline bool is_whitespace(char s) +{ + return (s == ' ' || s == '\t' || s == '\n'); +} + +inline bool is_space(char s) +{ + return (s == ' ' || s == '\t'); +} + +inline bool is_ident_start(char s) +{ + return ((s >= 'a' && s <= 'z') + || (s >= 'A' && s <= 'Z') + || s == '_' + ); +} + +inline bool is_ident_char(char s) +{ + return ((s >= 'a' && s <= 'z') + || (s >= 'A' && s <= 'Z') + || (s >= '0' && s <= '9') + || s == '_' + ); +} + +inline bool is_digit_char(char s) +{ + return (s >= '0' && s <= '9'); +} + +inline bool is_octal_char(char s) +{ + return (s >= '0' && s <= '7'); +} + +inline bool is_hex_char(char s) +{ + return ((s >= 'a' && s <= 'f') + || (s >= 'A' && s <= 'F') + || (s >= '0' && s <= '9') + ); +} + +inline const char *skipQuote(const char *data) +{ + while (*data && (*data != '\"')) { + if (*data == '\\') { + ++data; + if (!*data) break; + } + ++data; + } + + if (*data) //Skip last quote + ++data; + return data; +} + +QT_END_NAMESPACE + +#endif // UTILS_H |