/**************************************************************************** ** ** Parser and code generator for meta object compiler ** ** Created : 930417 ** ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. ** ** This file is part of the TQt GUI Toolkit. ** ** This file may be used under the terms of the GNU General ** Public License versions 2.0 or 3.0 as published by the Free ** Software Foundation and appearing in the files LICENSE.GPL2 ** and LICENSE.GPL3 included in the packaging of this file. ** Alternatively you may (at your option) use any later version ** of the GNU General Public License if such license has been ** publicly approved by Trolltech ASA (or its successors, if any) ** and the KDE Free TQt Foundation. ** ** Please review the following information to ensure GNU General ** Public Licensing retquirements will be met: ** http://trolltech.com/products/qt/licenses/licensing/opensource/. ** If you are unsure which license is appropriate for your use, please ** review the following information: ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview ** or contact the sales department at sales@trolltech.com. ** ** This file may be used under the terms of the Q Public License as ** defined by Trolltech ASA and appearing in the file LICENSE.TQPL ** included in the packaging of this file. Licensees holding valid TQt ** Commercial licenses may use this file in accordance with the TQt ** Commercial License Agreement provided with the Software. ** ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted ** herein. ** ** -------------------------------------------------------------------------- ** ** This compiler reads a C++ header file with class definitions and ouputs ** C++ code to build a meta class. The meta data includes public methods ** (not constructors, destructors or operator functions), signals and slot ** definitions. The output file should be compiled and linked into the ** target application. ** ** C++ header files are assumed to have correct syntax, and we are therefore ** doing less strict checking than C++ compilers. ** ** The C++ grammar has been adopted from the "The Annotated C++ Reference ** Manual" (ARM), by Ellis and Stroustrup (Addison Wesley, 1992). ** ** Notice that this code is not possible to compile with GNU bison, instead ** use standard AT&T yacc or Berkeley yacc. *****************************************************************************/ %{ #define MOC_YACC_CODE void yyerror( const char *msg ); #include "qplatformdefs.h" #include "qasciidict.h" #include "qdatetime.h" #include "qdict.h" #include "qfile.h" #include "qdir.h" #include "qptrlist.h" #include "qregexp.h" #include "qstrlist.h" #ifdef MOC_MWERKS_PLUGIN # ifdef Q_OS_MACX # undef OLD_DEBUG # ifdef DEBUG # define OLD_DEBUG DEBUG # undef DEBUG # endif # define DEBUG 0 # ifndef __IMAGECAPTURE__ # define __IMAGECAPTURE__ # endif # include # endif # include "mwerks_mac.h" #endif #include #include #include #if defined CONST #undef CONST #endif #if defined VOID #undef VOID #endif bool isEnumType( const char* type ); int enumIndex( const char* type ); bool isVariantType( const char* type ); int qvariant_nameToType( const char* name ); static void init(); // initialize static void initClass(); // prepare for new class static void generateClass(); // generate C++ code for class static void initExpression(); // prepare for new expression static void enterNameSpace( const char *name = 0 ); static void leaveNameSpace(); static void selectOutsideClassState(); static void registerClassInNamespace(); static bool suppress_func_warn = FALSE; static void func_warn( const char *msg ); static void moc_warn( const char *msg ); static void moc_err( const char *s ); static void moc_err( const char *s1, const char *s2 ); static void operatorError(); static void checkPropertyName( const char* ident ); static const char* const utype_map[] = { "bool", "int", "double", "TQString", "TQVariant", 0 }; inline bool isIdentChar( char x ) { // Avoid bug in isalnum return x == '_' || (x >= '0' && x <= '9') || (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z'); } bool validUType( TQCString ctype ) { if ( ctype.left(6) == "const " ) ctype = ctype.mid( 6, ctype.length() - 6 ); if ( ctype.right(1) == "&" ) ctype = ctype.left( ctype.length() - 1 ); else if ( ctype.right(1) == "*" ) return TRUE; int i = -1; while ( utype_map[++i] ) if ( ctype == utype_map[i] ) return TRUE; return isEnumType( ctype ); } TQCString castToUType( TQCString ctype ) { if ( ctype.right(1) == "&" ) ctype = ctype.left( ctype.length() - 1 ); if( ctype.right(1) == "]") { int lb = ctype.findRev('['); if(lb != -1) ctype = ctype.left(lb) + "*"; } return ctype; } TQCString rawUType( TQCString ctype ) { ctype = castToUType( ctype ); if ( ctype.left(6) == "const " ) ctype = ctype.mid( 6, ctype.length() - 6 ); return ctype; } TQCString uType( TQCString ctype ) { if ( !validUType( ctype ) ) { if ( isVariantType( rawUType(ctype) ) ) return "varptr"; else return "ptr"; } if ( ctype.left(6) == "const " ) ctype = ctype.mid( 6, ctype.length() - 6 ); if ( ctype.right(1) == "&" ) { ctype = ctype.left( ctype.length() - 1 ); } else if ( ctype.right(1) == "*" ) { TQCString raw = ctype.left( ctype.length() - 1 ); ctype = "ptr"; if ( raw == "char" ) ctype = "charstar"; else if ( raw == "TQUnknownInterface" ) ctype = "iface"; else if ( raw == "TQDispatchInterface" ) ctype = "idisp"; else if ( isVariantType( raw ) ) ctype = "varptr"; } if ( isEnumType( ctype ) ) ctype = "enum"; return ctype; } bool isInOut( TQCString ctype ) { if ( ctype.left(6) == "const " ) return FALSE; if ( ctype.right(1) == "&" ) return TRUE; if ( ctype.right(2) == "**" ) return TRUE; return FALSE; } TQCString uTypeExtra( TQCString ctype ) { TQCString typeExtra = "0"; if ( !validUType( ctype ) ) { if ( isVariantType( rawUType(ctype) ) ) typeExtra.sprintf("\"\\x%02x\"", qvariant_nameToType( rawUType(ctype) ) ); else typeExtra.sprintf( "\"%s\"", rawUType(ctype).data() ); return typeExtra; } if ( ctype.left(6) == "const " ) ctype = ctype.mid( 6, ctype.length() - 6 ); if ( ctype.right(1) == "&" ) ctype = ctype.left( ctype.length() - 1 ); if ( ctype.right(1) == "*" ) { TQCString raw = ctype.left( ctype.length() - 1 ); ctype = "ptr"; if ( raw == "char" ) ; else if ( isVariantType( raw ) ) typeExtra.sprintf("\"\\x%02x\"", qvariant_nameToType( raw ) ); else typeExtra.sprintf( "\"%s\"", raw.stripWhiteSpace().data() ); } else if ( isEnumType( ctype ) ) { int idx = enumIndex( ctype ); if ( idx >= 0 ) { typeExtra.sprintf( "&enum_tbl[%d]", enumIndex( ctype ) ); } else { typeExtra.sprintf( "parentObject->enumerator(\"%s\", TRUE )", ctype.data() ); } typeExtra = "\n#ifndef QT_NO_PROPERTIES\n\t " + typeExtra + "\n#else" "\n\t 0" "\n#endif // QT_NO_PROPERTIES\n\t "; } return typeExtra; } /* Attention! This table is copied from qvariant.cpp. If you change one, change both. */ static const int ntypes = 35; static const char* const type_map[ntypes] = { 0, "TQMap", "TQValueList", "TQString", "TQStringList", "TQFont", "TQPixmap", "TQBrush", "TQRect", "TQSize", "TQColor", "TQPalette", "TQColorGroup", "TQIconSet", "TQPoint", "TQImage", "int", "uint", "bool", "double", "TQCString", "TQPointArray", "TQRegion", "TQBitmap", "TQCursor", "TQSizePolicy", "TQDate", "TQTime", "TQDateTime", "TQByteArray", "TQBitArray", "TQKeySequence", "TQPen", "Q_LLONG", "Q_ULLONG" }; int qvariant_nameToType( const char* name ) { for ( int i = 0; i < ntypes; i++ ) { if ( !qstrcmp( type_map[i], name ) ) return i; } return 0; } /* Returns TRUE if the type is a TQVariant types. */ bool isVariantType( const char* type ) { return qvariant_nameToType( type ) != 0; } /* Replaces '>>' with '> >' (as in 'TQValueList >'). This function must be called to produce valid C++ code. However, the string representation still uses '>>'. */ void fixRightAngles( TQCString *str ) { str->replace( TQRegExp(">>"), "> >" ); } static TQCString rmWS( const char * ); enum Access { Private, Protected, Public }; class Argument // single arg meta data { public: Argument( const char *left, const char *right, const char* argName = 0, bool isDefaultArgument = FALSE ) { leftType = rmWS( left ); rightType = rmWS( right ); if ( leftType == "void" && rightType.isEmpty() ) leftType = ""; int len = leftType.length(); /* Convert 'char const *' into 'const char *'. Start at index 1, not 0, because 'const char *' is already OK. */ for ( int i = 1; i < len; i++ ) { if ( leftType[i] == 'c' && strncmp(leftType.data() + i + 1, "onst", 4) == 0 && (i + 5 >= len || !isIdentChar(leftType[i + 5])) && !isIdentChar(i-1) ) { leftType.remove( i, 5 ); if ( leftType[i - 1] == ' ' ) leftType.remove( i - 1, 1 ); leftType.prepend( "const " ); break; } /* We musn't convert 'char * const *' into 'const char **' and we must beware of 'Bar'. */ if ( leftType[i] == '&' || leftType[i] == '*' || leftType[i] == '<' ) break; } name = argName; isDefault = isDefaultArgument; } TQCString leftType; TQCString rightType; TQCString name; bool isDefault; }; class ArgList : public TQPtrList { // member function arg list public: ArgList() { setAutoDelete( TRUE ); } ~ArgList() { clear(); } /* the clone has one default argument less, the orignal has all default arguments removed */ ArgList* magicClone() { ArgList* l = new ArgList; bool firstDefault = FALSE; for ( first(); current(); next() ) { bool isDefault = current()->isDefault; if ( !firstDefault && isDefault ) { isDefault = FALSE; firstDefault = TRUE; } l->append( new Argument( current()->leftType, current()->rightType, current()->name, isDefault ) ); } for ( first(); current(); ) { if ( current()->isDefault ) remove(); else next(); } return l; } bool hasDefaultArguments() { for ( Argument* a = first(); a; a = next() ) { if ( a->isDefault ) return TRUE; } return FALSE; } }; struct Function // member function meta data { Access access; TQCString qualifier; // const or volatile TQCString name; TQCString type; TQCString signature; int lineNo; ArgList *args; Function() { args=0;} ~Function() { delete args; } const char* accessAsString() { switch ( access ) { case Private: return "Private"; case Protected: return "Protected"; default: return "Public"; } } }; class FuncList : public TQPtrList { // list of member functions public: FuncList( bool autoDelete = FALSE ) { setAutoDelete( autoDelete ); } FuncList find( const char* name ) { FuncList result; for ( TQPtrListIterator it(*this); it.current(); ++it ) { if ( it.current()->name == name ) result.append( it.current() ); } return result; } }; class Enum : public TQStrList { public: TQCString name; bool set; }; class EnumList : public TQPtrList { // list of property enums public: EnumList() { setAutoDelete(TRUE); } }; struct Property { Property( int l, const char* t, const char* n, const char* s, const char* g, const char* r, const TQCString& st, const TQCString& d, const TQCString& sc, bool ov ) : lineNo(l), type(t), name(n), set(s), get(g), reset(r), setfunc(0), getfunc(0), sspec(Unspecified), gspec(Unspecified), stored( st ), designable( d ), scriptable( sc ), override( ov ), oredEnum( -1 ) { /* The Q_PROPERTY construct cannot contain any commas, since commas separate macro arguments. We therefore expect users to type "TQMap" instead of "TQMap". For coherence, we also expect the same for TQValueList, the other template class supported by TQVariant. */ if ( type == "TQMap" ) { type = "TQMap"; } else if ( type == "TQValueList" ) { type = "TQValueList"; } else if ( type == "LongLong" ) { type = "Q_LLONG"; } else if ( type == "ULongLong" ) { type = "Q_ULLONG"; } } int lineNo; TQCString type; TQCString name; TQCString set; TQCString get; TQCString reset; TQCString stored; TQCString designable; TQCString scriptable; bool override; Function* setfunc; Function* getfunc; int oredEnum; // If the enums item may be ored. That means the data type is int. // Allowed values are 1 (True), 0 (False), and -1 (Unset) TQCString enumsettype; // contains the set function type in case of oredEnum TQCString enumgettype; // contains the get function type in case of oredEnum enum Specification { Unspecified, Class, Reference, Pointer, ConstCharStar }; Specification sspec; Specification gspec; bool stdSet() { TQCString s = "set"; s += toupper( name[0] ); s += name.mid( 1 ); return s == set; } static const char* specToString( Specification s ) { switch ( s ) { case Class: return "Class"; case Reference: return "Reference"; case Pointer: return "Pointer"; case ConstCharStar: return "ConstCharStar"; default: return "Unspecified"; } } }; class PropList : public TQPtrList { // list of properties public: PropList() { setAutoDelete( TRUE ); } }; struct ClassInfo { ClassInfo( const char* n, const char* v ) : name(n), value(v) {} TQCString name; TQCString value; }; class ClassInfoList : public TQPtrList { // list of class infos public: ClassInfoList() { setAutoDelete( TRUE ); } }; class parser_reg { public: parser_reg(); ~parser_reg(); // some temporary values TQCString tmpExpression; // Used to store the characters the lexer // is currently skipping (see addExpressionChar and friends) TQCString fileName; // file name TQCString outputFile; // output file name TQCString pchFile; // name of PCH file (used on Windows) TQStrList includeFiles; // name of #include files TQCString includePath; // #include file path TQCString qtPath; // #include qt file path int gen_count; //number of classes generated bool noInclude; // no #include bool generatedCode; // no code generated bool mocError; // moc parsing error occurred bool hasVariantIncluded; //whether or not qvariant.h was included yet TQCString className; // name of parsed class TQCString superClassName; // name of first super class TQStrList multipleSuperClasses; // other superclasses FuncList signals; // signal interface FuncList slots; // slots interface FuncList propfuncs; // all possible property access functions FuncList funcs; // all parsed functions, including signals EnumList enums; // enums used in properties PropList props; // list of all properties ClassInfoList infos; // list of all class infos // Used to store the values in the Q_PROPERTY macro TQCString propWrite; // set function TQCString propRead; // get function TQCString propReset; // reset function TQCString propStored; // TQCString propDesignable; // "true", "false" or function or empty if not specified TQCString propScriptable; // "true", "false" or function or empty if not specified bool propOverride; // Wether OVERRIDE was detected TQStrList qtEnums; // Used to store the contents of Q_ENUMS TQStrList qtSets; // Used to store the contents of Q_SETS }; static parser_reg *g = 0; ArgList *addArg( Argument * ); // add arg to tmpArgList enum Member { SignalMember, SlotMember, PropertyCandidateMember }; void addMember( Member ); // add tmpFunc to current class void addEnum(); // add tmpEnum to current class char *stradd( const char *, const char * ); // add two strings char *stradd( const char *, const char *, // add three strings const char * ); char *stradd( const char *, const char *, // adds 4 strings const char *, const char * ); char *straddSpc( const char *, const char * ); char *straddSpc( const char *, const char *, const char * ); char *straddSpc( const char *, const char *, const char *, const char * ); extern int yydebug; bool lexDebug = FALSE; int lineNo; // current line number bool errorControl = FALSE; // controled errors bool displayWarnings = TRUE; bool skipClass; // don't generate for class bool skipFunc; // don't generate for func bool templateClass; // class is a template bool templateClassOld; // previous class is a template ArgList *tmpArgList; // current argument list Function *tmpFunc; // current member function Enum *tmpEnum; // current enum Access tmpAccess; // current access permission Access subClassPerm; // current access permission bool Q_OBJECTdetected; // TRUE if current class // contains the Q_OBJECT macro bool Q_PROPERTYdetected; // TRUE if current class // contains at least one Q_PROPERTY, // Q_OVERRIDE, Q_SETS or Q_ENUMS macro bool tmpPropOverride; // current property override setting int tmpYYStart; // Used to store the lexers current mode int tmpYYStart2; // Used to store the lexers current mode // (if tmpYYStart is already used) // if the format revision changes, you MUST change it in qmetaobject.h too const int formatRevision = 26; // moc output format revision // if the flags change, you HAVE to change it in qmetaobject.h too enum Flags { Invalid = 0x00000000, Readable = 0x00000001, Writable = 0x00000002, EnumOrSet = 0x00000004, UnresolvedEnum = 0x00000008, StdSet = 0x00000100, Override = 0x00000200, NotDesignable = 0x00001000, DesignableOverride = 0x00002000, NotScriptable = 0x00004000, ScriptableOverride = 0x00008000, NotStored = 0x00010000, StoredOverride = 0x00020000 }; #ifdef YYBISON # if defined(Q_OS_WIN32) # include # undef isatty extern "C" int hack_isatty( int ) { return 0; } # define isatty hack_isatty # else # include # endif # define YYDEBUG 1 # include "moc_yacc.h" # include "moc_lex.cpp" #endif //YYBISON %} %union { char char_val; int int_val; double double_val; char *string; Access access; Function *function; ArgList *arg_list; Argument *arg; } %start declaration_seq %token CHAR_VAL /* value types */ %token INT_VAL %token DOUBLE_VAL %token STRING %token IDENTIFIER /* identifier string */ %token FRIEND /* declaration keywords */ %token TYPEDEF %token AUTO %token REGISTER %token STATIC %token EXTERN %token INLINE %token VIRTUAL %token CONST %token VOLATILE %token CHAR %token SHORT %token INT %token LONG %token SIGNED %token UNSIGNED %token FLOAT %token DOUBLE %token VOID %token ENUM %token CLASS %token STRUCT %token UNION %token ASM %token PRIVATE %token PROTECTED %token PUBLIC %token OPERATOR %token DBL_COLON %token TRIPLE_DOT %token TEMPLATE %token NAMESPACE %token USING %token MUTABLE %token THROW %token SIGNALS %token SLOTS %token Q_OBJECT %token Q_PROPERTY %token Q_OVERRIDE %token Q_CLASSINFO %token Q_ENUMS %token Q_SETS %token READ %token WRITE %token STORED %token DESIGNABLE %token SCRIPTABLE %token RESET %type class_name %type template_class_name %type template_spec %type opt_base_spec %type base_spec %type base_list %type qt_macro_name %type base_specifier %type access_specifier %type fct_name %type type_name %type simple_type_names %type simple_type_name %type class_key %type complete_class_name %type qualified_class_name %type elaborated_type_specifier %type whatever %type argument_declaration_list %type arg_declaration_list %type arg_declaration_list_opt %type abstract_decl_opt %type abstract_decl %type argument_declaration %type opt_exception_argument %type cv_qualifier_list_opt %type cv_qualifier_list %type cv_qualifier %type decl_specifiers %type decl_specifier %type decl_specs_opt %type decl_specs %type type_specifier %type fct_specifier %type declarator %type ptr_operator %type ptr_operators %type ptr_operators_opt %type dname %% declaration_seq: /* empty */ | declaration_seq declaration ; declaration: class_def /* | template_declaration */ | namespace_def | namespace_alias_def | using_declaration | using_directive ; namespace_def: named_namespace_def | unnamed_namespace_def ; named_namespace_def: NAMESPACE IDENTIFIER { enterNameSpace($2); } '{' { BEGIN IN_NAMESPACE; } namespace_body '}' { leaveNameSpace(); selectOutsideClassState(); } ; unnamed_namespace_def: NAMESPACE { enterNameSpace(); } '{' { BEGIN IN_NAMESPACE; } namespace_body '}' { leaveNameSpace(); selectOutsideClassState(); } ; namespace_body: declaration_seq ; namespace_alias_def: NAMESPACE IDENTIFIER '=' complete_class_name ';' { selectOutsideClassState(); } ; using_directive: USING NAMESPACE { selectOutsideClassState(); } /* Skip namespace */ ; using_declaration: USING IDENTIFIER { selectOutsideClassState(); } | USING DBL_COLON { selectOutsideClassState(); } ; class_def: { initClass(); } class_specifier ';' { generateClass(); registerClassInNamespace(); selectOutsideClassState(); } ; /***** r.17.1 (ARM p.387 ): Keywords *****/ class_name: IDENTIFIER { $$ = $1; } | template_class_name { $$ = $1; } ; template_class_name: IDENTIFIER '<' template_args '>' { g->tmpExpression = rmWS( g->tmpExpression ); $$ = stradd( $1, "<", g->tmpExpression, ">" ); } ; /* template_args skips all characters until it encounters a ">" (it handles and discards sublevels of parentheses). Since the rule is empty it must be used with care! */ template_args: /* empty */ { initExpression(); templLevel = 1; BEGIN IN_TEMPL_ARGS; } ; /***** r.17.2 (ARM p.388): Expressions *****/ /* const_expression skips all characters until it encounters either one of "]", ")" or "," (it handles and discards sublevels of parentheses). Since the rule is empty it must be used with care! */ const_expression: /* empty */ { initExpression(); BEGIN IN_EXPR; } ; /* def_argument is just like const expression but handles the "," slightly differently. It was added for 3.0 as tquick solution. TODO: merge with const_expression. */ def_argument: /* empty */ { BEGIN IN_DEF_ARG; } ; enumerator_expression: /* empty */ { initExpression(); BEGIN IN_ENUM; } ; /***** r.17.3 (ARM p.391): Declarations *****/ decl_specifier: storage_class_specifier { $$ = ""; } | type_specifier { $$ = $1; } | fct_specifier { $$ = ""; } | FRIEND { skipFunc = TRUE; $$ = ""; } | TYPEDEF { skipFunc = TRUE; $$ = ""; } ; decl_specifiers: decl_specs_opt type_name decl_specs_opt { $$ = straddSpc($1,$2,$3); } ; decl_specs_opt: /* empty */ { $$ = ""; } | decl_specs { $$ = $1; } ; decl_specs: decl_specifier { $$ = $1; } | decl_specs decl_specifier { $$ = straddSpc($1,$2); } ; storage_class_specifier: AUTO | REGISTER | STATIC { skipFunc = TRUE; } | EXTERN ; fct_specifier: INLINE { } | VIRTUAL { } ; type_specifier: CONST { $$ = "const"; } | VOLATILE { $$ = "volatile"; } ; type_name: elaborated_type_specifier { $$ = $1; } | complete_class_name { $$ = $1; } | simple_type_names { $$ = $1; } ; simple_type_names: simple_type_names simple_type_name { $$ = straddSpc($1,$2); } | simple_type_name { $$ = $1; } ; simple_type_name: CHAR { $$ = "char"; } | SHORT { $$ = "short"; } | INT { $$ = "int"; } | LONG { $$ = "long"; } | SIGNED { $$ = "signed"; } | UNSIGNED { $$ = "unsigned"; } | FLOAT { $$ = "float"; } | DOUBLE { $$ = "double"; } | VOID { $$ = "void"; } ; template_spec: TEMPLATE '<' template_args '>' { g->tmpExpression = rmWS( g->tmpExpression ); $$ = stradd( "template<", g->tmpExpression, ">" ); } ; opt_template_spec: /* empty */ | template_spec { templateClassOld = templateClass; templateClass = TRUE; } ; class_key: opt_template_spec CLASS { $$ = "class"; } | opt_template_spec STRUCT { $$ = "struct"; } ; complete_class_name: qualified_class_name { $$ = $1; } | DBL_COLON qualified_class_name { $$ = stradd( "::", $2 ); } ; qualified_class_name: qualified_class_name DBL_COLON class_name { $$ = stradd( $1, "::", $3 );} | class_name { $$ = $1; } ; elaborated_type_specifier: class_key IDENTIFIER { $$ = straddSpc($1,$2); } | ENUM IDENTIFIER { $$ = stradd("enum ",$2); } | UNION IDENTIFIER { $$ = stradd("union ",$2); } ; /***** r.17.4 (ARM p.393): Declarators *****/ argument_declaration_list: arg_declaration_list_opt triple_dot_opt { $$ = $1;} | arg_declaration_list ',' TRIPLE_DOT { $$ = $1; func_warn("Ellipsis not supported" " in signals and slots.\n" "Ellipsis argument ignored."); } ; arg_declaration_list_opt: /* empty */ { $$ = tmpArgList; } | arg_declaration_list { $$ = $1; } ; opt_exception_argument: /* empty */ { $$ = 0; } | argument_declaration ; triple_dot_opt: /* empty */ | TRIPLE_DOT { func_warn("Ellipsis not supported" " in signals and slots.\n" "Ellipsis argument ignored."); } ; arg_declaration_list: arg_declaration_list ',' argument_declaration { $$ = addArg($3); } | argument_declaration { $$ = addArg($1); } ; argument_declaration: decl_specifiers abstract_decl_opt { $$ = new Argument(straddSpc($1,$2),""); } | decl_specifiers abstract_decl_opt '=' { expLevel = 1; } def_argument { $$ = new Argument(straddSpc($1,$2),"", 0, TRUE ); } | decl_specifiers abstract_decl_opt dname abstract_decl_opt { $$ = new Argument(straddSpc($1,$2),$4, $3); } | decl_specifiers abstract_decl_opt dname abstract_decl_opt '=' { expLevel = 1; } def_argument { $$ = new Argument(straddSpc($1,$2),$4, $3, TRUE); } ; abstract_decl_opt: /* empty */ { $$ = ""; } | abstract_decl { $$ = $1; } ; abstract_decl: abstract_decl ptr_operator { $$ = straddSpc($1,$2); } | '[' { expLevel = 1; } const_expression ']' { $$ = stradd( "[", g->tmpExpression = g->tmpExpression.stripWhiteSpace(), "]" ); } | abstract_decl '[' { expLevel = 1; } const_expression ']' { $$ = stradd( $1,"[", g->tmpExpression = g->tmpExpression.stripWhiteSpace(),"]" ); } | ptr_operator { $$ = $1; } | '(' abstract_decl ')' { $$ = $2; } ; declarator: dname { $$ = ""; } | declarator ptr_operator { $$ = straddSpc($1,$2);} | declarator '[' { expLevel = 1; } const_expression ']' { $$ = stradd( $1,"[", g->tmpExpression = g->tmpExpression.stripWhiteSpace(),"]" ); } | '(' declarator ')' { $$ = $2; } ; dname: IDENTIFIER ; fct_decl: '(' argument_declaration_list ')' cv_qualifier_list_opt ctor_initializer_opt exception_spec_opt opt_identifier fct_body_or_semicolon { tmpFunc->args = $2; tmpFunc->qualifier = $4; } ; fct_name: IDENTIFIER /* NOTE: simplified! */ | IDENTIFIER array_decls { func_warn("Variable as signal or slot."); } | IDENTIFIER '=' { expLevel=0; } const_expression /* probably const member */ { skipFunc = TRUE; } | IDENTIFIER array_decls '=' { expLevel=0; } const_expression /* probably const member */ { skipFunc = TRUE; } ; array_decls: '[' { expLevel = 1; } const_expression ']' | array_decls '[' { expLevel = 1; } const_expression ']' ; ptr_operators_opt: /* empty */ { $$ = ""; } | ptr_operators { $$ = $1; } ; ptr_operators: ptr_operator { $$ = $1; } | ptr_operators ptr_operator { $$ = straddSpc($1,$2);} ; ptr_operator: '*' cv_qualifier_list_opt { $$ = straddSpc("*",$2);} | '&' cv_qualifier_list_opt { $$ = stradd("&",$2);} /*! | complete_class_name DBL_COLON '*' cv_qualifier_list_opt { $$ = stradd($1,"::*",$4); }*/ ; cv_qualifier_list_opt: /* empty */ { $$ = ""; } | cv_qualifier_list { $$ = $1; } ; cv_qualifier_list: cv_qualifier { $$ = $1; } | cv_qualifier_list cv_qualifier { $$ = straddSpc($1,$2); } ; cv_qualifier: CONST { $$ = "const"; } | VOLATILE { $$ = "volatile"; } ; fct_body_or_semicolon: ';' | fct_body | '=' INT_VAL ';' /* abstract func, INT_VAL = 0 */ ; fct_body: '{' { BEGIN IN_FCT; fctLevel = 1;} '}' { BEGIN QT_DEF; } ; /***** r.17.5 (ARM p.395): Class Declarations *****/ class_specifier: full_class_head '{' { BEGIN IN_CLASS; classPLevel = 1; } opt_obj_member_list '}' { BEGIN QT_DEF; } /*catch ';'*/ | class_head { BEGIN QT_DEF; /* -- " -- */ skipClass = TRUE; } | class_head '*' IDENTIFIER { BEGIN QT_DEF; /* -- " -- */ skipClass = TRUE; } | class_head '&' IDENTIFIER { BEGIN QT_DEF; /* -- " -- */ skipClass = TRUE; } | class_head '(' IDENTIFIER ')' /* TQt macro name */ { BEGIN QT_DEF; /* catch ';' */ skipClass = TRUE; } | template_spec whatever { skipClass = TRUE; BEGIN GIMME_SEMICOLON; } ; whatever: IDENTIFIER | simple_type_name | type_specifier | storage_class_specifier { $$ = ""; } | fct_specifier ; class_head: class_key qualified_class_name { g->className = $2; if ( g->className == "TQObject" ) Q_OBJECTdetected = TRUE; } | class_key IDENTIFIER /* possible DLL EXPORT macro */ class_name { g->className = $3; if ( g->className == "TQObject" ) Q_OBJECTdetected = TRUE; } ; full_class_head: class_head opt_base_spec { g->superClassName = $2; } ; nested_class_head: class_key qualified_class_name opt_base_spec { templateClass = templateClassOld; } ; exception_spec_opt: /* empty */ | exception_spec ; /* looser than the real thing */ exception_spec: THROW '(' opt_exception_argument ')' ; ctor_initializer_opt: /* empty */ | ctor_initializer ; ctor_initializer: ':' mem_initializer_list ; mem_initializer_list: mem_initializer | mem_initializer ',' mem_initializer_list ; /* complete_class_name also represents IDENTIFIER */ mem_initializer: complete_class_name '(' { expLevel = 1; } const_expression ')' ; opt_base_spec: /* empty */ { $$ = 0; } | base_spec { $$ = $1; } ; opt_obj_member_list: /* empty */ | obj_member_list ; obj_member_list: obj_member_list obj_member_area | obj_member_area ; qt_access_specifier: access_specifier { tmpAccess = $1; } | SLOTS { moc_err( "Missing access specifier" " before \"slots:\"." ); } ; obj_member_area: qt_access_specifier { BEGIN QT_DEF; } slot_area | SIGNALS { BEGIN QT_DEF; } ':' opt_signal_declarations | Q_OBJECT { if ( tmpAccess ) moc_warn("Q_OBJECT is not in the private" " section of the class.\n" "Q_OBJECT is a macro that resets" " access permission to \"private\"."); Q_OBJECTdetected = TRUE; } | Q_PROPERTY { tmpYYStart = YY_START; tmpPropOverride = FALSE; BEGIN IN_PROPERTY; } '(' property ')' { BEGIN tmpYYStart; } opt_property_candidates | Q_OVERRIDE { tmpYYStart = YY_START; tmpPropOverride = TRUE; BEGIN IN_PROPERTY; } '(' property ')' { BEGIN tmpYYStart; } opt_property_candidates | Q_CLASSINFO { tmpYYStart = YY_START; BEGIN IN_CLASSINFO; } '(' STRING ',' STRING ')' { g->infos.append( new ClassInfo( $4, $6 ) ); BEGIN tmpYYStart; } opt_property_candidates | Q_ENUMS { tmpYYStart = YY_START; BEGIN IN_PROPERTY; } '(' qt_enums ')' { Q_PROPERTYdetected = TRUE; BEGIN tmpYYStart; } opt_property_candidates | Q_SETS { tmpYYStart = YY_START; BEGIN IN_PROPERTY; } '(' qt_sets ')' { Q_PROPERTYdetected = TRUE; BEGIN tmpYYStart; } opt_property_candidates ; slot_area: SIGNALS ':' { moc_err( "Signals cannot " "have access specifiers" ); } | SLOTS ':' opt_slot_declarations | ':' { if ( tmpAccess == Public && Q_PROPERTYdetected ) BEGIN QT_DEF; else BEGIN IN_CLASS; suppress_func_warn = TRUE; } opt_property_candidates { suppress_func_warn = FALSE; } | IDENTIFIER { BEGIN IN_CLASS; if ( classPLevel != 1 ) moc_warn( "unexpected access" "specifier" ); } ; opt_property_candidates: /*empty*/ | property_candidate_declarations ; property_candidate_declarations: property_candidate_declarations property_candidate_declaration | property_candidate_declaration ; property_candidate_declaration: signal_or_slot { addMember( PropertyCandidateMember ); } ; opt_signal_declarations: /* empty */ | signal_declarations ; signal_declarations: signal_declarations signal_declaration | signal_declaration ; signal_declaration: signal_or_slot { addMember( SignalMember ); } ; opt_slot_declarations: /* empty */ | slot_declarations ; slot_declarations: slot_declarations slot_declaration | slot_declaration ; slot_declaration: signal_or_slot { addMember( SlotMember ); } ; opt_semicolons: /* empty */ | opt_semicolons ';' ; base_spec: ':' base_list { $$=$2; } ; base_list : base_list ',' base_specifier { g->multipleSuperClasses.append( $3 ); } | base_specifier ; qt_macro_name: IDENTIFIER '(' IDENTIFIER ')' { $$ = stradd( $1, "(", $3, ")" ); } | IDENTIFIER '(' simple_type_name ')' { $$ = stradd( $1, "(", $3, ")" ); } ; base_specifier: complete_class_name {$$=$1;} | VIRTUAL access_specifier complete_class_name {$$=$3;} | VIRTUAL complete_class_name {$$=$2;} | access_specifier VIRTUAL complete_class_name {$$=$3;} | access_specifier complete_class_name {$$=$2;} | qt_macro_name {$$=$1;} | VIRTUAL access_specifier qt_macro_name {$$=$3;} | VIRTUAL qt_macro_name {$$=$2;} | access_specifier VIRTUAL qt_macro_name {$$=$3;} | access_specifier qt_macro_name {$$=$2;} ; access_specifier: PRIVATE { $$=Private; } | PROTECTED { $$=Protected; } | PUBLIC { $$=Public; } ; operator_name: decl_specs_opt IDENTIFIER ptr_operators_opt { } | decl_specs_opt simple_type_name ptr_operators_opt { } | '+' | '-' | '*' | '/' | '%' | '^' | '&' | '|' | '~' | '!' | '=' | '<' | '>' | '+' '=' | '-' '=' | '*' '=' | '/' '=' | '%' '=' | '^' '=' | '&' '=' | '|' '=' | '~' '=' | '!' '=' | '=' '=' | '<' '=' | '>' '=' | '<' '<' | '>' '>' | '<' '<' '=' | '>' '>' '=' | '&' '&' | '|' '|' | '+' '+' | '-' '-' | ',' | '-' '>' '*' | '-' '>' | '(' ')' | '[' ']' ; opt_virtual: /* empty */ | VIRTUAL ; type_and_name: type_name fct_name { tmpFunc->type = $1; tmpFunc->name = $2; } | fct_name { tmpFunc->type = "int"; tmpFunc->name = $1; if ( tmpFunc->name == g->className ) func_warn( "Constructors cannot be" " signals or slots."); } | opt_virtual '~' fct_name { tmpFunc->type = "void"; tmpFunc->name = "~"; tmpFunc->name += $3; func_warn( "Destructors cannot be" " signals or slots."); } | decl_specs type_name decl_specs_opt ptr_operators_opt fct_name { char *tmp = straddSpc($1,$2,$3,$4); tmpFunc->type = rmWS(tmp); delete [] tmp; tmpFunc->name = $5; } | decl_specs type_name /* probably friend decl */ { skipFunc = TRUE; } | type_name ptr_operators fct_name { tmpFunc->type = straddSpc($1,$2); tmpFunc->name = $3; } | type_name decl_specs ptr_operators_opt fct_name { tmpFunc->type = straddSpc($1,$2,$3); tmpFunc->name = $4; } | type_name OPERATOR operator_name { operatorError(); } | OPERATOR operator_name { operatorError(); } | decl_specs type_name decl_specs_opt ptr_operators_opt OPERATOR operator_name { operatorError(); } | type_name ptr_operators OPERATOR operator_name { operatorError(); } | type_name decl_specs ptr_operators_opt OPERATOR operator_name { operatorError(); } ; signal_or_slot: type_and_name fct_decl opt_semicolons | type_and_name opt_bitfield ';' opt_semicolons { func_warn("Unexpected variable declaration."); } | type_and_name opt_bitfield ','member_declarator_list ';' opt_semicolons { func_warn("Unexpected variable declaration."); } | enum_specifier opt_identifier ';' opt_semicolons { func_warn("Unexpected enum declaration."); } | USING complete_class_name ';' opt_semicolons { func_warn("Unexpected using declaration."); } | USING NAMESPACE complete_class_name ';' opt_semicolons { func_warn("Unexpected using declaration."); } | NAMESPACE IDENTIFIER '{' { classPLevel++; moc_err("Unexpected namespace declaration."); } | nested_class_head ';' opt_semicolons { func_warn("Unexpected class declaration.");} | nested_class_head '{' { func_warn("Unexpected class declaration."); BEGIN IN_FCT; fctLevel=1; } '}' { BEGIN QT_DEF; } ';' opt_semicolons ; member_declarator_list: member_declarator | member_declarator_list ',' member_declarator ; member_declarator: declarator { } | IDENTIFIER ':' { expLevel = 0; } const_expression | ':' { expLevel = 0; } const_expression ; opt_bitfield: /* empty */ | ':' { expLevel = 0; } const_expression ; enum_specifier: ENUM enum_tail ; /* optional final comma at the end of an enum list. Not really C++ but some people still use it */ opt_komma: /*empty*/ | ',' ; enum_tail: IDENTIFIER '{' enum_list opt_komma '}' { BEGIN QT_DEF; if ( tmpAccess == Public) { tmpEnum->name = $1; addEnum(); } } | '{' enum_list opt_komma '}' { tmpEnum->clear();} ; opt_identifier: /* empty */ | IDENTIFIER { } ; enum_list: /* empty */ | enumerator | enum_list ',' enumerator ; enumerator: IDENTIFIER { if ( tmpAccess == Public) tmpEnum->append( $1 ); } | IDENTIFIER '=' { enumLevel=0; } enumerator_expression { if ( tmpAccess == Public) tmpEnum->append( $1 ); } ; property: IDENTIFIER IDENTIFIER { g->propWrite = ""; g->propRead = ""; g->propOverride = tmpPropOverride; g->propReset = ""; if ( g->propOverride ) { g->propStored = ""; g->propDesignable = ""; g->propScriptable = ""; } else { g->propStored = "true"; g->propDesignable = "true"; g->propScriptable = "true"; } } prop_statements { if ( g->propRead.isEmpty() && !g->propOverride ) moc_err( "A property must at least feature a read method." ); checkPropertyName( $2 ); Q_PROPERTYdetected = TRUE; // Avoid duplicates for( TQPtrListIterator lit( g->props ); lit.current(); ++lit ) { if ( lit.current()->name == $2 ) { if ( displayWarnings ) moc_err( "Property '%s' defined twice.", (const char*)lit.current()->name ); } } g->props.append( new Property( lineNo, $1, $2, g->propWrite, g->propRead, g->propReset, g->propStored, g->propDesignable, g->propScriptable, g->propOverride ) ); } ; prop_statements: /* empty */ | READ IDENTIFIER prop_statements { g->propRead = $2; } | WRITE IDENTIFIER prop_statements { g->propWrite = $2; } | RESET IDENTIFIER prop_statements { g->propReset = $2; } | STORED IDENTIFIER prop_statements { g->propStored = $2; } | DESIGNABLE IDENTIFIER prop_statements { g->propDesignable = $2; } | SCRIPTABLE IDENTIFIER prop_statements { g->propScriptable = $2; } ; qt_enums: /* empty */ { } | IDENTIFIER qt_enums { g->qtEnums.append( $1 ); } ; qt_sets: /* empty */ { } | IDENTIFIER qt_sets { g->qtSets.append( $1 ); } ; %% #ifndef YYBISON # if defined(Q_OS_WIN32) # include # undef isatty extern "C" int hack_isatty( int ) { return 0; } # define isatty hack_isatty # else # include # endif # include "moc_lex.cpp" #endif //YYBISON void cleanup(); TQCString combinePath( const char *, const char * ); FILE *out; // output file parser_reg::parser_reg() : funcs(TRUE) { gen_count = 0; noInclude = FALSE; // no #include generatedCode = FALSE; // no code generated mocError = FALSE; // moc parsing error occurred hasVariantIncluded = FALSE; } parser_reg::~parser_reg() { slots.clear(); signals.clear(); propfuncs.clear(); funcs.clear(); infos.clear(); props.clear(); infos.clear(); } int yyparse(); void replace( char *s, char c1, char c2 ); void setDefaultIncludeFile() { if ( g->includeFiles.isEmpty() ) { if ( g->includePath.isEmpty() ) { if ( !g->fileName.isEmpty() && !g->outputFile.isEmpty() ) { g->includeFiles.append( combinePath(g->fileName, g->outputFile) ); } else { g->includeFiles.append( g->fileName ); } } else { g->includeFiles.append( combinePath(g->fileName, g->fileName) ); } } } #ifdef Q_CC_MSVC #define ErrorFormatString "%s(%d):" #else #define ErrorFormatString "%s:%d:" #endif #ifndef MOC_MWERKS_PLUGIN int main( int argc, char **argv ) { init(); bool autoInclude = TRUE; const char *error = 0; g->qtPath = ""; for ( int n=1; noutputFile = argv[++n]; } else g->outputFile = &opt[1]; } else if ( opt == "i" ) { // no #include statement g->noInclude = TRUE; autoInclude = FALSE; } else if ( opt[0] == 'f' ) { // produce #include statement g->noInclude = FALSE; autoInclude = FALSE; if ( opt[1] ) // -fsomething.h g->includeFiles.append( &opt[1] ); } else if ( opt == "pch" ) { // produce #include statement for PCH if ( !(n < argc-1) ) { error = "Missing name of PCH file"; break; } g->pchFile = argv[++n]; } else if ( opt[0] == 'p' ) { // include file path if ( opt[1] == '\0' ) { if ( !(n < argc-1) ) { error = "Missing path name for the -p option."; break; } g->includePath = argv[++n]; } else { g->includePath = &opt[1]; } } else if ( opt[0] == 'q' ) { // qt include file path if ( opt[1] == '\0' ) { if ( !(n < argc-1) ) { error = "Missing path name for the -q option."; break; } g->qtPath = argv[++n]; } else { g->qtPath = &opt[1]; } replace(g->qtPath.data(),'\\','/'); if ( g->qtPath.right(1) != "/" ) g->qtPath += '/'; } else if ( opt == "v" ) { // version number fprintf( stderr, "TQt Meta Object Compiler version %d" " (TQt %s)\n", formatRevision, QT_VERSION_STR ); cleanup(); return 1; } else if ( opt == "k" ) { // stop on errors errorControl = TRUE; } else if ( opt == "nw" ) { // don't display warnings displayWarnings = FALSE; } else if ( opt == "ldbg" ) { // lex debug output lexDebug = TRUE; } else if ( opt == "ydbg" ) { // yacc debug output yydebug = TRUE; } else { error = "Invalid argument"; } } else { if ( !g->fileName.isNull() ) // can handle only one file error = "Too many input files specified"; else g->fileName = arg.copy(); } } if ( autoInclude ) { int ppos = g->fileName.findRev('.'); if ( ppos != -1 && tolower( g->fileName[ppos + 1] ) == 'h' ) g->noInclude = FALSE; else g->noInclude = TRUE; } setDefaultIncludeFile(); if ( g->fileName.isNull() && !error ) { g->fileName = "standard input"; yyin = stdin; } else if ( argc < 2 || error ) { // incomplete/wrong args fprintf( stderr, "TQt meta object compiler\n" ); if ( error ) fprintf( stderr, "moc: %s\n", error ); fprintf( stderr, "Usage: moc [options] \n" "\t-o file Write output to file rather than stdout\n" "\t-f[file] Force #include, optional file name\n" "\t-p path Path prefix for included file\n" "\t-i Do not generate an #include statement\n" "\t-k Do not stop on errors\n" "\t-nw Do not display warnings\n" "\t-v Display version of moc\n" ); cleanup(); return 1; } else { yyin = fopen( (const char *)g->fileName, "r" ); if ( !yyin ) { fprintf( stderr, "moc: %s: No such file\n", (const char*)g->fileName); cleanup(); return 1; } } if ( !g->outputFile.isEmpty() ) { // output file specified out = fopen( (const char *)g->outputFile, "w" ); // create output file if ( !out ) { fprintf( stderr, "moc: Cannot create %s\n", (const char*)g->outputFile ); cleanup(); return 1; } } else { // use stdout out = stdout; } yyparse(); fclose( yyin ); if ( !g->outputFile.isNull() ) fclose( out ); if ( !g->generatedCode && displayWarnings && !g->mocError ) { fprintf( stderr, ErrorFormatString" Warning: %s\n", g->fileName.data(), 0, "No relevant classes found. No output generated." ); } int ret = g->mocError ? 1 : 0; cleanup(); return ret; } #else bool qt_is_gui_used = FALSE; #include #include #include #ifdef Q_OS_MAC9 # include # include # include # include "Aliases.h" #endif #include "CWPluginErrors.h" #include #include "DropInCompilerLinker.h" #include const unsigned char *p_str(const char *, int =-1); CWPluginContext g_ctx; moc_status do_moc( CWPluginContext ctx, const TQCString &fin, const TQCString &fout, CWFileSpec *dspec, bool i) { init(); g_ctx = ctx; g->noInclude = i; g->fileName = fin; g->outputFile = fout; setDefaultIncludeFile(); CWFileInfo fi; memset(&fi, 0, sizeof(fi)); fi.fullsearch = TRUE; fi.dependencyType = cwNormalDependency; fi.isdependentoffile = kCurrentCompiledFile; if(CWFindAndLoadFile( ctx, fin.data(), &fi) != cwNoErr) { cleanup(); return moc_no_source; } if(dspec) { memcpy(dspec, &fi.filespec, sizeof(fi.filespec)); const unsigned char *f = p_str(fout.data()); memcpy(dspec->name, f, f[0]+1); free(f); } buf_size_total = fi.filedatalength; buf_buffer = fi.filedata; TQCString path(""); AliasHandle alias; Str63 str; AliasInfoType x = 1; char tmp[sizeof(Str63)+2]; if(NewAlias( NULL, &fi.filespec, &alias) != noErr) { cleanup(); return moc_general_error; } for(;;) { GetAliasInfo(alias, x++, str); if(!str[0]) break; strncpy((char *)tmp, (const char *)str+1, str[0]); tmp[str[0]] = '\0'; path.prepend(":"); path.prepend((char *)tmp); } path.prepend("MacOS 9:"); //FIXME TQString inpath = path + fin, outpath = path + fout; struct stat istat, ostat; if(stat(inpath, &istat) == -1) { cleanup(); return moc_no_source; } if(stat(outpath, &ostat) == 0 && istat.st_mtime < ostat.st_mtime) { cleanup(); return moc_not_time; } unlink(outpath.data()); out = fopen(outpath.data(), "w+"); if(!out) { cleanup(); return moc_general_error; } yyparse(); if(out != stdout) fclose(out); if(g->mocError || !g->generatedCode) { unlink(outpath.data()); moc_status ret = !g->generatedCode ? moc_no_qobject : moc_parse_error; cleanup(); return ret; } cleanup(); return moc_success; } #endif void replace( char *s, char c1, char c2 ) { if ( !s ) return; while ( *s ) { if ( *s == c1 ) *s = c2; s++; } } /* 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 */ TQCString combinePath( const char *infile, const char *outfile ) { TQFileInfo inFileInfo( TQDir::current(), TQFile::decodeName(infile) ); TQFileInfo outFileInfo( TQDir::current(), TQFile::decodeName(outfile) ); int numCommonComponents = 0; TQStringList inSplitted = TQStringList::split( '/', inFileInfo.dir().canonicalPath(), TRUE ); TQStringList outSplitted = TQStringList::split( '/', outFileInfo.dir().canonicalPath(), TRUE ); while ( !inSplitted.isEmpty() && !outSplitted.isEmpty() && inSplitted.first() == outSplitted.first() ) { inSplitted.remove( inSplitted.begin() ); outSplitted.remove( outSplitted.begin() ); 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 TQFile::encodeName( inFileInfo.absFilePath() ); } else { /* The paths have something in common. Use a path relative to the output file. */ while ( !outSplitted.isEmpty() ) { outSplitted.remove( outSplitted.begin() ); inSplitted.prepend( ".." ); } inSplitted.append( inFileInfo.fileName() ); return TQFile::encodeName( inSplitted.join("/") ); } } #define getenv hack_getenv // workaround for byacc char *getenv() { return 0; } char *getenv( const char * ) { return 0; } void init() // initialize { BEGIN OUTSIDE; if(g) delete g; g = new parser_reg; lineNo = 1; skipClass = FALSE; skipFunc = FALSE; tmpArgList = new ArgList; tmpFunc = new Function; tmpEnum = new Enum; #ifdef MOC_MWERKS_PLUGIN buf_buffer = NULL; buf_index = 0; buf_size_total = 0; #endif } void cleanup() { delete g; g = NULL; #ifdef MOC_MWERKS_PLUGIN if(buf_buffer && g_ctx) CWReleaseFileText(g_ctx, buf_buffer); #endif } void initClass() // prepare for new class { tmpAccess = Private; subClassPerm = Private; Q_OBJECTdetected = FALSE; Q_PROPERTYdetected = FALSE; skipClass = FALSE; templateClass = FALSE; g->slots.clear(); g->signals.clear(); g->propfuncs.clear(); g->enums.clear(); g->funcs.clear(); g->props.clear(); g->infos.clear(); g->qtSets.clear(); g->qtEnums.clear(); g->multipleSuperClasses.clear(); } struct NamespaceInfo { TQCString name; int pLevelOnEntering; // Parenthesis level on entering the namespace TQDict definedClasses; // Classes defined in the namespace }; TQPtrList namespaces; void enterNameSpace( const char *name ) // prepare for new class { static bool first = TRUE; if ( first ) { namespaces.setAutoDelete( TRUE ); first = FALSE; } NamespaceInfo *tmp = new NamespaceInfo; if ( name ) tmp->name = name; tmp->pLevelOnEntering = namespacePLevel; namespaces.append( tmp ); } void leaveNameSpace() // prepare for new class { NamespaceInfo *tmp = namespaces.last(); namespacePLevel = tmp->pLevelOnEntering; namespaces.remove(); } TQCString nameQualifier() { TQPtrListIterator iter( namespaces ); NamespaceInfo *tmp; TQCString qualifier = ""; for( ; (tmp = iter.current()) ; ++iter ) { if ( !tmp->name.isNull() ) { // If not unnamed namespace qualifier += tmp->name; qualifier += "::"; } } return qualifier; } int openNameSpaceForMetaObject( FILE *out ) { int levels = 0; TQPtrListIterator iter( namespaces ); NamespaceInfo *tmp; TQCString indent = ""; for( ; (tmp = iter.current()) ; ++iter ) { if ( !tmp->name.isNull() ) { // If not unnamed namespace fprintf( out, "%snamespace %s {\n", (const char *)indent, (const char *) tmp->name ); indent += " "; levels++; } } TQCString nm = g->className; int pos; while( (pos = nm.find( "::" )) != -1 ) { TQCString spaceName = nm.left( pos ); nm = nm.right( nm.length() - pos - 2 ); if ( !spaceName.isEmpty() ) { fprintf( out, "%snamespace %s {\n", (const char *)indent, (const char *) spaceName ); indent += " "; levels++; } } return levels; } void closeNameSpaceForMetaObject( FILE *out, int levels ) { int i; for( i = 0 ; i < levels ; i++ ) fprintf( out, "}" ); if ( levels ) fprintf( out, "\n" ); } void selectOutsideClassState() { if ( namespaces.count() == 0 ) BEGIN OUTSIDE; else BEGIN IN_NAMESPACE; } void registerClassInNamespace() { if ( namespaces.count() == 0 ) return; namespaces.last()->definedClasses.insert((const char *)g->className,(char*)1); } // // Remove white space from SIGNAL and SLOT names. // This function has been copied from qobject.cpp. // inline bool isSpace( char x ) { #if defined(Q_CC_BOR) /* Borland C++ 4.5 has a weird isspace() bug. isspace() usually works, but not here. This implementation is sufficient for our internal use: rmWS() */ return (uchar) x <= 32; #else return isspace( (uchar) x ); #endif } static TQCString rmWS( const char *src ) { TQCString result( qstrlen(src)+1 ); char *d = result.data(); char *s = (char *)src; char last = 0; while( *s && isSpace(*s) ) // skip leading space s++; while ( *s ) { while ( *s && !isSpace(*s) ) last = *d++ = *s++; while ( *s && isSpace(*s) ) s++; if ( *s && isIdentChar(*s) && isIdentChar(last) ) last = *d++ = ' '; } result.truncate( (int)(d - result.data()) ); return result; } void initExpression() { g->tmpExpression = ""; } void addExpressionString( const char *s ) { g->tmpExpression += s; } void addExpressionChar( const char c ) { g->tmpExpression += c; } void yyerror( const char *msg ) // print yacc error message { g->mocError = TRUE; #ifndef MOC_MWERKS_PLUGIN fprintf( stderr, ErrorFormatString" Error: %s\n", g->fileName.data(), lineNo, msg ); #else char msg2[200]; sprintf(msg2, ErrorFormatString" Error: %s", g->fileName.data(), lineNo, msg); CWReportMessage(g_ctx, NULL, msg2, NULL, messagetypeError, 0); #endif if ( errorControl ) { if ( !g->outputFile.isEmpty() && yyin && fclose(yyin) == 0 ) remove( g->outputFile ); exit( -1 ); } } void moc_err( const char *s ) { yyerror( s ); } void moc_err( const char *s1, const char *s2 ) { static char tmp[1024]; sprintf( tmp, s1, s2 ); yyerror( tmp ); } void moc_warn( const char *msg ) { if ( displayWarnings ) fprintf( stderr, ErrorFormatString" Warning: %s\n", g->fileName.data(), lineNo, msg); } void moc_warn( char *s1, char *s2 ) { static char tmp[1024]; sprintf( tmp, s1, s2 ); if ( displayWarnings ) fprintf( stderr, ErrorFormatString" Warning: %s\n", g->fileName.data(), lineNo, tmp); } void func_warn( const char *msg ) { if ( !suppress_func_warn ) moc_warn( msg ); skipFunc = TRUE; } void operatorError() { if ( !suppress_func_warn ) moc_warn("Operator functions cannot be signals or slots."); skipFunc = TRUE; } #ifndef yywrap int yywrap() // more files? { return 1; // end of file } #endif char *stradd( const char *s1, const char *s2 ) // adds two strings { char *n = new char[qstrlen(s1)+qstrlen(s2)+1]; qstrcpy( n, s1 ); strcat( n, s2 ); return n; } char *stradd( const char *s1, const char *s2, const char *s3 )// adds 3 strings { char *n = new char[qstrlen(s1)+qstrlen(s2)+qstrlen(s3)+1]; qstrcpy( n, s1 ); strcat( n, s2 ); strcat( n, s3 ); return n; } char *stradd( const char *s1, const char *s2, const char *s3, const char *s4 )// adds 4 strings { char *n = new char[qstrlen(s1)+qstrlen(s2)+qstrlen(s3)+qstrlen(s4)+1]; qstrcpy( n, s1 ); strcat( n, s2 ); strcat( n, s3 ); strcat( n, s4 ); return n; } char *straddSpc( const char *s1, const char *s2 ) { char *n = new char[qstrlen(s1)+qstrlen(s2)+2]; qstrcpy( n, s1 ); strcat( n, " " ); strcat( n, s2 ); return n; } char *straddSpc( const char *s1, const char *s2, const char *s3 ) { char *n = new char[qstrlen(s1)+qstrlen(s2)+qstrlen(s3)+3]; qstrcpy( n, s1 ); strcat( n, " " ); strcat( n, s2 ); strcat( n, " " ); strcat( n, s3 ); return n; } char *straddSpc( const char *s1, const char *s2, const char *s3, const char *s4 ) { char *n = new char[qstrlen(s1)+qstrlen(s2)+qstrlen(s3)+qstrlen(s4)+4]; qstrcpy( n, s1 ); strcat( n, " " ); strcat( n, s2 ); strcat( n, " " ); strcat( n, s3 ); strcat( n, " " ); strcat( n, s4 ); return n; } // Generate C++ code for building member function table /* We call B::qt_invoke() rather than A::B::qt_invoke() to work around a bug in MSVC 6. The bug occurs if the super-class is in a namespace and the sub-class isn't. Exception: If the superclass has the same name as the subclass, we want non-MSVC users to have a working generated files. */ TQCString purestSuperClassName() { TQCString sc = g->superClassName; TQCString c = g->className; /* Make sure qualified template arguments (e.g., foo) don't interfere. */ int pos = sc.findRev( "::", sc.find( '<' ) ); if ( pos != -1 ) { sc = sc.right( sc.length() - pos - 2 ); pos = c.findRev( "::" ); if ( pos != -1 ) c = c.right( c.length() - pos - 2 ); if ( sc == c ) sc = g->superClassName; } return sc; } TQCString qualifiedClassName() { return nameQualifier() + g->className; } const int Slot_Num = 1; const int Signal_Num = 2; const int Prop_Num = 3; void generateFuncs( FuncList *list, const char *functype, int num ) { Function *f; for ( f=list->first(); f; f=list->next() ) { bool hasReturnValue = f->type != "void" && (validUType( f->type ) || isVariantType( f->type) ); if ( hasReturnValue || !f->args->isEmpty() ) { fprintf( out, " static const TQUParameter param_%s_%d[] = {\n", functype, list->at() ); if ( hasReturnValue ) { if ( validUType( f->type ) ) fprintf( out, "\t{ 0, &static_QUType_%s, %s, TQUParameter::Out }", uType(f->type).data(), uTypeExtra(f->type).data() ); else fprintf( out, "\t{ 0, &static_QUType_TQVariant, %s, TQUParameter::Out }", uTypeExtra(f->type).data() ); if ( !f->args->isEmpty() ) fprintf( out, ",\n" ); } Argument* a = f->args->first(); while ( a ) { TQCString type = a->leftType + ' ' + a->rightType; type = type.simplifyWhiteSpace(); if( a->name.isEmpty() ) fprintf( out, "\t{ 0, &static_QUType_%s, %s, TQUParameter::%s }", uType( type ).data(), uTypeExtra( type ).data(), isInOut( type ) ? "InOut" : "In" ); else fprintf( out, "\t{ \"%s\", &static_QUType_%s, %s, TQUParameter::%s }", a->name.data(), uType( type ).data(), uTypeExtra( type ).data(), isInOut( type ) ? "InOut" : "In" ); a = f->args->next(); if ( a ) fprintf( out, ",\n" ); } fprintf( out, "\n };\n"); } fprintf( out, " static const TQUMethod %s_%d = {", functype, list->at() ); int n = f->args->count(); if ( hasReturnValue ) n++; fprintf( out, "\"%s\", %d,", f->name.data(), n ); if ( n ) fprintf( out, " param_%s_%d };\n", functype, list->at() ); else fprintf( out, " 0 };\n" ); TQCString typstr = ""; int count = 0; Argument *a = f->args->first(); while ( a ) { if ( !a->leftType.isEmpty() || ! a->rightType.isEmpty() ) { if ( count++ ) typstr += ","; typstr += a->leftType; typstr += a->rightType; } a = f->args->next(); } f->signature = f->name; f->signature += "("; f->signature += typstr; f->signature += ")"; } if ( list->count() ) { fprintf(out," static const TQMetaData %s_tbl[] = {\n", functype ); f = list->first(); while ( f ) { fprintf( out, "\t{ \"%s\",", f->signature.data() ); fprintf( out, " &%s_%d,", functype, list->at() ); fprintf( out, " TQMetaData::%s }", f->accessAsString() ); f = list->next(); if ( f ) fprintf( out, ",\n"); } fprintf( out, "\n };\n" ); } } int enumIndex( const char* type ) { int index = 0; for( TQPtrListIterator lit( g->enums ); lit.current(); ++lit ) { if ( lit.current()->name == type ) return index; index++; } return -1; } bool isEnumType( const char* type ) { return enumIndex( type ) >= 0 || ( g->qtEnums.contains( type ) || g->qtSets.contains( type ) ); } bool isPropertyType( const char* type ) { if ( isVariantType( type ) ) return TRUE; return isEnumType( type ); } int generateEnums() { if ( g->enums.count() == 0 ) return 0; fprintf( out, "#ifndef QT_NO_PROPERTIES\n" ); int i = 0; for ( TQPtrListIterator it( g->enums ); it.current(); ++it, ++i ) { fprintf( out, " static const TQMetaEnum::Item enum_%i[] = {\n", i ); int k = 0; for( TQStrListIterator eit( *it.current() ); eit.current(); ++eit, ++k ) { if ( k ) fprintf( out, ",\n" ); fprintf( out, "\t{ \"%s\", (int) %s::%s }", eit.current(), (const char*) g->className, eit.current() ); } fprintf( out, "\n };\n" ); } fprintf( out, " static const TQMetaEnum enum_tbl[] = {\n" ); i = 0; for ( TQPtrListIterator it2( g->enums ); it2.current(); ++it2, ++i ) { if ( i ) fprintf( out, ",\n" ); fprintf( out, "\t{ \"%s\", %u, enum_%i, %s }", (const char*)it2.current()->name, it2.current()->count(), i, it2.current()->set ? "TRUE" : "FALSE" ); } fprintf( out, "\n };\n" ); fprintf( out, "#endif // QT_NO_PROPERTIES\n" ); return g->enums.count(); } int generateProps() { // // Resolve and verify property access functions // for( TQPtrListIterator it( g->props ); it.current(); ) { Property* p = it.current(); ++it; // verify get function if ( !p->get.isEmpty() ) { FuncList candidates = g->propfuncs.find( p->get ); for ( Function* f = candidates.first(); f; f = candidates.next() ) { if ( f->qualifier != "const" ) // get functions must be const continue; if ( f->args && !f->args->isEmpty() ) // and must not take any arguments continue; TQCString tmp = f->type; Property::Specification spec = Property::Unspecified; if ( p->type == "TQCString" && (tmp == "const char*" || tmp == "const char *" ) ) { tmp = "TQCString"; spec = Property::ConstCharStar; } else if ( tmp.right(1) == "&" ) { tmp = tmp.left( tmp.length() - 1 ); spec = Property::Reference; } else if ( tmp.right(1) == "*" ) { tmp = tmp.left( tmp.length() - 1 ); spec = Property::Pointer; } else { spec = Property::Class; } if ( tmp.left(6) == "const " ) tmp = tmp.mid( 6, tmp.length() - 6 ); tmp = tmp.simplifyWhiteSpace(); if ( p->type == tmp ) { // If it is an enum then it may not be a set bool ok = TRUE; for( TQPtrListIterator lit( g->enums ); lit.current(); ++lit ) if ( lit.current()->name == p->type && lit.current()->set ) ok = FALSE; if ( !ok ) continue; p->gspec = spec; p->getfunc = f; p->oredEnum = 0; break; } else if ( !isVariantType( p->type ) ) { if ( tmp == "int" || tmp == "uint" || tmp == "unsigned int" ) { // Test whether the enum is really a set (unfortunately we don't know enums of super classes) bool ok = TRUE; for( TQPtrListIterator lit( g->enums ); lit.current(); ++lit ) if ( lit.current()->name == p->type && !lit.current()->set ) ok = FALSE; if ( !ok ) continue; p->gspec = spec; p->getfunc = f; p->oredEnum = 1; p->enumgettype = tmp; } } } if ( p->getfunc == 0 ) { if ( displayWarnings ) { // Is the type a set, that means, mentioned in Q_SETS? bool set = FALSE; for( TQPtrListIterator lit( g->enums ); lit.current(); ++lit ) if ( lit.current()->name == p->type && lit.current()->set ) set = TRUE; fprintf( stderr, ErrorFormatString" Warning: Property '%s' not available.\n", g->fileName.data(), p->lineNo, (const char*) p->name ); fprintf( stderr, " Have been looking for public get functions \n"); if ( !set ) { fprintf( stderr, " %s %s() const\n" " %s& %s() const\n" " const %s& %s() const\n" " %s* %s() const\n", (const char*) p->type, (const char*) p->get, (const char*) p->type, (const char*) p->get, (const char*) p->type, (const char*) p->get, (const char*) p->type, (const char*) p->get ); } if ( set || !isPropertyType( p->type ) ) { fprintf( stderr, " int %s() const\n" " uint %s() const\n" " unsigned int %s() const\n", (const char*) p->get, (const char*) p->get, (const char*) p->get ); } if ( p->type == "TQCString" ) fprintf( stderr, " const char* %s() const\n", (const char*)p->get ); if ( candidates.isEmpty() ) { fprintf( stderr, " but found nothing.\n"); } else { fprintf( stderr, " but only found the mismatching candidate(s)\n"); for ( Function* f = candidates.first(); f; f = candidates.next() ) { TQCString typstr = ""; Argument *a = f->args->first(); int count = 0; while ( a ) { if ( !a->leftType.isEmpty() || ! a->rightType.isEmpty() ) { if ( count++ ) typstr += ","; typstr += a->leftType; typstr += a->rightType; } a = f->args->next(); } fprintf( stderr, " %s:%d: %s %s(%s) %s\n", g->fileName.data(), f->lineNo, (const char*) f->type,(const char*) f->name, (const char*) typstr, f->qualifier.isNull()?"":(const char*) f->qualifier ); } } } } } // verify set function if ( !p->set.isEmpty() ) { FuncList candidates = g->propfuncs.find( p->set ); for ( Function* f = candidates.first(); f; f = candidates.next() ) { if ( !f->args || f->args->isEmpty() ) continue; TQCString tmp = f->args->first()->leftType; tmp = tmp.simplifyWhiteSpace(); Property::Specification spec = Property::Unspecified; if ( tmp.right(1) == "&" ) { tmp = tmp.left( tmp.length() - 1 ); spec = Property::Reference; } else { spec = Property::Class; } if ( p->type == "TQCString" && (tmp == "const char*" || tmp == "const char *" ) ) { tmp = "TQCString"; spec = Property::ConstCharStar; } if ( tmp.left(6) == "const " ) tmp = tmp.mid( 6, tmp.length() - 6 ); tmp = tmp.simplifyWhiteSpace(); if ( p->type == tmp && f->args->count() == 1 ) { // If it is an enum then it may not be a set if ( p->oredEnum == 1 ) continue; bool ok = TRUE; for( TQPtrListIterator lit( g->enums ); lit.current(); ++lit ) if ( lit.current()->name == p->type && lit.current()->set ) ok = FALSE; if ( !ok ) continue; p->sspec = spec; p->setfunc = f; p->oredEnum = 0; break; } else if ( !isVariantType( p->type ) && f->args->count() == 1 ) { if ( tmp == "int" || tmp == "uint" || tmp == "unsigned int" ) { if ( p->oredEnum == 0 ) continue; // Test wether the enum is really a set (unfortunately we don't know enums of super classes) bool ok = TRUE; for( TQPtrListIterator lit( g->enums ); lit.current(); ++lit ) if ( lit.current()->name == p->type && !lit.current()->set ) ok = FALSE; if ( !ok ) continue; p->sspec = spec; p->setfunc = f; p->oredEnum = 1; p->enumsettype = tmp; } } } if ( p->setfunc == 0 ) { if ( displayWarnings ) { // Is the type a set, that means, mentioned in Q_SETS ? bool set = FALSE; for( TQPtrListIterator lit( g->enums ); lit.current(); ++lit ) if ( lit.current()->name == p->type && lit.current()->set ) set = TRUE; fprintf( stderr, ErrorFormatString" Warning: Property '%s' not writable.\n", g->fileName.data(), p->lineNo, (const char*) p->name ); fprintf( stderr, " Have been looking for public set functions \n"); if ( !set && p->oredEnum != 1 ) { fprintf( stderr, " void %s( %s )\n" " void %s( %s& )\n" " void %s( const %s& )\n", (const char*) p->set, (const char*) p->type, (const char*) p->set, (const char*) p->type, (const char*) p->set, (const char*) p->type ); } if ( set || ( !isPropertyType( p->type ) && p->oredEnum != 0 ) ) { fprintf( stderr, " void %s( int )\n" " void %s( uint )\n" " void %s( unsigned int )\n", (const char*) p->set, (const char*) p->set, (const char*) p->set ); } if ( p->type == "TQCString" ) fprintf( stderr, " void %s( const char* ) const\n", (const char*) p->set ); if ( !candidates.isEmpty() ) { fprintf( stderr, " but only found the mismatching candidate(s)\n"); for ( Function* f = candidates.first(); f; f = candidates.next() ) { TQCString typstr = ""; Argument *a = f->args->first(); int count = 0; while ( a ) { if ( !a->leftType.isEmpty() || ! a->rightType.isEmpty() ) { if ( count++ ) typstr += ","; typstr += a->leftType; typstr += a->rightType; } a = f->args->next(); } fprintf( stderr, " %s:%d: %s %s(%s)\n", g->fileName.data(), f->lineNo, (const char*) f->type,(const char*) f->name, (const char*) typstr ); } } } } } } // // Create meta data // if ( g->props.count() ) { if ( displayWarnings && !Q_OBJECTdetected ) moc_err("The declaration of the class \"%s\" contains properties" " but no Q_OBJECT macro.", g->className.data()); fprintf( out, "#ifndef QT_NO_PROPERTIES\n" ); fprintf( out, " static const TQMetaProperty props_tbl[%d] = {\n ", g->props.count() ); for( TQPtrListIterator it( g->props ); it.current(); ++it ) { fprintf( out, "\t{ \"%s\",\"%s\", ", it.current()->type.data(), it.current()->name.data() ); int flags = Invalid; if ( !isVariantType( it.current()->type ) ) { flags |= EnumOrSet; if ( !isEnumType( it.current()->type ) ) flags |= UnresolvedEnum; } else { flags |= qvariant_nameToType( it.current()->type ) << 24; } if ( it.current()->getfunc ) flags |= Readable; if ( it.current()->setfunc ) { flags |= Writable; if ( it.current()->stdSet() ) flags |= StdSet; } if ( it.current()->override ) flags |= Override; if ( it.current()->designable.isEmpty() ) flags |= DesignableOverride; else if ( it.current()->designable == "false" ) flags |= NotDesignable; if ( it.current()->scriptable.isEmpty() ) flags |= ScriptableOverride; else if ( it.current()->scriptable == "false" ) flags |= NotScriptable; if ( it.current()->stored.isEmpty() ) flags |= StoredOverride; else if ( it.current()->stored == "false" ) flags |= NotStored; fprintf( out, "0x%.4x, ", flags ); fprintf( out, "&%s::metaObj, ", (const char*) qualifiedClassName() ); if ( !isVariantType( it.current()->type ) ) { int enumpos = -1; int k = 0; for( TQPtrListIterator eit( g->enums ); eit.current(); ++eit, ++k ) { if ( eit.current()->name == it.current()->type ) enumpos = k; } // Is it an enum of this class ? if ( enumpos != -1 ) fprintf( out, "&enum_tbl[%i], ", enumpos ); else fprintf( out, "0, "); } else { fprintf( out, "0, "); } fprintf( out, "-1 }" ); if ( !it.atLast() ) fprintf( out, ",\n" ); else fprintf( out, "\n" ); } fprintf( out, " };\n" ); fprintf( out, "#endif // QT_NO_PROPERTIES\n" ); } return g->props.count(); } int generateClassInfos() { if ( g->infos.isEmpty() ) return 0; if ( displayWarnings && !Q_OBJECTdetected ) moc_err("The declaration of the class \"%s\" contains class infos" " but no Q_OBJECT macro.", g->className.data()); fprintf( out, " static const TQClassInfo classinfo_tbl[] = {\n" ); int i = 0; for( TQPtrListIterator it( g->infos ); it.current(); ++it, ++i ) { if ( i ) fprintf( out, ",\n" ); fprintf( out, "\t{ \"%s\", \"%s\" }", it.current()->name.data(),it.current()->value.data() ); } fprintf( out, "\n };\n" ); return i; } void generateClass() // generate C++ source code for a class { const char *hdr1 = "/****************************************************************************\n" "** %s meta object code from reading C++ file '%s'\n**\n"; const char *hdr2 = "** Created: %s\n" const char *hdr3 = "** WARNING! All changes made in this file will be lost!\n"; const char *hdr4 = "*****************************************************************************/\n\n"; int i; if ( skipClass ) // don't generate for class return; if ( !Q_OBJECTdetected ) { if ( g->signals.count() == 0 && g->slots.count() == 0 && g->props.count() == 0 && g->infos.count() == 0 ) return; if ( displayWarnings && (g->signals.count() + g->slots.count()) != 0 ) moc_err("The declaration of the class \"%s\" contains signals " "or slots\n\t but no Q_OBJECT macro.", g->className.data()); } else { if ( g->superClassName.isEmpty() ) moc_err("The declaration of the class \"%s\" contains the\n" "\tQ_OBJECT macro but does not inherit from any class!\n" "\tInherit from TQObject or one of its descendants" " or remove Q_OBJECT.", g->className.data() ); } if ( templateClass ) { // don't generate for class moc_err( "Sorry, TQt does not support templates that contain\n" "\tsignals, slots or Q_OBJECT." ); return; } g->generatedCode = TRUE; g->gen_count++; if ( g->gen_count == 1 ) { // first class to be generated TQDateTime dt = TQDateTime::currentDateTime(); TQCString dstr = dt.toString().ascii(); TQCString fn = g->fileName; i = g->fileName.length()-1; while ( i>0 && g->fileName[i-1] != '/' && g->fileName[i-1] != '\\' ) i--; // skip path if ( i >= 0 ) fn = &g->fileName[i]; fprintf( out, hdr1, (const char*)qualifiedClassName(),(const char*)fn); fprintf( out, hdr2, (const char*)dstr ); fprintf( out, hdr3 ); fprintf( out, hdr4 ); if ( !g->noInclude ) { /* The header file might be a TQt header file with QT_NO_COMPAT macros around signals, slots or properties. Without the #undef, we cannot compile the TQt library with QT_NO_COMPAT defined. Header files of libraries build around TQt can also use QT_NO_COMPAT, so this #undef might be beneficial to users of TQt, and not only to developers of TQt. */ fprintf( out, "#undef QT_NO_COMPAT\n" ); if ( !g->pchFile.isEmpty() ) fprintf( out, "#include \"%s\" // PCH include\n", (const char*)g->pchFile ); if ( !g->includePath.isEmpty() && g->includePath.right(1) != "/" ) g->includePath += "/"; g->includeFiles.first(); while ( g->includeFiles.current() ) { TQCString inc = g->includeFiles.current(); if ( inc[0] != '<' && inc[0] != '"' ) { if ( !g->includePath.isEmpty() && g->includePath != "./" ) inc.prepend( g->includePath ); inc = "\"" + inc + "\""; } fprintf( out, "#include %s\n", (const char *)inc ); g->includeFiles.next(); } } fprintf( out, "#include <%sqmetaobject.h>\n", (const char*)g->qtPath ); fprintf( out, "#include <%sqapplication.h>\n\n", (const char*)g->qtPath ); fprintf( out, "#include <%sprivate/qucomextra_p.h>\n", (const char*)g->qtPath ); fprintf( out, "#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != %d)\n", formatRevision ); 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 TQt.\"\n#error \"(The moc has changed too" " much.)\"\n", QT_VERSION_STR ); fprintf( out, "#endif\n\n" ); } else { fprintf( out, "\n\n" ); } if ( !g->hasVariantIncluded ) { bool needToIncludeVariant = !g->props.isEmpty(); for ( Function* f =g->slots.first(); f && !needToIncludeVariant; f=g->slots.next() ) needToIncludeVariant = ( f->type != "void" && !validUType( f->type ) && isVariantType( f->type) ); if ( needToIncludeVariant ) { fprintf( out, "#include <%sqvariant.h>\n", (const char*)g->qtPath ); g->hasVariantIncluded = TRUE; } } bool isTQObject = g->className == "TQObject" ; // // Generate virtual function className() // fprintf( out, "const char *%s::className() const\n{\n ", (const char*)qualifiedClassName() ); fprintf( out, "return \"%s\";\n}\n\n", (const char*)qualifiedClassName() ); // // Generate static metaObj variable // fprintf( out, "TQMetaObject *%s::metaObj = 0;\n", (const char*)qualifiedClassName()); // // Generate static cleanup object variable // TQCString cleanup = qualifiedClassName().copy(); for ( int cnpos = 0; cnpos < cleanup.length(); cnpos++ ) { if ( cleanup[cnpos] == ':' ) cleanup[cnpos] = '_'; } fprintf( out, "static TQMetaObjectCleanUp cleanUp_%s( \"%s\", &%s::staticMetaObject );\n\n", (const char*)cleanup, (const char*)qualifiedClassName(), (const char*)qualifiedClassName() ); // // Generate tr and trUtf8 member functions // fprintf( out, "#ifndef QT_NO_TRANSLATION\n" ); fprintf( out, "TQString %s::tr( const char *s, const char *c )\n{\n", (const char*)qualifiedClassName() ); fprintf( out, " if ( qApp )\n" ); fprintf( out, "\treturn qApp->translate( \"%s\", s, c," " TQApplication::DefaultCodec );\n", (const char*)qualifiedClassName() ); fprintf( out, " else\n" ); fprintf( out, "\treturn TQString::fromLatin1( s );\n"); fprintf( out, "}\n" ); fprintf( out, "#ifndef QT_NO_TRANSLATION_UTF8\n" ); fprintf( out, "TQString %s::trUtf8( const char *s, const char *c )\n{\n", (const char*)qualifiedClassName() ); fprintf( out, " if ( qApp )\n" ); fprintf( out, "\treturn qApp->translate( \"%s\", s, c," " TQApplication::UnicodeUTF8 );\n", (const char*)qualifiedClassName() ); fprintf( out, " else\n" ); fprintf( out, "\treturn TQString::fromUtf8( s );\n" ); fprintf( out, "}\n" ); fprintf( out, "#endif // QT_NO_TRANSLATION_UTF8\n\n" ); fprintf( out, "#endif // QT_NO_TRANSLATION\n\n" ); // // Generate staticMetaObject member function // fprintf( out, "TQMetaObject* %s::staticMetaObject()\n{\n", (const char*)qualifiedClassName() ); fprintf( out, " if ( metaObj )\n\treturn metaObj;\n" ); if ( isTQObject ) fprintf( out, " TQMetaObject* parentObject = staticTQtMetaObject();\n" ); else if ( !g->superClassName.isEmpty() ) fprintf( out, " TQMetaObject* parentObject = %s::staticMetaObject();\n", (const char*)g->superClassName ); else fprintf( out, " TQMetaObject* parentObject = 0;\n" ); // // Build the classinfo array // int n_infos = generateClassInfos(); // Build the enums array // Enums HAVE to be generated BEFORE the properties and slots // int n_enums = generateEnums(); // // Build slots array in staticMetaObject() // generateFuncs( &g->slots, "slot", Slot_Num ); // // Build signals array in staticMetaObject() // generateFuncs( &g->signals, "signal", Signal_Num ); // // Build property array in staticMetaObject() // int n_props = generateProps(); // // Finally code to create and return meta object // fprintf( out, " metaObj = TQMetaObject::new_metaobject(\n" "\t\"%s\", parentObject,\n", (const char*)qualifiedClassName() ); if ( g->slots.count() ) fprintf( out, "\tslot_tbl, %d,\n", g->slots.count() ); else fprintf( out, "\t0, 0,\n" ); if ( g->signals.count() ) fprintf( out, "\tsignal_tbl, %d,\n", g->signals.count() ); else fprintf( out, "\t0, 0,\n" ); fprintf( out, "#ifndef QT_NO_PROPERTIES\n" ); if ( n_props ) fprintf( out, "\tprops_tbl, %d,\n", n_props ); else fprintf( out, "\t0, 0,\n" ); if ( n_enums ) fprintf( out, "\tenum_tbl, %d,\n", n_enums ); else fprintf( out, "\t0, 0,\n" ); fprintf( out, "#endif // QT_NO_PROPERTIES\n" ); if ( n_infos ) fprintf( out, "\tclassinfo_tbl, %d );\n", n_infos ); else fprintf( out, "\t0, 0 );\n" ); // // Setup cleanup handler and return meta object // fprintf( out, " cleanUp_%s.setMetaObject( metaObj );\n", cleanup.data() ); fprintf( out, " return metaObj;\n}\n" ); // // End of function staticMetaObject() // // // Generate smart cast function // fprintf( out, "\nvoid* %s::qt_cast( const char* clname )\n{\n", (const char*)qualifiedClassName() ); fprintf( out, " if ( !qstrcmp( clname, \"%s\" ) )\n" "\treturn this;\n", (const char*)qualifiedClassName() ); for ( const char* cname = g->multipleSuperClasses.first(); cname; cname = g->multipleSuperClasses.next() ) { fprintf( out, " if ( !qstrcmp( clname, \"%s\" ) )\n", cname); TQCString fixed(cname); while (fixed.find(">>") != -1) fixed = fixed.replace(">>", "> >"); fprintf( out, "\treturn (%s*)this;\n", fixed.data()); } if ( !g->superClassName.isEmpty() && !isTQObject ) fprintf( out, " return %s::qt_cast( clname );\n", (const char*)purestSuperClassName() ); else fprintf( out, " return 0;\n" ); fprintf( out, "}\n" ); // // Generate internal signal functions // Function *f; f = g->signals.first(); // make internal signal methods static bool included_list_headers = FALSE; int sigindex = 0; while ( f ) { TQCString argstr; char buf[12]; Argument *a = f->args->first(); int offset = 0; const char *predef_call_func = 0; bool hasReturnValue = f->type != "void" && (validUType( f->type ) || isVariantType( f->type) ); if ( hasReturnValue ) { ; // no predefined function available } else if ( !a ) { predef_call_func = "activate_signal"; } else if ( f->args->count() == 1 ) { TQCString ctype = (a->leftType + ' ' + a->rightType).simplifyWhiteSpace(); if ( !isInOut( ctype ) ) { TQCString utype = uType( ctype ); if ( utype == "bool" ) predef_call_func = "activate_signal_bool"; else if ( utype == "TQString" || utype == "int" || utype == "double" ) predef_call_func = "activate_signal"; } } if ( !predef_call_func && !included_list_headers ) { // yes we need it, because otherwise QT_VERSION may not be defined fprintf( out, "\n#include <%sqobjectdefs.h>\n", (const char*)g->qtPath ); fprintf( out, "#include <%sqsignalslotimp.h>\n", (const char*)g->qtPath ); included_list_headers = TRUE; } while ( a ) { // argument list if ( !a->leftType.isEmpty() || !a->rightType.isEmpty() ) { argstr += a->leftType; argstr += " "; sprintf( buf, "t%d", offset++ ); argstr += buf; argstr += a->rightType; a = f->args->next(); if ( a ) argstr += ", "; } else { a = f->args->next(); } } fixRightAngles( &argstr ); fprintf( out, "\n// SIGNAL %s\n", (const char*)f->name ); fprintf( out, "%s %s::%s(", (const char*) f->type, (const char*)qualifiedClassName(), (const char*)f->name ); if ( argstr.isEmpty() ) fprintf( out, ")\n{\n" ); else fprintf( out, " %s )\n{\n", (const char*)argstr ); if ( predef_call_func ) { fprintf( out, " %s( staticMetaObject()->signalOffset() + %d", predef_call_func, sigindex ); if ( !argstr.isEmpty() ) fprintf( out, ", t0" ); fprintf( out, " );\n}\n" ); } else { if ( hasReturnValue ) fprintf( out, " %s something;\n", f->type.data() ); int nargs = f->args->count(); fprintf( out, " if ( signalsBlocked() )\n\treturn%s;\n", hasReturnValue ? " something" : "" ); fprintf( out, " TQConnectionList *clist = receivers( staticMetaObject()->signalOffset() + %d );\n", sigindex ); fprintf( out, " if ( !clist )\n\treturn%s;\n", hasReturnValue ? " something" : "" ); fprintf( out, " TQUObject o[%d];\n", f->args->count() + 1 ); // initialize return value to something if ( hasReturnValue ) { if ( validUType( f->type ) ) { TQCString utype = uType( f->type ); fprintf( out, " static_QUType_%s.set(o,something);\n", utype.data() ); } else if ( uType( f->type ) == "varptr" ) { fprintf( out, " static_QUType_varptr.set(o,&something);\n" ); } else { fprintf( out, " static_QUType_ptr.set(o,&something);\n" ); } } // initialize arguments if ( !f->args->isEmpty() ) { offset = 0; Argument* a = f->args->first(); while ( a ) { TQCString type = a->leftType + ' ' + a->rightType; type = type.simplifyWhiteSpace(); if ( validUType( type ) ) { TQCString utype = uType( type ); fprintf( out, " static_QUType_%s.set(o+%d,t%d);\n", utype.data(), offset+1, offset ); } else if ( uType( type ) == "varptr" ) { fprintf( out, " static_QUType_varptr.set(o+%d,&t%d);\n", offset+1, offset ); } else { fprintf( out, " static_QUType_ptr.set(o+%d,&t%d);\n", offset+1, offset ); } a = f->args->next(); offset++; } } fprintf( out, " activate_signal( clist, o );\n" ); // get return values from inOut parameters if ( !f->args->isEmpty() ) { offset = 0; Argument* a = f->args->first(); while ( a ) { TQCString type = a->leftType + ' ' + a->rightType; type = type.simplifyWhiteSpace(); if ( validUType( type ) && isInOut( type ) ) { TQCString utype = uType( type ); if ( utype == "enum" ) fprintf( out, " t%d = (%s)static_QUType_%s.get(o+%d);\n", offset, type.data(), utype.data(), offset+1 ); else if ( utype == "ptr" && type.right(2) == "**" ) fprintf( out, " if (t%d) *t%d = *(%s)static_QUType_ptr.get(o+%d);\n", offset, offset, type.data(), offset+1 ); else fprintf( out, " t%d = static_QUType_%s.get(o+%d);\n", offset, utype.data(), offset+1 ); } a = f->args->next(); offset++; } } // get and return return value if ( hasReturnValue ) { TQCString utype = uType( f->type ); if ( utype == "enum" || utype == "ptr" || utype == "varptr" ) // need cast fprintf( out, " return (%s)static_QUType_%s.get(o);\n", f->type.data(), utype.data() ); else fprintf( out, " return static_QUType_%s.get(o);\n", utype.data() ); } fprintf( out, "}\n" ); } f = g->signals.next(); sigindex++; } // // Generate internal qt_invoke() function // fprintf( out, "\nbool %s::qt_invoke( int _id, TQUObject* _o )\n{\n", qualifiedClassName().data() ); if( !g->slots.isEmpty() ) { fprintf( out, " switch ( _id - staticMetaObject()->slotOffset() ) {\n" ); int slotindex = -1; for ( f = g->slots.first(); f; f = g->slots.next() ) { slotindex ++; if ( f->type == "void" && f->args->isEmpty() ) { fprintf( out, " case %d: %s(); break;\n", slotindex, f->name.data() ); continue; } fprintf( out, " case %d: ", slotindex ); bool hasReturnValue = FALSE; bool hasVariantReturn = FALSE; if ( f->type != "void" ) { if ( validUType( f->type )) { hasReturnValue = TRUE; fprintf( out, "static_QUType_%s.set(_o,", uType(f->type).data() ); } else if ( isVariantType( f->type ) ) { hasReturnValue = hasVariantReturn = TRUE; // do not need special handling for bool since this is handled as utype fprintf( out, "static_QUType_TQVariant.set(_o,TQVariant(" ); } } int offset = 0; fprintf( out, "%s(", f->name.data() ); Argument* a = f->args->first(); while ( a ) { TQCString type = a->leftType + ' ' + a->rightType; type = type.simplifyWhiteSpace(); fixRightAngles( &type ); if ( validUType( type ) ) { TQCString utype = uType( type ); if ( utype == "ptr" || utype == "varptr" || utype == "enum" ) fprintf( out, "(%s)static_QUType_%s.get(_o+%d)", type.data(), utype.data(), offset+1 ); else fprintf( out, "(%s)static_QUType_%s.get(_o+%d)", type.data(), utype.data(), offset+1 ); } else { TQCString castType = castToUType( type ); if(castType == type) fprintf( out, "(%s)(*((%s*)static_QUType_ptr.get(_o+%d)))", type.data(), castType.data(), offset+1 ); else fprintf( out, "(%s)*((%s*)static_QUType_ptr.get(_o+%d))", type.data(), castType.data(), offset+1 ); } a = f->args->next(); if ( a ) fprintf( out, "," ); offset++; } fprintf( out, ")" ); if ( hasReturnValue ) fprintf( out, ")" ); if ( hasVariantReturn ) fprintf( out, ")" ); fprintf( out, "; break;\n" ); } fprintf( out, " default:\n" ); if ( !g->superClassName.isEmpty() && !isTQObject ) { fprintf( out, "\treturn %s::qt_invoke( _id, _o );\n", (const char *) purestSuperClassName() ); } else { fprintf( out, "\treturn FALSE;\n" ); } fprintf( out, " }\n" ); fprintf( out, " return TRUE;\n}\n" ); } else { if ( !g->superClassName.isEmpty() && !isTQObject ) fprintf( out, " return %s::qt_invoke(_id,_o);\n}\n", (const char *) purestSuperClassName() ); else fprintf( out, " return FALSE;\n}\n" ); } // // Generate internal qt_emit() function // fprintf( out, "\nbool %s::qt_emit( int _id, TQUObject* _o )\n{\n", qualifiedClassName().data() ); if ( !g->signals.isEmpty() ) { fprintf( out, " switch ( _id - staticMetaObject()->signalOffset() ) {\n" ); int signalindex = -1; for ( f = g->signals.first(); f; f = g->signals.next() ) { signalindex++; if ( f->type == "void" && f->args->isEmpty() ) { fprintf( out, " case %d: %s(); break;\n", signalindex, f->name.data() ); continue; } fprintf( out, " case %d: ", signalindex ); bool hasReturnValue = FALSE; if ( f->type != "void" && validUType( f->type )) { hasReturnValue = TRUE; fprintf( out, "static_QUType_%s.set(_o,", uType(f->type).data() ); } int offset = 0; fprintf( out, "%s(", f->name.data() ); Argument* a = f->args->first(); while ( a ) { TQCString type = a->leftType + ' ' + a->rightType; type = type.simplifyWhiteSpace(); fixRightAngles( &type ); if ( validUType( type ) ) { TQCString utype = uType( type ); if ( utype == "ptr" || utype == "varptr" || utype == "enum" ) fprintf( out, "(%s)static_QUType_%s.get(_o+%d)", type.data(), utype.data(), offset+1 ); else fprintf( out, "(%s)static_QUType_%s.get(_o+%d)", type.data(), utype.data(), offset+1 ); } else { TQCString castType = castToUType( type ); if(castType == type) fprintf( out, "(%s)(*((%s*)static_QUType_ptr.get(_o+%d)))", type.data(), castType.data(), offset+1 ); else fprintf( out, "(%s)*((%s*)static_QUType_ptr.get(_o+%d))", type.data(), castType.data(), offset+1 ); } a = f->args->next(); if ( a ) fprintf( out, "," ); offset++; } fprintf( out, ")" ); if ( hasReturnValue ) fprintf( out, ")" ); fprintf( out, "; break;\n" ); } fprintf( out, " default:\n" ); if ( !g->superClassName.isEmpty() && !isTQObject ) fprintf( out, "\treturn %s::qt_emit(_id,_o);\n", (const char *) purestSuperClassName() ); else fprintf( out, "\treturn FALSE;\n" ); fprintf( out, " }\n" ); fprintf( out, " return TRUE;\n}\n" ); } else { if ( !g->superClassName.isEmpty() && !isTQObject ) fprintf( out, " return %s::qt_emit(_id,_o);\n}\n", (const char *) purestSuperClassName() ); else fprintf( out, " return FALSE;\n}\n" ); } fprintf( out, "#ifndef QT_NO_PROPERTIES\n" ); // // Generate internal qt_property() functions // fprintf( out, "\nbool %s::qt_property( int id, int f, TQVariant* v)\n{\n", qualifiedClassName().data() ); if ( !g->props.isEmpty() ) { fprintf( out, " switch ( id - staticMetaObject()->propertyOffset() ) {\n" ); int propindex = -1; bool need_resolve = FALSE; for( TQPtrListIterator it( g->props ); it.current(); ++it ){ propindex ++; fprintf( out, " case %d: ", propindex ); fprintf( out, "switch( f ) {\n" ); uint flag_break = 0; uint flag_propagate = 0; if ( it.current()->setfunc ) { fprintf( out, "\tcase 0: %s(", it.current()->setfunc->name.data() ); TQCString type = it.current()->type.copy(); // detach on purpose if ( it.current()->oredEnum ) type = it.current()->enumsettype; if ( type == "uint" ) fprintf( out, "v->asUInt()" ); else if ( type == "unsigned int" ) fprintf( out, "(uint)v->asUInt()" ); else if ( type == "TQMap" ) fprintf( out, "v->asMap()" ); else if ( type == "TQValueList" ) fprintf( out, "v->asList()" ); else if ( type == "Q_LLONG" ) fprintf( out, "v->asLongLong()" ); else if ( type == "Q_ULLONG" ) fprintf( out, "v->asULongLong()" ); else if ( isVariantType( type ) ) { if (( type[0] == 'T' ) && ( type[1] == 'Q' )) type = type.mid(2); else type[0] = toupper( type[0] ); fprintf( out, "v->as%s()", type.data() ); } else { fprintf( out, "(%s&)v->asInt()", type.data() ); } fprintf( out, "); break;\n" ); } else if ( it.current()->override ) { flag_propagate |= 1 << (0+1); } if ( it.current()->getfunc ) { if ( it.current()->gspec == Property::Pointer ) fprintf( out, "\tcase 1: if ( this->%s() ) *v = TQVariant( %s*%s()%s ); break;\n", it.current()->getfunc->name.data(), !isVariantType( it.current()->type ) ? "(int)" : "", it.current()->getfunc->name.data(), it.current()->type == "bool" ? ", 0" : "" ); else fprintf( out, "\tcase 1: *v = TQVariant( %sthis->%s()%s ); break;\n", !isVariantType( it.current()->type ) ? "(int)" : "", it.current()->getfunc->name.data(), it.current()->type == "bool" ? ", 0" : "" ); } else if ( it.current()->override ) { flag_propagate |= 1<< (1+1); } if ( !it.current()->reset.isEmpty() ) fprintf( out, "\tcase 2: this->%s(); break;\n", it.current()->reset.data() ); if ( it.current()->designable.isEmpty() ) flag_propagate |= 1 << (3+1); else if ( it.current()->designable == "true" ) flag_break |= 1 << (3+1); else if ( it.current()->designable != "false" ) fprintf( out, "\tcase 3: return this->%s();\n", it.current()->designable.data() ); if ( it.current()->scriptable.isEmpty() ) flag_propagate |= 1 << (4+1); else if ( it.current()->scriptable == "true" ) flag_break |= 1 << (4+1); else if ( it.current()->scriptable != "false" ) fprintf( out, "\tcase 4: return this->%s();\n", it.current()->scriptable.data() ); if ( it.current()->stored.isEmpty() ) flag_propagate |= 1 << (5+1); else if ( it.current()->stored == "true" ) flag_break |= 1 << (5+1); else if ( it.current()->stored != "false" ) fprintf( out, "\tcase 5: return this->%s();\n", it.current()->stored.data() ); int i = 0; if ( flag_propagate != 0 ) { fprintf( out, "\t" ); for ( i = 0; i <= 5; i++ ) { if ( flag_propagate & (1 << (i+1) ) ) fprintf( out, "case %d: ", i ); } if (!g->superClassName.isEmpty() && !isTQObject ) { fprintf( out, "goto resolve;\n" ); need_resolve = TRUE; } else { fprintf( out, " return FALSE;\n" ); } } if ( flag_break != 0 ) { fprintf( out, "\t" ); for ( i = 0; i <= 5; i++ ) { if ( flag_break & (1 << (i+1) ) ) fprintf( out, "case %d: ", i ); } fprintf( out, "break;\n"); } fprintf( out, "\tdefault: return FALSE;\n } break;\n" ); } fprintf( out, " default:\n" ); if ( !g->superClassName.isEmpty() && !isTQObject ) fprintf( out, "\treturn %s::qt_property( id, f, v );\n", (const char *) purestSuperClassName() ); else fprintf( out, "\treturn FALSE;\n" ); fprintf( out, " }\n" ); fprintf( out, " return TRUE;\n" ); if ( need_resolve ) fprintf( out, "resolve:\n return %s::qt_property( staticMetaObject()->resolveProperty(id), f, v );\n", (const char *) purestSuperClassName() ); fprintf( out, "}\n" ); } else { if ( !g->superClassName.isEmpty() && !isTQObject ) fprintf( out, " return %s::qt_property( id, f, v);\n}\n", (const char *) purestSuperClassName() ); else fprintf( out, " return FALSE;\n}\n" ); } fprintf( out, "\nbool %s::qt_static_property( TQObject* , int , int , TQVariant* ){ return FALSE; }\n", qualifiedClassName().data() ); fprintf( out, "#endif // QT_NO_PROPERTIES\n" ); } ArgList *addArg( Argument *a ) // add argument to list { if ( (!a->leftType.isEmpty() || !a->rightType.isEmpty() ) ) //filter out truely void arguments tmpArgList->append( a ); return tmpArgList; } void addEnum() { // Avoid duplicates for( TQPtrListIterator lit( g->enums ); lit.current(); ++lit ) { if ( lit.current()->name == tmpEnum->name ) { if ( displayWarnings ) moc_err( "Enum %s defined twice.", (const char*)tmpEnum->name ); } } // Only look at types mentioned in Q_ENUMS and Q_SETS if ( g->qtEnums.contains( tmpEnum->name ) || g->qtSets.contains( tmpEnum->name ) ) { g->enums.append( tmpEnum ); if ( g->qtSets.contains( tmpEnum->name ) ) tmpEnum->set = TRUE; else tmpEnum->set = FALSE; } else delete tmpEnum; tmpEnum = new Enum; } void addMember( Member m ) { if ( skipFunc ) { tmpFunc->args = tmpArgList; // just to be sure delete tmpFunc; tmpArgList = new ArgList; // ugly but works tmpFunc = new Function; skipFunc = FALSE; return; } tmpFunc->type = tmpFunc->type.simplifyWhiteSpace(); tmpFunc->access = tmpAccess; tmpFunc->args = tmpArgList; tmpFunc->lineNo = lineNo; for ( ;; ) { g->funcs.append( tmpFunc ); if ( m == SignalMember ) { g->signals.append( tmpFunc ); break; } else { if ( m == SlotMember ) g->slots.append( tmpFunc ); // PropertyCandidateMember or SlotMember if ( !tmpFunc->name.isEmpty() && tmpFunc->access == Public ) g->propfuncs.append( tmpFunc ); if ( !tmpFunc->args || !tmpFunc->args->hasDefaultArguments() ) break; tmpFunc = new Function( *tmpFunc ); tmpFunc->args = tmpFunc->args->magicClone(); } } skipFunc = FALSE; tmpFunc = new Function; tmpArgList = new ArgList; } void checkPropertyName( const char* ident ) { if ( ident[0] == '_' ) { moc_err( "Invalid property name '%s'.", ident ); return; } }