src/tools/moc/generator.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the tools applications of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "generator.h"
       
    43 #include "outputrevision.h"
       
    44 #include "utils.h"
       
    45 #include <QtCore/qmetatype.h>
       
    46 #include <stdio.h>
       
    47 
       
    48 #include <private/qmetaobject_p.h> //for the flags.
       
    49 
       
    50 QT_BEGIN_NAMESPACE
       
    51 
       
    52 uint qvariant_nameToType(const char* name)
       
    53 {
       
    54     if (!name)
       
    55         return 0;
       
    56 
       
    57     if (strcmp(name, "QVariant") == 0)
       
    58         return 0xffffffff;
       
    59     if (strcmp(name, "QCString") == 0)
       
    60         return QMetaType::QByteArray;
       
    61     if (strcmp(name, "Q_LLONG") == 0)
       
    62         return QMetaType::LongLong;
       
    63     if (strcmp(name, "Q_ULLONG") == 0)
       
    64         return QMetaType::ULongLong;
       
    65     if (strcmp(name, "QIconSet") == 0)
       
    66         return QMetaType::QIcon;
       
    67 
       
    68     uint tp = QMetaType::type(name);
       
    69     return tp < QMetaType::User ? tp : 0;
       
    70 }
       
    71 
       
    72 /*
       
    73   Returns true if the type is a QVariant types.
       
    74 */
       
    75 bool isVariantType(const char* type)
       
    76 {
       
    77     return qvariant_nameToType(type) != 0;
       
    78 }
       
    79 
       
    80 /*!
       
    81   Returns true if the type is qreal.
       
    82 */
       
    83 static bool isQRealType(const char *type)
       
    84 {
       
    85     return strcmp(type, "qreal") == 0;
       
    86 }
       
    87 
       
    88 Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile)
       
    89     : out(outfile), cdef(classDef), metaTypes(metaTypes)
       
    90 {
       
    91     if (cdef->superclassList.size())
       
    92         purestSuperClass = cdef->superclassList.first().first;
       
    93 }
       
    94 
       
    95 static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
       
    96 {
       
    97     if (s.at(i) != '\\' || i >= s.length() - 1)
       
    98         return 1;
       
    99     const int startPos = i;
       
   100     ++i;
       
   101     char ch = s.at(i);
       
   102     if (ch == 'x') {
       
   103         ++i;
       
   104         while (i < s.length() && is_hex_char(s.at(i)))
       
   105             ++i;
       
   106     } else if (is_octal_char(ch)) {
       
   107         while (i < startPos + 4
       
   108                && i < s.length()
       
   109                && is_octal_char(s.at(i))) {
       
   110             ++i;
       
   111         }
       
   112     } else { // single character escape sequence
       
   113         i = qMin(i + 1, s.length());
       
   114     }
       
   115     return i - startPos;
       
   116 }
       
   117 
       
   118 int Generator::strreg(const char *s)
       
   119 {
       
   120     int idx = 0;
       
   121     if (!s)
       
   122         s = "";
       
   123     for (int i = 0; i < strings.size(); ++i) {
       
   124         const QByteArray &str = strings.at(i);
       
   125         if (str == s)
       
   126             return idx;
       
   127         idx += str.length() + 1;
       
   128         for (int i = 0; i < str.length(); ++i) {
       
   129             if (str.at(i) == '\\') {
       
   130                 int cnt = lengthOfEscapeSequence(str, i) - 1;
       
   131                 idx -= cnt;
       
   132                 i += cnt;
       
   133             }
       
   134         }
       
   135     }
       
   136     strings.append(s);
       
   137     return idx;
       
   138 }
       
   139 
       
   140 void Generator::generateCode()
       
   141 {
       
   142     bool isQt = (cdef->classname == "Qt");
       
   143     bool isQObject = (cdef->classname == "QObject");
       
   144     bool isConstructible = !cdef->constructorList.isEmpty();
       
   145 
       
   146 //
       
   147 // build the data array
       
   148 //
       
   149     int i = 0;
       
   150 
       
   151 
       
   152     // filter out undeclared enumerators and sets
       
   153     {
       
   154         QList<EnumDef> enumList;
       
   155         for (i = 0; i < cdef->enumList.count(); ++i) {
       
   156             EnumDef def = cdef->enumList.at(i);
       
   157             if (cdef->enumDeclarations.contains(def.name)) {
       
   158                 enumList += def;
       
   159             }
       
   160             QByteArray alias = cdef->flagAliases.value(def.name);
       
   161             if (cdef->enumDeclarations.contains(alias)) {
       
   162                 def.name = alias;
       
   163                 enumList += def;
       
   164             }
       
   165         }
       
   166         cdef->enumList = enumList;
       
   167     }
       
   168 
       
   169 
       
   170     QByteArray qualifiedClassNameIdentifier = cdef->qualified;
       
   171     qualifiedClassNameIdentifier.replace(':', '_');
       
   172 
       
   173     int index = 14;
       
   174     fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
       
   175     fprintf(out, "\n // content:\n");
       
   176     fprintf(out, "    %4d,       // revision\n", 4);
       
   177     fprintf(out, "    %4d,       // classname\n", strreg(cdef->qualified));
       
   178     fprintf(out, "    %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0);
       
   179     index += cdef->classInfoList.count() * 2;
       
   180 
       
   181     int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count();
       
   182     fprintf(out, "    %4d, %4d, // methods\n", methodCount, methodCount ? index : 0);
       
   183     index += methodCount * 5;
       
   184     fprintf(out, "    %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0);
       
   185     index += cdef->propertyList.count() * 3;
       
   186     if(cdef->notifyableProperties)
       
   187         index += cdef->propertyList.count();
       
   188     fprintf(out, "    %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0);
       
   189 
       
   190     int enumsIndex = index;
       
   191     for (i = 0; i < cdef->enumList.count(); ++i)
       
   192         index += 4 + (cdef->enumList.at(i).values.count() * 2);
       
   193     fprintf(out, "    %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
       
   194             isConstructible ? index : 0);
       
   195 
       
   196     fprintf(out, "    %4d,       // flags\n", 0);
       
   197     fprintf(out, "    %4d,       // signalCount\n", cdef->signalList.count());
       
   198 
       
   199 
       
   200 //
       
   201 // Build classinfo array
       
   202 //
       
   203     generateClassInfos();
       
   204 
       
   205 //
       
   206 // Build signals array first, otherwise the signal indices would be wrong
       
   207 //
       
   208     generateFunctions(cdef->signalList, "signal", MethodSignal);
       
   209 
       
   210 //
       
   211 // Build slots array
       
   212 //
       
   213     generateFunctions(cdef->slotList, "slot", MethodSlot);
       
   214 
       
   215 //
       
   216 // Build method array
       
   217 //
       
   218     generateFunctions(cdef->methodList, "method", MethodMethod);
       
   219 
       
   220 
       
   221 //
       
   222 // Build property array
       
   223 //
       
   224     generateProperties();
       
   225 
       
   226 //
       
   227 // Build enums array
       
   228 //
       
   229     generateEnums(enumsIndex);
       
   230 
       
   231 //
       
   232 // Build constructors array
       
   233 //
       
   234     if (isConstructible)
       
   235         generateFunctions(cdef->constructorList, "constructor", MethodConstructor);
       
   236 
       
   237 //
       
   238 // Terminate data array
       
   239 //
       
   240     fprintf(out, "\n       0        // eod\n};\n\n");
       
   241 
       
   242 //
       
   243 // Build stringdata array
       
   244 //
       
   245     fprintf(out, "static const char qt_meta_stringdata_%s[] = {\n", qualifiedClassNameIdentifier.constData());
       
   246     fprintf(out, "    \"");
       
   247     int col = 0;
       
   248     int len = 0;
       
   249     for (i = 0; i < strings.size(); ++i) {
       
   250         QByteArray s = strings.at(i);
       
   251         len = s.length();
       
   252         if (col && col + len >= 72) {
       
   253             fprintf(out, "\"\n    \"");
       
   254             col = 0;
       
   255         } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
       
   256             fprintf(out, "\"\"");
       
   257             len += 2;
       
   258         }
       
   259         int idx = 0;
       
   260         while (idx < s.length()) {
       
   261             if (idx > 0) {
       
   262                 col = 0;
       
   263                 fprintf(out, "\"\n    \"");
       
   264             }
       
   265             int spanLen = qMin(70, s.length() - idx);
       
   266             // don't cut escape sequences at the end of a line
       
   267             int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
       
   268             if (backSlashPos >= idx) {
       
   269                 int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
       
   270                 spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx);
       
   271             }
       
   272             fwrite(s.constData() + idx, 1, spanLen, out);
       
   273             idx += spanLen;
       
   274             col += spanLen;
       
   275         }
       
   276 
       
   277         fputs("\\0", out);
       
   278         col += len + 2;
       
   279     }
       
   280     fprintf(out, "\"\n};\n\n");
       
   281 
       
   282 
       
   283 //
       
   284 // Generate internal qt_static_metacall() function
       
   285 //
       
   286     if (isConstructible)
       
   287         generateStaticMetacall(qualifiedClassNameIdentifier);
       
   288 
       
   289 //
       
   290 // Build extra array
       
   291 //
       
   292     QList<QByteArray> extraList;
       
   293     for (int i = 0; i < cdef->propertyList.count(); ++i) {
       
   294         const PropertyDef &p = cdef->propertyList.at(i);
       
   295         if (!isVariantType(p.type) && !metaTypes.contains(p.type)) {
       
   296             int s = p.type.lastIndexOf("::");
       
   297             if (s > 0) {
       
   298                 QByteArray scope = p.type.left(s);
       
   299                 if (scope != "Qt" && scope != cdef->classname && !extraList.contains(scope))
       
   300                     extraList += scope;
       
   301             }
       
   302         }
       
   303     }
       
   304     if (!extraList.isEmpty()) {
       
   305         fprintf(out, "#ifdef Q_NO_DATA_RELOCATION\n");
       
   306         fprintf(out, "static const QMetaObjectAccessor qt_meta_extradata_%s[] = {\n    ", qualifiedClassNameIdentifier.constData());
       
   307         for (int i = 0; i < extraList.count(); ++i) {
       
   308             fprintf(out, "    %s::getStaticMetaObject,\n", extraList.at(i).constData());
       
   309         }
       
   310         fprintf(out, "#else\n");
       
   311         fprintf(out, "static const QMetaObject *qt_meta_extradata_%s[] = {\n    ", qualifiedClassNameIdentifier.constData());
       
   312         for (int i = 0; i < extraList.count(); ++i) {
       
   313             fprintf(out, "    &%s::staticMetaObject,\n", extraList.at(i).constData());
       
   314         }
       
   315         fprintf(out, "#endif //Q_NO_DATA_RELOCATION\n");
       
   316         fprintf(out, "    0\n};\n\n");
       
   317     }
       
   318 
       
   319     if (isConstructible || !extraList.isEmpty()) {
       
   320         fprintf(out, "static const QMetaObjectExtraData qt_meta_extradata2_%s = {\n    ",
       
   321                 qualifiedClassNameIdentifier.constData());
       
   322         if (extraList.isEmpty())
       
   323             fprintf(out, "0, ");
       
   324         else
       
   325             fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData());
       
   326         if (!isConstructible)
       
   327             fprintf(out, "0");
       
   328         else
       
   329             fprintf(out, "%s_qt_static_metacall", qualifiedClassNameIdentifier.constData());
       
   330         fprintf(out, " \n};\n\n");
       
   331     }
       
   332 
       
   333 //
       
   334 // Finally create and initialize the static meta object
       
   335 //
       
   336     if (isQt)
       
   337         fprintf(out, "const QMetaObject QObject::staticQtMetaObject = {\n");
       
   338     else
       
   339         fprintf(out, "const QMetaObject %s::staticMetaObject = {\n", cdef->qualified.constData());
       
   340 
       
   341     if (isQObject)
       
   342         fprintf(out, "    { 0, ");
       
   343     else if (cdef->superclassList.size())
       
   344         fprintf(out, "    { &%s::staticMetaObject, ", purestSuperClass.constData());
       
   345     else
       
   346         fprintf(out, "    { 0, ");
       
   347     fprintf(out, "qt_meta_stringdata_%s,\n      qt_meta_data_%s, ",
       
   348              qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
       
   349     if (!isConstructible && extraList.isEmpty())
       
   350         fprintf(out, "0 }\n");
       
   351     else
       
   352         fprintf(out, "&qt_meta_extradata2_%s }\n", qualifiedClassNameIdentifier.constData());
       
   353     fprintf(out, "};\n");
       
   354 
       
   355     if(isQt)
       
   356         return;
       
   357 
       
   358 //
       
   359 // Generate static meta object accessor (needed for symbian, because DLLs do not support data imports.
       
   360 //
       
   361     fprintf(out, "\n#ifdef Q_NO_DATA_RELOCATION\n");
       
   362     fprintf(out, "const QMetaObject &%s::getStaticMetaObject() { return staticMetaObject; }\n", cdef->qualified.constData());
       
   363     fprintf(out, "#endif //Q_NO_DATA_RELOCATION\n");
       
   364 
       
   365     if (!cdef->hasQObject)
       
   366         return;
       
   367 
       
   368     fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;\n}\n",
       
   369             cdef->qualified.constData());
       
   370 
       
   371 //
       
   372 // Generate smart cast function
       
   373 //
       
   374     fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData());
       
   375     fprintf(out, "    if (!_clname) return 0;\n");
       
   376     fprintf(out, "    if (!strcmp(_clname, qt_meta_stringdata_%s))\n"
       
   377                   "        return static_cast<void*>(const_cast< %s*>(this));\n",
       
   378             qualifiedClassNameIdentifier.constData(), cdef->classname.constData());
       
   379     for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
       
   380         if (cdef->superclassList.at(i).second == FunctionDef::Private)
       
   381             continue;
       
   382         const char *cname = cdef->superclassList.at(i).first;
       
   383         fprintf(out, "    if (!strcmp(_clname, \"%s\"))\n        return static_cast< %s*>(const_cast< %s*>(this));\n",
       
   384                 cname, cname, cdef->classname.constData());
       
   385     }
       
   386     for (int i = 0; i < cdef->interfaceList.size(); ++i) {
       
   387         const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i);
       
   388         for (int j = 0; j < iface.size(); ++j) {
       
   389             fprintf(out, "    if (!strcmp(_clname, %s))\n        return ", iface.at(j).interfaceId.constData());
       
   390             for (int k = j; k >= 0; --k)
       
   391                 fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData());
       
   392             fprintf(out, "const_cast< %s*>(this)%s;\n",
       
   393                     cdef->classname.constData(), QByteArray(j+1, ')').constData());
       
   394         }
       
   395     }
       
   396     if (!purestSuperClass.isEmpty() && !isQObject) {
       
   397         QByteArray superClass = purestSuperClass;
       
   398         // workaround for VC6
       
   399         if (superClass.contains("::")) {
       
   400             fprintf(out, "    typedef %s QMocSuperClass;\n", superClass.constData());
       
   401             superClass = "QMocSuperClass";
       
   402         }
       
   403         fprintf(out, "    return %s::qt_metacast(_clname);\n", superClass.constData());
       
   404     } else {
       
   405         fprintf(out, "    return 0;\n");
       
   406     }
       
   407     fprintf(out, "}\n");
       
   408 
       
   409 //
       
   410 // Generate internal qt_metacall()  function
       
   411 //
       
   412     generateMetacall();
       
   413 
       
   414 //
       
   415 // Generate internal signal functions
       
   416 //
       
   417     for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
       
   418         generateSignal(&cdef->signalList[signalindex], signalindex);
       
   419 }
       
   420 
       
   421 
       
   422 void Generator::generateClassInfos()
       
   423 {
       
   424     if (cdef->classInfoList.isEmpty())
       
   425         return;
       
   426 
       
   427     fprintf(out, "\n // classinfo: key, value\n");
       
   428 
       
   429     for (int i = 0; i < cdef->classInfoList.size(); ++i) {
       
   430         const ClassInfoDef &c = cdef->classInfoList.at(i);
       
   431         fprintf(out, "    %4d, %4d,\n", strreg(c.name), strreg(c.value));
       
   432     }
       
   433 }
       
   434 
       
   435 void Generator::generateFunctions(QList<FunctionDef>& list, const char *functype, int type)
       
   436 {
       
   437     if (list.isEmpty())
       
   438         return;
       
   439     fprintf(out, "\n // %ss: signature, parameters, type, tag, flags\n", functype);
       
   440 
       
   441     for (int i = 0; i < list.count(); ++i) {
       
   442         const FunctionDef &f = list.at(i);
       
   443 
       
   444         QByteArray sig = f.name + '(';
       
   445         QByteArray arguments;
       
   446 
       
   447         for (int j = 0; j < f.arguments.count(); ++j) {
       
   448             const ArgumentDef &a = f.arguments.at(j);
       
   449             if (j) {
       
   450                 sig += ",";
       
   451                 arguments += ",";
       
   452             }
       
   453             sig += a.normalizedType;
       
   454             arguments += a.name;
       
   455         }
       
   456         sig += ')';
       
   457 
       
   458         char flags = type;
       
   459         if (f.access == FunctionDef::Private)
       
   460             flags |= AccessPrivate;
       
   461         else if (f.access == FunctionDef::Public)
       
   462             flags |= AccessPublic;
       
   463         else if (f.access == FunctionDef::Protected)
       
   464             flags |= AccessProtected;
       
   465         if (f.access == FunctionDef::Private)
       
   466             flags |= AccessPrivate;
       
   467         else if (f.access == FunctionDef::Public)
       
   468             flags |= AccessPublic;
       
   469         else if (f.access == FunctionDef::Protected)
       
   470             flags |= AccessProtected;
       
   471         if (f.isCompat)
       
   472             flags |= MethodCompatibility;
       
   473         if (f.wasCloned)
       
   474             flags |= MethodCloned;
       
   475         if (f.isScriptable)
       
   476             flags |= MethodScriptable;
       
   477         fprintf(out, "    %4d, %4d, %4d, %4d, 0x%02x,\n", strreg(sig),
       
   478                 strreg(arguments), strreg(f.normalizedType), strreg(f.tag), flags);
       
   479     }
       
   480 }
       
   481 
       
   482 void Generator::generateProperties()
       
   483 {
       
   484     //
       
   485     // specify get function, for compatibiliy we accept functions
       
   486     // returning pointers, or const char * for QByteArray.
       
   487     //
       
   488     for (int i = 0; i < cdef->propertyList.count(); ++i) {
       
   489         PropertyDef &p = cdef->propertyList[i];
       
   490         if (p.read.isEmpty())
       
   491             continue;
       
   492         for (int j = 0; j < cdef->publicList.count(); ++j) {
       
   493             const FunctionDef &f = cdef->publicList.at(j);
       
   494             if (f.name != p.read)
       
   495                 continue;
       
   496             if (!f.isConst) // get  functions must be const
       
   497                 continue;
       
   498             if (f.arguments.size()) // and must not take any arguments
       
   499                 continue;
       
   500             PropertyDef::Specification spec = PropertyDef::ValueSpec;
       
   501             QByteArray tmp = f.normalizedType;
       
   502             if (p.type == "QByteArray" && tmp == "const char *")
       
   503                     tmp = "QByteArray";
       
   504             if (tmp.left(6) == "const ")
       
   505                 tmp = tmp.mid(6);
       
   506             if (p.type != tmp && tmp.endsWith('*')) {
       
   507                 tmp.chop(1);
       
   508                 spec = PropertyDef::PointerSpec;
       
   509             } else if (f.type.name.endsWith('&')) { // raw type, not normalized type
       
   510                 spec = PropertyDef::ReferenceSpec;
       
   511             }
       
   512             if (p.type != tmp)
       
   513                 continue;
       
   514             p.gspec = spec;
       
   515             break;
       
   516         }
       
   517         if(!p.notify.isEmpty()) {
       
   518             int notifyId = -1;
       
   519             for (int j = 0; j < cdef->signalList.count(); ++j) {
       
   520                 const FunctionDef &f = cdef->signalList.at(j);
       
   521                 if(f.name != p.notify) {
       
   522                     continue;
       
   523                 } else {
       
   524                     notifyId = j /* Signal indexes start from 0 */;
       
   525                     break;
       
   526                 }
       
   527             }
       
   528             p.notifyId = notifyId;
       
   529         }
       
   530     }
       
   531 
       
   532     //
       
   533     // Create meta data
       
   534     //
       
   535 
       
   536     if (cdef->propertyList.count())
       
   537         fprintf(out, "\n // properties: name, type, flags\n");
       
   538     for (int i = 0; i < cdef->propertyList.count(); ++i) {
       
   539         const PropertyDef &p = cdef->propertyList.at(i);
       
   540         uint flags = Invalid;
       
   541         if (!isVariantType(p.type)) {
       
   542             flags |= EnumOrFlag;
       
   543         } else if (!isQRealType(p.type)) {
       
   544             flags |= qvariant_nameToType(p.type) << 24;
       
   545         }
       
   546         if (!p.read.isEmpty())
       
   547             flags |= Readable;
       
   548         if (!p.write.isEmpty()) {
       
   549             flags |= Writable;
       
   550             if (p.stdCppSet())
       
   551                 flags |= StdCppSet;
       
   552         }
       
   553         if (!p.reset.isEmpty())
       
   554             flags |= Resettable;
       
   555 
       
   556 //         if (p.override)
       
   557 //             flags |= Override;
       
   558 
       
   559         if (p.designable.isEmpty())
       
   560             flags |= ResolveDesignable;
       
   561         else if (p.designable != "false")
       
   562             flags |= Designable;
       
   563 
       
   564         if (p.scriptable.isEmpty())
       
   565             flags |= ResolveScriptable;
       
   566         else if (p.scriptable != "false")
       
   567             flags |= Scriptable;
       
   568 
       
   569         if (p.stored.isEmpty())
       
   570             flags |= ResolveStored;
       
   571         else if (p.stored != "false")
       
   572             flags |= Stored;
       
   573 
       
   574         if (p.editable.isEmpty())
       
   575             flags |= ResolveEditable;
       
   576         else if (p.editable != "false")
       
   577             flags |= Editable;
       
   578 
       
   579         if (p.user.isEmpty())
       
   580             flags |= ResolveUser;
       
   581         else if (p.user != "false")
       
   582             flags |= User;
       
   583 
       
   584         if (p.notifyId != -1)
       
   585             flags |= Notify;
       
   586 
       
   587         if (p.constant)
       
   588             flags |= Constant;
       
   589         if (p.final)
       
   590             flags |= Final;
       
   591 
       
   592         fprintf(out, "    %4d, %4d, ",
       
   593                 strreg(p.name),
       
   594                 strreg(p.type));
       
   595         if (!(flags >> 24) && isQRealType(p.type))
       
   596             fprintf(out, "(QMetaType::QReal << 24) | ");
       
   597         fprintf(out, "0x%.8x,\n", flags);
       
   598     }
       
   599 
       
   600     if(cdef->notifyableProperties) {
       
   601         fprintf(out, "\n // properties: notify_signal_id\n");
       
   602         for (int i = 0; i < cdef->propertyList.count(); ++i) {
       
   603             const PropertyDef &p = cdef->propertyList.at(i);
       
   604             if(p.notifyId == -1)
       
   605                 fprintf(out, "    %4d,\n",
       
   606                         0);
       
   607             else
       
   608                 fprintf(out, "    %4d,\n",
       
   609                         p.notifyId);
       
   610         }
       
   611     }
       
   612 }
       
   613 
       
   614 void Generator::generateEnums(int index)
       
   615 {
       
   616     if (cdef->enumDeclarations.isEmpty())
       
   617         return;
       
   618 
       
   619     fprintf(out, "\n // enums: name, flags, count, data\n");
       
   620     index += 4 * cdef->enumList.count();
       
   621     int i;
       
   622     for (i = 0; i < cdef->enumList.count(); ++i) {
       
   623         const EnumDef &e = cdef->enumList.at(i);
       
   624         fprintf(out, "    %4d, 0x%.1x, %4d, %4d,\n",
       
   625                  strreg(e.name),
       
   626                  cdef->enumDeclarations.value(e.name) ? 1 : 0,
       
   627                  e.values.count(),
       
   628                  index);
       
   629         index += e.values.count() * 2;
       
   630     }
       
   631 
       
   632     fprintf(out, "\n // enum data: key, value\n");
       
   633     for (i = 0; i < cdef->enumList.count(); ++i) {
       
   634         const EnumDef &e = cdef->enumList.at(i);
       
   635         for (int j = 0; j < e.values.count(); ++j) {
       
   636             const QByteArray &val = e.values.at(j);
       
   637             fprintf(out, "    %4d, uint(%s::%s),\n",
       
   638                     strreg(val),
       
   639                     cdef->qualified.constData(),
       
   640                     val.constData());
       
   641         }
       
   642     }
       
   643 }
       
   644 
       
   645 void Generator::generateMetacall()
       
   646 {
       
   647     bool isQObject = (cdef->classname == "QObject");
       
   648 
       
   649     fprintf(out, "\nint %s::qt_metacall(QMetaObject::Call _c, int _id, void **_a)\n{\n",
       
   650              cdef->qualified.constData());
       
   651 
       
   652     if (!purestSuperClass.isEmpty() && !isQObject) {
       
   653         QByteArray superClass = purestSuperClass;
       
   654         // workaround for VC6
       
   655         if (superClass.contains("::")) {
       
   656             fprintf(out, "    typedef %s QMocSuperClass;\n", superClass.constData());
       
   657             superClass = "QMocSuperClass";
       
   658         }
       
   659         fprintf(out, "    _id = %s::qt_metacall(_c, _id, _a);\n", superClass.constData());
       
   660     }
       
   661 
       
   662     fprintf(out, "    if (_id < 0)\n        return _id;\n");
       
   663     fprintf(out, "    ");
       
   664 
       
   665     bool needElse = false;
       
   666     QList<FunctionDef> methodList;
       
   667     methodList += cdef->signalList;
       
   668     methodList += cdef->slotList;
       
   669     methodList += cdef->methodList;
       
   670 
       
   671     if (methodList.size()) {
       
   672         needElse = true;
       
   673         fprintf(out, "if (_c == QMetaObject::InvokeMetaMethod) {\n        ");
       
   674         fprintf(out, "switch (_id) {\n");
       
   675         for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
       
   676             const FunctionDef &f = methodList.at(methodindex);
       
   677             fprintf(out, "        case %d: ", methodindex);
       
   678             if (f.normalizedType.size())
       
   679                 fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData());
       
   680             if (f.inPrivateClass.size())
       
   681                 fprintf(out, "%s->", f.inPrivateClass.constData());
       
   682             fprintf(out, "%s(", f.name.constData());
       
   683             int offset = 1;
       
   684             for (int j = 0; j < f.arguments.count(); ++j) {
       
   685                 const ArgumentDef &a = f.arguments.at(j);
       
   686                 if (j)
       
   687                     fprintf(out, ",");
       
   688                 fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++);
       
   689             }
       
   690             fprintf(out, ");");
       
   691             if (f.normalizedType.size())
       
   692                 fprintf(out, "\n            if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ",
       
   693                         noRef(f.normalizedType).constData());
       
   694             fprintf(out, " break;\n");
       
   695         }
       
   696         fprintf(out, "        default: ;\n");
       
   697         fprintf(out, "        }\n");
       
   698     }
       
   699     if (methodList.size())
       
   700         fprintf(out, "        _id -= %d;\n    }", methodList.size());
       
   701 
       
   702     if (cdef->propertyList.size()) {
       
   703         bool needGet = false;
       
   704         bool needTempVarForGet = false;
       
   705         bool needSet = false;
       
   706         bool needReset = false;
       
   707         bool needDesignable = false;
       
   708         bool needScriptable = false;
       
   709         bool needStored = false;
       
   710         bool needEditable = false;
       
   711         bool needUser = false;
       
   712         for (int i = 0; i < cdef->propertyList.size(); ++i) {
       
   713             const PropertyDef &p = cdef->propertyList.at(i);
       
   714             needGet |= !p.read.isEmpty();
       
   715             if (!p.read.isEmpty())
       
   716                 needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec
       
   717                                       && p.gspec != PropertyDef::ReferenceSpec);
       
   718 
       
   719             needSet |= !p.write.isEmpty();
       
   720             needReset |= !p.reset.isEmpty();
       
   721             needDesignable |= p.designable.endsWith(')');
       
   722             needScriptable |= p.scriptable.endsWith(')');
       
   723             needStored |= p.stored.endsWith(')');
       
   724             needEditable |= p.editable.endsWith(')');
       
   725             needUser |= p.user.endsWith(')');
       
   726         }
       
   727         bool needAnything = needGet
       
   728                             | needSet
       
   729                             | needReset
       
   730                             | needDesignable
       
   731                             | needScriptable
       
   732                             | needStored
       
   733                             | needEditable
       
   734                             | needUser;
       
   735         if (!needAnything)
       
   736             goto skip_properties;
       
   737         fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n     ");
       
   738 
       
   739         if (needElse)
       
   740             fprintf(out, " else ");
       
   741         fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
       
   742         if (needGet) {
       
   743             if (needTempVarForGet)
       
   744                 fprintf(out, "        void *_v = _a[0];\n");
       
   745             fprintf(out, "        switch (_id) {\n");
       
   746             for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
       
   747                 const PropertyDef &p = cdef->propertyList.at(propindex);
       
   748                 if (p.read.isEmpty())
       
   749                     continue;
       
   750                 if (p.gspec == PropertyDef::PointerSpec)
       
   751                     fprintf(out, "        case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s())); break;\n",
       
   752                             propindex, p.read.constData());
       
   753                 else if (p.gspec == PropertyDef::ReferenceSpec)
       
   754                     fprintf(out, "        case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s())); break;\n",
       
   755                             propindex, p.read.constData());
       
   756                 else if (cdef->enumDeclarations.value(p.type, false))
       
   757                     fprintf(out, "        case %d: *reinterpret_cast<int*>(_v) = QFlag(%s()); break;\n",
       
   758                             propindex, p.read.constData());
       
   759                 else
       
   760                     fprintf(out, "        case %d: *reinterpret_cast< %s*>(_v) = %s(); break;\n",
       
   761                             propindex, p.type.constData(), p.read.constData());
       
   762             }
       
   763             fprintf(out, "        }\n");
       
   764         }
       
   765 
       
   766         fprintf(out,
       
   767                 "        _id -= %d;\n"
       
   768                 "    }", cdef->propertyList.count());
       
   769 
       
   770         fprintf(out, " else ");
       
   771         fprintf(out, "if (_c == QMetaObject::WriteProperty) {\n");
       
   772 
       
   773         if (needSet) {
       
   774             fprintf(out, "        void *_v = _a[0];\n");
       
   775             fprintf(out, "        switch (_id) {\n");
       
   776             for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
       
   777                 const PropertyDef &p = cdef->propertyList.at(propindex);
       
   778                 if (p.write.isEmpty())
       
   779                     continue;
       
   780                 if (cdef->enumDeclarations.value(p.type, false)) {
       
   781                     fprintf(out, "        case %d: %s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
       
   782                             propindex, p.write.constData());
       
   783                 } else {
       
   784                     fprintf(out, "        case %d: %s(*reinterpret_cast< %s*>(_v)); break;\n",
       
   785                             propindex, p.write.constData(), p.type.constData());
       
   786                 }
       
   787             }
       
   788             fprintf(out, "        }\n");
       
   789         }
       
   790 
       
   791         fprintf(out,
       
   792                 "        _id -= %d;\n"
       
   793                 "    }", cdef->propertyList.count());
       
   794 
       
   795         fprintf(out, " else ");
       
   796         fprintf(out, "if (_c == QMetaObject::ResetProperty) {\n");
       
   797         if (needReset) {
       
   798             fprintf(out, "        switch (_id) {\n");
       
   799             for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
       
   800                 const PropertyDef &p = cdef->propertyList.at(propindex);
       
   801                 if (!p.reset.endsWith(')'))
       
   802                     continue;
       
   803                 fprintf(out, "        case %d: %s; break;\n",
       
   804                         propindex, p.reset.constData());
       
   805             }
       
   806             fprintf(out, "        }\n");
       
   807         }
       
   808         fprintf(out,
       
   809                 "        _id -= %d;\n"
       
   810                 "    }", cdef->propertyList.count());
       
   811 
       
   812         fprintf(out, " else ");
       
   813         fprintf(out, "if (_c == QMetaObject::QueryPropertyDesignable) {\n");
       
   814         if (needDesignable) {
       
   815             fprintf(out, "        bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
       
   816             fprintf(out, "        switch (_id) {\n");
       
   817             for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
       
   818                 const PropertyDef &p = cdef->propertyList.at(propindex);
       
   819                 if (!p.designable.endsWith(')'))
       
   820                     continue;
       
   821                 fprintf(out, "        case %d: *_b = %s; break;\n",
       
   822                          propindex, p.designable.constData());
       
   823             }
       
   824             fprintf(out, "        }\n");
       
   825         }
       
   826         fprintf(out,
       
   827                 "        _id -= %d;\n"
       
   828                 "    }", cdef->propertyList.count());
       
   829 
       
   830         fprintf(out, " else ");
       
   831         fprintf(out, "if (_c == QMetaObject::QueryPropertyScriptable) {\n");
       
   832         if (needScriptable) {
       
   833             fprintf(out, "        bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
       
   834             fprintf(out, "        switch (_id) {\n");
       
   835             for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
       
   836                 const PropertyDef &p = cdef->propertyList.at(propindex);
       
   837                 if (!p.scriptable.endsWith(')'))
       
   838                     continue;
       
   839                 fprintf(out, "        case %d: *_b = %s; break;\n",
       
   840                          propindex, p.scriptable.constData());
       
   841             }
       
   842             fprintf(out, "        }\n");
       
   843         }
       
   844         fprintf(out,
       
   845                 "        _id -= %d;\n"
       
   846                 "    }", cdef->propertyList.count());
       
   847 
       
   848         fprintf(out, " else ");
       
   849         fprintf(out, "if (_c == QMetaObject::QueryPropertyStored) {\n");
       
   850         if (needStored) {
       
   851             fprintf(out, "        bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
       
   852             fprintf(out, "        switch (_id) {\n");
       
   853             for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
       
   854                 const PropertyDef &p = cdef->propertyList.at(propindex);
       
   855                 if (!p.stored.endsWith(')'))
       
   856                     continue;
       
   857                 fprintf(out, "        case %d: *_b = %s; break;\n",
       
   858                          propindex, p.stored.constData());
       
   859             }
       
   860             fprintf(out, "        }\n");
       
   861         }
       
   862         fprintf(out,
       
   863                 "        _id -= %d;\n"
       
   864                 "    }", cdef->propertyList.count());
       
   865 
       
   866         fprintf(out, " else ");
       
   867         fprintf(out, "if (_c == QMetaObject::QueryPropertyEditable) {\n");
       
   868         if (needEditable) {
       
   869             fprintf(out, "        bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
       
   870             fprintf(out, "        switch (_id) {\n");
       
   871             for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
       
   872                 const PropertyDef &p = cdef->propertyList.at(propindex);
       
   873                 if (!p.editable.endsWith(')'))
       
   874                     continue;
       
   875                 fprintf(out, "        case %d: *_b = %s; break;\n",
       
   876                          propindex, p.editable.constData());
       
   877             }
       
   878             fprintf(out, "        }\n");
       
   879         }
       
   880         fprintf(out,
       
   881                 "        _id -= %d;\n"
       
   882                 "    }", cdef->propertyList.count());
       
   883 
       
   884 
       
   885         fprintf(out, " else ");
       
   886         fprintf(out, "if (_c == QMetaObject::QueryPropertyUser) {\n");
       
   887         if (needUser) {
       
   888             fprintf(out, "        bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
       
   889             fprintf(out, "        switch (_id) {\n");
       
   890             for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
       
   891                 const PropertyDef &p = cdef->propertyList.at(propindex);
       
   892                 if (!p.user.endsWith(')'))
       
   893                     continue;
       
   894                 fprintf(out, "        case %d: *_b = %s; break;\n",
       
   895                          propindex, p.user.constData());
       
   896             }
       
   897             fprintf(out, "        }\n");
       
   898         }
       
   899         fprintf(out,
       
   900                 "        _id -= %d;\n"
       
   901                 "    }", cdef->propertyList.count());
       
   902 
       
   903 
       
   904         fprintf(out, "\n#endif // QT_NO_PROPERTIES");
       
   905     }
       
   906  skip_properties:
       
   907     if (methodList.size() || cdef->signalList.size() || cdef->propertyList.size())
       
   908         fprintf(out, "\n    ");
       
   909     fprintf(out,"return _id;\n}\n");
       
   910 }
       
   911 
       
   912 void Generator::generateStaticMetacall(const QByteArray &prefix)
       
   913 {
       
   914     bool isQObject = (cdef->classname == "QObject");
       
   915 
       
   916     fprintf(out, "static int %s_qt_static_metacall(QMetaObject::Call _c, int _id, void **_a)\n{\n",
       
   917             prefix.constData());
       
   918 
       
   919     fprintf(out, "    if (_c == QMetaObject::CreateInstance) {\n");
       
   920     fprintf(out, "        switch (_id) {\n");
       
   921     for (int ctorindex = 0; ctorindex < cdef->constructorList.count(); ++ctorindex) {
       
   922         fprintf(out, "        case %d: { %s *_r = new %s(", ctorindex,
       
   923                 cdef->qualified.constData(), cdef->qualified.constData());
       
   924         const FunctionDef &f = cdef->constructorList.at(ctorindex);
       
   925         int offset = 1;
       
   926         for (int j = 0; j < f.arguments.count(); ++j) {
       
   927             const ArgumentDef &a = f.arguments.at(j);
       
   928             if (j)
       
   929                 fprintf(out, ",");
       
   930             fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))", a.typeNameForCast.constData(), offset++);
       
   931         }
       
   932         fprintf(out, ");\n");
       
   933         fprintf(out, "            if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;\n");
       
   934     }
       
   935     fprintf(out, "        }\n");
       
   936     fprintf(out, "        _id -= %d;\n", cdef->constructorList.count());
       
   937     fprintf(out, "        return _id;\n");
       
   938     fprintf(out, "    }\n");
       
   939 
       
   940     if (!isQObject)
       
   941         fprintf(out, "    _id = %s::staticMetaObject.superClass()->static_metacall(_c, _id, _a);\n", cdef->qualified.constData());
       
   942 
       
   943     fprintf(out, "    if (_id < 0)\n        return _id;\n");
       
   944 
       
   945     fprintf(out, "    return _id;\n");
       
   946     fprintf(out, "}\n\n");
       
   947 }
       
   948 
       
   949 void Generator::generateSignal(FunctionDef *def,int index)
       
   950 {
       
   951     if (def->wasCloned || def->isAbstract)
       
   952         return;
       
   953     fprintf(out, "\n// SIGNAL %d\n%s %s::%s(",
       
   954             index, def->type.name.constData(), cdef->qualified.constData(), def->name.constData());
       
   955 
       
   956     QByteArray thisPtr = "this";
       
   957     const char *constQualifier = "";
       
   958 
       
   959     if (def->isConst) {
       
   960         thisPtr = "const_cast< ";
       
   961         thisPtr += cdef->qualified;
       
   962         thisPtr += " *>(this)";
       
   963         constQualifier = "const";
       
   964     }
       
   965 
       
   966     if (def->arguments.isEmpty() && def->normalizedType.isEmpty()) {
       
   967         fprintf(out, ")%s\n{\n"
       
   968                 "    QMetaObject::activate(%s, &staticMetaObject, %d, 0);\n"
       
   969                 "}\n", constQualifier, thisPtr.constData(), index);
       
   970         return;
       
   971     }
       
   972 
       
   973     int offset = 1;
       
   974     for (int j = 0; j < def->arguments.count(); ++j) {
       
   975         const ArgumentDef &a = def->arguments.at(j);
       
   976         if (j)
       
   977             fprintf(out, ", ");
       
   978         fprintf(out, "%s _t%d%s", a.type.name.constData(), offset++, a.rightType.constData());
       
   979     }
       
   980     fprintf(out, ")%s\n{\n", constQualifier);
       
   981     if (def->type.name.size() && def->normalizedType.size())
       
   982         fprintf(out, "    %s _t0;\n", noRef(def->normalizedType).constData());
       
   983 
       
   984     fprintf(out, "    void *_a[] = { ");
       
   985     if (def->normalizedType.isEmpty()) {
       
   986         fprintf(out, "0");
       
   987     } else {
       
   988         if (def->returnTypeIsVolatile)
       
   989              fprintf(out, "const_cast<void*>(reinterpret_cast<const volatile void*>(&_t0))");
       
   990         else
       
   991              fprintf(out, "const_cast<void*>(reinterpret_cast<const void*>(&_t0))");
       
   992     }
       
   993     int i;
       
   994     for (i = 1; i < offset; ++i)
       
   995         if (def->arguments.at(i - 1).type.isVolatile)
       
   996             fprintf(out, ", const_cast<void*>(reinterpret_cast<const volatile void*>(&_t%d))", i);
       
   997         else
       
   998             fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(&_t%d))", i);
       
   999     fprintf(out, " };\n");
       
  1000     fprintf(out, "    QMetaObject::activate(%s, &staticMetaObject, %d, _a);\n", thisPtr.constData(), index);
       
  1001     if (def->normalizedType.size())
       
  1002         fprintf(out, "    return _t0;\n");
       
  1003     fprintf(out, "}\n");
       
  1004 }
       
  1005 
       
  1006 //
       
  1007 // Functions used when generating QMetaObject directly
       
  1008 //
       
  1009 // Much of this code is copied from the corresponding
       
  1010 // C++ code-generating functions; we can change the
       
  1011 // two generators so that more of the code is shared.
       
  1012 // The key difference from the C++ code generator is
       
  1013 // that instead of calling fprintf(), we append bytes
       
  1014 // to a buffer.
       
  1015 //
       
  1016 
       
  1017 QMetaObject *Generator::generateMetaObject(bool ignoreProperties)
       
  1018 {
       
  1019 //
       
  1020 // build the data array
       
  1021 //
       
  1022 
       
  1023     // filter out undeclared enumerators and sets
       
  1024     {
       
  1025         QList<EnumDef> enumList;
       
  1026         for (int i = 0; i < cdef->enumList.count(); ++i) {
       
  1027             EnumDef def = cdef->enumList.at(i);
       
  1028             if (cdef->enumDeclarations.contains(def.name)) {
       
  1029                 enumList += def;
       
  1030             }
       
  1031             QByteArray alias = cdef->flagAliases.value(def.name);
       
  1032             if (cdef->enumDeclarations.contains(alias)) {
       
  1033                 def.name = alias;
       
  1034                 enumList += def;
       
  1035             }
       
  1036         }
       
  1037         cdef->enumList = enumList;
       
  1038     }
       
  1039 
       
  1040     int index = 10;
       
  1041     meta_data
       
  1042         << 1 // revision
       
  1043         << strreg(cdef->qualified) // classname
       
  1044         << cdef->classInfoList.count() << (cdef->classInfoList.count() ? index : 0) // classinfo
       
  1045         ;
       
  1046     index += cdef->classInfoList.count() * 2;
       
  1047 
       
  1048     int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count();
       
  1049     meta_data << methodCount << (methodCount ? index : 0); // methods
       
  1050     index += methodCount * 5;
       
  1051     if (!ignoreProperties) {
       
  1052         meta_data << cdef->propertyList.count() << (cdef->propertyList.count() ? index : 0); // properties
       
  1053         index += cdef->propertyList.count() * 3;
       
  1054     } else {
       
  1055         meta_data << 0 << 0; // properties
       
  1056     }
       
  1057     meta_data << cdef->enumList.count() << (cdef->enumList.count() ? index : 0); // enums/sets
       
  1058 
       
  1059 //
       
  1060 // Build classinfo array
       
  1061 //
       
  1062     _generateClassInfos();
       
  1063 
       
  1064 //
       
  1065 // Build signals array first, otherwise the signal indices would be wrong
       
  1066 //
       
  1067     _generateFunctions(cdef->signalList, MethodSignal);
       
  1068 
       
  1069 //
       
  1070 // Build slots array
       
  1071 //
       
  1072     _generateFunctions(cdef->slotList, MethodSlot);
       
  1073 
       
  1074 //
       
  1075 // Build method array
       
  1076 //
       
  1077     _generateFunctions(cdef->methodList, MethodMethod);
       
  1078 
       
  1079 
       
  1080 //
       
  1081 // Build property array
       
  1082 //
       
  1083     if (!ignoreProperties)
       
  1084         _generateProperties();
       
  1085 
       
  1086 //
       
  1087 // Build enums array
       
  1088 //
       
  1089     _generateEnums(index);
       
  1090 
       
  1091 //
       
  1092 // Terminate data array
       
  1093 //
       
  1094     meta_data << 0;
       
  1095 
       
  1096 //
       
  1097 // Build stringdata array
       
  1098 //
       
  1099     QVector<char> string_data;
       
  1100     for (int i = 0; i < strings.size(); ++i) {
       
  1101         const char *s = strings.at(i).constData();
       
  1102         char c;
       
  1103         do {
       
  1104             c = *(s++);
       
  1105             string_data << c;
       
  1106         } while (c != '\0');
       
  1107     }
       
  1108 
       
  1109 //
       
  1110 // Finally create and initialize the static meta object
       
  1111 //
       
  1112     const int meta_object_offset = 0;
       
  1113     const int meta_object_size = sizeof(QMetaObject);
       
  1114     const int meta_data_offset = meta_object_offset + meta_object_size;
       
  1115     const int meta_data_size = meta_data.count() * sizeof(uint);
       
  1116     const int string_data_offset = meta_data_offset + meta_data_size;
       
  1117     const int string_data_size = string_data.count();
       
  1118     const int total_size = string_data_offset + string_data_size;
       
  1119 
       
  1120     char *blob = new char[total_size];
       
  1121 
       
  1122     char *string_data_output = blob + string_data_offset;
       
  1123     const char *string_data_src = string_data.constData();
       
  1124     for (int i = 0; i < string_data.count(); ++i)
       
  1125         string_data_output[i] = string_data_src[i];
       
  1126 
       
  1127     uint *meta_data_output = reinterpret_cast<uint *>(blob + meta_data_offset);
       
  1128     const uint *meta_data_src = meta_data.constData();
       
  1129     for (int i = 0; i < meta_data.count(); ++i)
       
  1130         meta_data_output[i] = meta_data_src[i];
       
  1131 
       
  1132     QMetaObject *meta_object = new (blob + meta_object_offset)QMetaObject;
       
  1133     meta_object->d.superdata = 0;
       
  1134     meta_object->d.stringdata = string_data_output;
       
  1135     meta_object->d.data = meta_data_output;
       
  1136     meta_object->d.extradata = 0;
       
  1137     return meta_object;
       
  1138 }
       
  1139 
       
  1140 void Generator::_generateClassInfos()
       
  1141 {
       
  1142     for (int i = 0; i < cdef->classInfoList.size(); ++i) {
       
  1143         const ClassInfoDef &c = cdef->classInfoList.at(i);
       
  1144         meta_data << strreg(c.name) << strreg(c.value);
       
  1145     }
       
  1146 }
       
  1147 
       
  1148 void Generator::_generateFunctions(QList<FunctionDef> &list, int type)
       
  1149 {
       
  1150     for (int i = 0; i < list.count(); ++i) {
       
  1151         const FunctionDef &f = list.at(i);
       
  1152 
       
  1153         QByteArray sig = f.name + '(';
       
  1154         QByteArray arguments;
       
  1155 
       
  1156         for (int j = 0; j < f.arguments.count(); ++j) {
       
  1157             const ArgumentDef &a = f.arguments.at(j);
       
  1158             if (j) {
       
  1159                 sig += ',';
       
  1160                 arguments += ',';
       
  1161             }
       
  1162             sig += a.normalizedType;
       
  1163             arguments += a.name;
       
  1164         }
       
  1165         sig += ')';
       
  1166 
       
  1167         char flags = type;
       
  1168         if (f.access == FunctionDef::Private)
       
  1169             flags |= AccessPrivate;
       
  1170         else if (f.access == FunctionDef::Public)
       
  1171             flags |= AccessPublic;
       
  1172         else if (f.access == FunctionDef::Protected)
       
  1173             flags |= AccessProtected;
       
  1174         if (f.access == FunctionDef::Private)
       
  1175             flags |= AccessPrivate;
       
  1176         else if (f.access == FunctionDef::Public)
       
  1177             flags |= AccessPublic;
       
  1178         else if (f.access == FunctionDef::Protected)
       
  1179             flags |= AccessProtected;
       
  1180         if (f.isCompat)
       
  1181             flags |= MethodCompatibility;
       
  1182         if (f.wasCloned)
       
  1183             flags |= MethodCloned;
       
  1184         if (f.isScriptable)
       
  1185             flags |= MethodScriptable;
       
  1186 
       
  1187         meta_data << strreg(sig)
       
  1188                   << strreg(arguments)
       
  1189                   << strreg(f.normalizedType)
       
  1190                   << strreg(f.tag)
       
  1191                   << flags;
       
  1192     }
       
  1193 }
       
  1194 
       
  1195 void Generator::_generateEnums(int index)
       
  1196 {
       
  1197     index += 4 * cdef->enumList.count();
       
  1198     int i;
       
  1199     for (i = 0; i < cdef->enumList.count(); ++i) {
       
  1200         const EnumDef &e = cdef->enumList.at(i);
       
  1201         meta_data << strreg(e.name) << (cdef->enumDeclarations.value(e.name) ? 1 : 0)
       
  1202                   << e.values.count() << index;
       
  1203         index += e.values.count() * 2;
       
  1204     }
       
  1205 
       
  1206     for (i = 0; i < cdef->enumList.count(); ++i) {
       
  1207         const EnumDef &e = cdef->enumList.at(i);
       
  1208         for (int j = 0; j < e.values.count(); ++j) {
       
  1209             const QByteArray &val = e.values.at(j);
       
  1210             meta_data << strreg(val) << 0; // we don't know the value itself
       
  1211         }
       
  1212     }
       
  1213 }
       
  1214 
       
  1215 void Generator::_generateProperties()
       
  1216 {
       
  1217     //
       
  1218     // specify get function, for compatibiliy we accept functions
       
  1219     // returning pointers, or const char * for QByteArray.
       
  1220     //
       
  1221     for (int i = 0; i < cdef->propertyList.count(); ++i) {
       
  1222         PropertyDef &p = cdef->propertyList[i];
       
  1223         if (p.read.isEmpty())
       
  1224             continue;
       
  1225         for (int j = 0; j < cdef->publicList.count(); ++j) {
       
  1226             const FunctionDef &f = cdef->publicList.at(j);
       
  1227             if (f.name != p.read)
       
  1228                 continue;
       
  1229             if (!f.isConst) // get  functions must be const
       
  1230                 continue;
       
  1231             if (f.arguments.size()) // and must not take any arguments
       
  1232                 continue;
       
  1233             PropertyDef::Specification spec = PropertyDef::ValueSpec;
       
  1234             QByteArray tmp = f.normalizedType;
       
  1235             if (p.type == "QByteArray" && tmp == "const char *")
       
  1236                     tmp = "QByteArray";
       
  1237             if (tmp.left(6) == "const ")
       
  1238                 tmp = tmp.mid(6);
       
  1239             if (p.type != tmp && tmp.endsWith('*')) {
       
  1240                 tmp.chop(1);
       
  1241                 spec = PropertyDef::PointerSpec;
       
  1242             } else if (f.type.name.endsWith('&')) { // raw type, not normalized type
       
  1243                 spec = PropertyDef::ReferenceSpec;
       
  1244             }
       
  1245             if (p.type != tmp)
       
  1246                 continue;
       
  1247             p.gspec = spec;
       
  1248             break;
       
  1249         }
       
  1250     }
       
  1251 
       
  1252 
       
  1253     //
       
  1254     // Create meta data
       
  1255     //
       
  1256 
       
  1257     for (int i = 0; i < cdef->propertyList.count(); ++i) {
       
  1258         const PropertyDef &p = cdef->propertyList.at(i);
       
  1259         uint flags = Invalid;
       
  1260         if (!isVariantType(p.type)) {
       
  1261             flags |= EnumOrFlag;
       
  1262         } else {
       
  1263             flags |= qvariant_nameToType(p.type) << 24;
       
  1264         }
       
  1265         if (!p.read.isEmpty())
       
  1266             flags |= Readable;
       
  1267         if (!p.write.isEmpty()) {
       
  1268             flags |= Writable;
       
  1269             if (p.stdCppSet())
       
  1270                 flags |= StdCppSet;
       
  1271         }
       
  1272         if (!p.reset.isEmpty())
       
  1273             flags |= Resettable;
       
  1274 
       
  1275 //         if (p.override)
       
  1276 //             flags |= Override;
       
  1277 
       
  1278         if (p.designable.isEmpty())
       
  1279             flags |= ResolveDesignable;
       
  1280         else if (p.designable != "false")
       
  1281             flags |= Designable;
       
  1282 
       
  1283         if (p.scriptable.isEmpty())
       
  1284             flags |= ResolveScriptable;
       
  1285         else if (p.scriptable != "false")
       
  1286             flags |= Scriptable;
       
  1287 
       
  1288         if (p.stored.isEmpty())
       
  1289             flags |= ResolveStored;
       
  1290         else if (p.stored != "false")
       
  1291             flags |= Stored;
       
  1292 
       
  1293         if (p.editable.isEmpty())
       
  1294             flags |= ResolveEditable;
       
  1295         else if (p.editable != "false")
       
  1296             flags |= Editable;
       
  1297 
       
  1298         if (p.user.isEmpty())
       
  1299             flags |= ResolveUser;
       
  1300         else if (p.user != "false")
       
  1301             flags |= User;
       
  1302 
       
  1303         meta_data << strreg(p.name) << strreg(p.type) << flags;
       
  1304     }
       
  1305 }
       
  1306 
       
  1307 QT_END_NAMESPACE