source: trunk/src/moc/moc.y@ 9

Last change on this file since 9 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 101.4 KB
Line 
1/****************************************************************************
2** $Id: moc.y 2 2005-11-16 15:49:26Z dmik $
3**
4** Parser and code generator for meta object compiler
5**
6** Created : 930417
7**
8** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
9**
10** This file is part of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36** --------------------------------------------------------------------------
37**
38** This compiler reads a C++ header file with class definitions and ouputs
39** C++ code to build a meta class. The meta data includes public methods
40** (not constructors, destructors or operator functions), signals and slot
41** definitions. The output file should be compiled and linked into the
42** target application.
43**
44** C++ header files are assumed to have correct syntax, and we are therefore
45** doing less strict checking than C++ compilers.
46**
47** The C++ grammar has been adopted from the "The Annotated C++ Reference
48** Manual" (ARM), by Ellis and Stroustrup (Addison Wesley, 1992).
49**
50** Notice that this code is not possible to compile with GNU bison, instead
51** use standard AT&T yacc or Berkeley yacc.
52*****************************************************************************/
53
54%{
55#define MOC_YACC_CODE
56void yyerror( const char *msg );
57
58#include "qplatformdefs.h"
59#include "qasciidict.h"
60#include "qdatetime.h"
61#include "qdict.h"
62#include "qfile.h"
63#include "qdir.h"
64#include "qptrlist.h"
65#include "qregexp.h"
66#include "qstrlist.h"
67#ifdef MOC_MWERKS_PLUGIN
68# ifdef Q_OS_MACX
69# undef OLD_DEBUG
70# ifdef DEBUG
71# define OLD_DEBUG DEBUG
72# undef DEBUG
73# endif
74# define DEBUG 0
75# ifndef __IMAGECAPTURE__
76# define __IMAGECAPTURE__
77# endif
78# include <Carbon/Carbon.h>
79# endif
80# include "mwerks_mac.h"
81#endif
82
83#include <ctype.h>
84#include <stdio.h>
85#include <stdlib.h>
86
87#if defined CONST
88#undef CONST
89#endif
90#if defined VOID
91#undef VOID
92#endif
93
94bool isEnumType( const char* type );
95int enumIndex( const char* type );
96bool isVariantType( const char* type );
97int qvariant_nameToType( const char* name );
98static void init(); // initialize
99static void initClass(); // prepare for new class
100static void generateClass(); // generate C++ code for class
101static void initExpression(); // prepare for new expression
102static void enterNameSpace( const char *name = 0 );
103static void leaveNameSpace();
104static void selectOutsideClassState();
105static void registerClassInNamespace();
106static bool suppress_func_warn = FALSE;
107static void func_warn( const char *msg );
108static void moc_warn( const char *msg );
109static void moc_err( const char *s );
110static void moc_err( const char *s1, const char *s2 );
111static void operatorError();
112static void checkPropertyName( const char* ident );
113
114static const char* const utype_map[] =
115{
116 "bool",
117 "int",
118 "double",
119 "QString",
120 "QVariant",
121 0
122};
123
124bool validUType( QCString ctype )
125{
126 if ( ctype.left(6) == "const " )
127 ctype = ctype.mid( 6, ctype.length() - 6 );
128 if ( ctype.right(1) == "&" )
129 ctype = ctype.left( ctype.length() - 1 );
130 else if ( ctype.right(1) == "*" )
131 return TRUE;
132
133 int i = -1;
134 while ( utype_map[++i] )
135 if ( ctype == utype_map[i] )
136 return TRUE;
137
138 return isEnumType( ctype );
139}
140
141QCString castToUType( QCString ctype )
142{
143 if ( ctype.right(1) == "&" )
144 ctype = ctype.left( ctype.length() - 1 );
145 if( ctype.right(1) == "]") {
146 int lb = ctype.findRev('[');
147 if(lb != -1)
148 ctype = ctype.left(lb) + "*";
149 }
150 return ctype;
151}
152
153QCString rawUType( QCString ctype )
154{
155 ctype = castToUType( ctype );
156 if ( ctype.left(6) == "const " )
157 ctype = ctype.mid( 6, ctype.length() - 6 );
158 return ctype;
159}
160
161QCString uType( QCString ctype )
162{
163 if ( !validUType( ctype ) ) {
164 if ( isVariantType( rawUType(ctype) ) )
165 return "varptr";
166 else
167 return "ptr";
168 }
169 if ( ctype.left(6) == "const " )
170 ctype = ctype.mid( 6, ctype.length() - 6 );
171 if ( ctype.right(1) == "&" ) {
172 ctype = ctype.left( ctype.length() - 1 );
173 } else if ( ctype.right(1) == "*" ) {
174 QCString raw = ctype.left( ctype.length() - 1 );
175 ctype = "ptr";
176 if ( raw == "char" )
177 ctype = "charstar";
178 else if ( raw == "QUnknownInterface" )
179 ctype = "iface";
180 else if ( raw == "QDispatchInterface" )
181 ctype = "idisp";
182 else if ( isVariantType( raw ) )
183 ctype = "varptr";
184 }
185 if ( isEnumType( ctype ) )
186 ctype = "enum";
187 return ctype;
188}
189
190bool isInOut( QCString ctype )
191{
192 if ( ctype.left(6) == "const " )
193 return FALSE;
194 if ( ctype.right(1) == "&" )
195 return TRUE;
196 if ( ctype.right(2) == "**" )
197 return TRUE;
198 return FALSE;
199}
200
201QCString uTypeExtra( QCString ctype )
202{
203 QCString typeExtra = "0";
204 if ( !validUType( ctype ) ) {
205 if ( isVariantType( rawUType(ctype) ) )
206 typeExtra.sprintf("\"\\x%02x\"", qvariant_nameToType( rawUType(ctype) ) );
207 else
208 typeExtra.sprintf( "\"%s\"", rawUType(ctype).data() );
209 return typeExtra;
210 }
211 if ( ctype.left(6) == "const " )
212 ctype = ctype.mid( 6, ctype.length() - 6 );
213 if ( ctype.right(1) == "&" )
214 ctype = ctype.left( ctype.length() - 1 );
215 if ( ctype.right(1) == "*" ) {
216 QCString raw = ctype.left( ctype.length() - 1 );
217 ctype = "ptr";
218 if ( raw == "char" )
219 ;
220 else if ( isVariantType( raw ) )
221 typeExtra.sprintf("\"\\x%02x\"", qvariant_nameToType( raw ) );
222 else
223 typeExtra.sprintf( "\"%s\"", raw.stripWhiteSpace().data() );
224
225 } else if ( isEnumType( ctype ) ) {
226 int idx = enumIndex( ctype );
227 if ( idx >= 0 ) {
228 typeExtra.sprintf( "&enum_tbl[%d]", enumIndex( ctype ) );
229 } else {
230 typeExtra.sprintf( "parentObject->enumerator(\"%s\", TRUE )", ctype.data() );
231 }
232 typeExtra =
233 "\n#ifndef QT_NO_PROPERTIES\n\t " + typeExtra +
234 "\n#else"
235 "\n\t 0"
236 "\n#endif // QT_NO_PROPERTIES\n\t ";
237 }
238 return typeExtra;
239}
240
241/*
242 Attention!
243 This table is copied from qvariant.cpp. If you change
244 one, change both.
245*/
246static const int ntypes = 35;
247static const char* const type_map[ntypes] =
248{
249 0,
250 "QMap<QString,QVariant>",
251 "QValueList<QVariant>",
252 "QString",
253 "QStringList",
254 "QFont",
255 "QPixmap",
256 "QBrush",
257 "QRect",
258 "QSize",
259 "QColor",
260 "QPalette",
261 "QColorGroup",
262 "QIconSet",
263 "QPoint",
264 "QImage",
265 "int",
266 "uint",
267 "bool",
268 "double",
269 "QCString",
270 "QPointArray",
271 "QRegion",
272 "QBitmap",
273 "QCursor",
274 "QSizePolicy",
275 "QDate",
276 "QTime",
277 "QDateTime",
278 "QByteArray",
279 "QBitArray",
280 "QKeySequence",
281 "QPen",
282 "Q_LLONG",
283 "Q_ULLONG"
284};
285
286int qvariant_nameToType( const char* name )
287{
288 for ( int i = 0; i < ntypes; i++ ) {
289 if ( !qstrcmp( type_map[i], name ) )
290 return i;
291 }
292 return 0;
293}
294
295/*
296 Returns TRUE if the type is a QVariant types.
297*/
298bool isVariantType( const char* type )
299{
300 return qvariant_nameToType( type ) != 0;
301}
302
303/*
304 Replaces '>>' with '> >' (as in 'QValueList<QValueList<double> >').
305 This function must be called to produce valid C++ code. However,
306 the string representation still uses '>>'.
307*/
308void fixRightAngles( QCString *str )
309{
310 str->replace( QRegExp(">>"), "> >" );
311}
312
313static QCString rmWS( const char * );
314
315enum Access { Private, Protected, Public };
316
317
318class Argument // single arg meta data
319{
320public:
321 Argument( const char *left, const char *right, const char* argName = 0, bool isDefaultArgument = FALSE )
322 {
323 leftType = rmWS( left );
324 rightType = rmWS( right );
325 if ( leftType == "void" && rightType.isEmpty() )
326 leftType = "";
327
328 int len = leftType.length();
329
330 /*
331 Convert 'char const *' into 'const char *'. Start at index 1,
332 not 0, because 'const char *' is already OK.
333 */
334 for ( int i = 1; i < len; i++ ) {
335 if ( leftType[i] == 'c' &&
336 strncmp(leftType.data() + i + 1, "onst", 4) == 0 ) {
337 leftType.remove( i, 5 );
338 if ( leftType[i - 1] == ' ' )
339 leftType.remove( i - 1, 1 );
340 leftType.prepend( "const " );
341 break;
342 }
343
344 /*
345 We musn't convert 'char * const *' into 'const char **'
346 and we must beware of 'Bar<const Bla>'.
347 */
348 if ( leftType[i] == '&' || leftType[i] == '*' ||
349 leftType[i] == '<' )
350 break;
351 }
352
353 name = argName;
354 isDefault = isDefaultArgument;
355 }
356
357 QCString leftType;
358 QCString rightType;
359 QCString name;
360 bool isDefault;
361};
362
363class ArgList : public QPtrList<Argument> { // member function arg list
364public:
365 ArgList() { setAutoDelete( TRUE ); }
366 ~ArgList() { clear(); }
367
368 /* the clone has one default argument less, the orignal has all default arguments removed */
369 ArgList* magicClone() {
370 ArgList* l = new ArgList;
371 bool firstDefault = FALSE;
372 for ( first(); current(); next() ) {
373 bool isDefault = current()->isDefault;
374 if ( !firstDefault && isDefault ) {
375 isDefault = FALSE;
376 firstDefault = TRUE;
377 }
378 l->append( new Argument( current()->leftType, current()->rightType, current()->name, isDefault ) );
379 }
380 for ( first(); current(); ) {
381 if ( current()->isDefault )
382 remove();
383 else
384 next();
385 }
386 return l;
387 }
388
389 bool hasDefaultArguments() {
390 for ( Argument* a = first(); a; a = next() ) {
391 if ( a->isDefault )
392 return TRUE;
393 }
394 return FALSE;
395 }
396
397};
398
399
400struct Function // member function meta data
401{
402 Access access;
403 QCString qualifier; // const or volatile
404 QCString name;
405 QCString type;
406 QCString signature;
407 int lineNo;
408 ArgList *args;
409 Function() { args=0;}
410 ~Function() { delete args; }
411 const char* accessAsString() {
412 switch ( access ) {
413 case Private: return "Private";
414 case Protected: return "Protected";
415 default: return "Public";
416 }
417 }
418};
419
420class FuncList : public QPtrList<Function> { // list of member functions
421public:
422 FuncList( bool autoDelete = FALSE ) { setAutoDelete( autoDelete ); }
423
424 FuncList find( const char* name )
425 {
426 FuncList result;
427 for ( QPtrListIterator<Function> it(*this); it.current(); ++it ) {
428 if ( it.current()->name == name )
429 result.append( it.current() );
430 }
431 return result;
432 }
433};
434
435class Enum : public QStrList
436{
437public:
438 QCString name;
439 bool set;
440};
441
442class EnumList : public QPtrList<Enum> { // list of property enums
443public:
444 EnumList() { setAutoDelete(TRUE); }
445};
446
447
448struct Property
449{
450 Property( int l, const char* t, const char* n, const char* s, const char* g, const char* r,
451 const QCString& st, const QCString& d, const QCString& sc, bool ov )
452 : lineNo(l), type(t), name(n), set(s), get(g), reset(r), setfunc(0), getfunc(0),
453 sspec(Unspecified), gspec(Unspecified), stored( st ),
454 designable( d ), scriptable( sc ), override( ov ), oredEnum( -1 )
455 {
456 /*
457 The Q_PROPERTY construct cannot contain any commas, since
458 commas separate macro arguments. We therefore expect users
459 to type "QMap" instead of "QMap<QString, QVariant>". For
460 coherence, we also expect the same for
461 QValueList<QVariant>, the other template class supported by
462 QVariant.
463 */
464 if ( type == "QMap" ) {
465 type = "QMap<QString,QVariant>";
466 } else if ( type == "QValueList" ) {
467 type = "QValueList<QVariant>";
468 } else if ( type == "LongLong" ) {
469 type = "Q_LLONG";
470 } else if ( type == "ULongLong" ) {
471 type = "Q_ULLONG";
472 }
473 }
474
475 int lineNo;
476 QCString type;
477 QCString name;
478 QCString set;
479 QCString get;
480 QCString reset;
481 QCString stored;
482 QCString designable;
483 QCString scriptable;
484 bool override;
485
486 Function* setfunc;
487 Function* getfunc;
488
489 int oredEnum; // If the enums item may be ored. That means the data type is int.
490 // Allowed values are 1 (True), 0 (False), and -1 (Unset)
491 QCString enumsettype; // contains the set function type in case of oredEnum
492 QCString enumgettype; // contains the get function type in case of oredEnum
493
494 enum Specification { Unspecified, Class, Reference, Pointer, ConstCharStar };
495 Specification sspec;
496 Specification gspec;
497
498 bool stdSet() {
499 QCString s = "set";
500 s += toupper( name[0] );
501 s += name.mid( 1 );
502 return s == set;
503 }
504
505 static const char* specToString( Specification s )
506 {
507 switch ( s ) {
508 case Class:
509 return "Class";
510 case Reference:
511 return "Reference";
512 case Pointer:
513 return "Pointer";
514 case ConstCharStar:
515 return "ConstCharStar";
516 default:
517 return "Unspecified";
518 }
519 }
520};
521
522class PropList : public QPtrList<Property> { // list of properties
523public:
524 PropList() { setAutoDelete( TRUE ); }
525};
526
527
528struct ClassInfo
529{
530 ClassInfo( const char* n, const char* v )
531 : name(n), value(v)
532 {}
533 QCString name;
534 QCString value;
535};
536
537class ClassInfoList : public QPtrList<ClassInfo> { // list of class infos
538public:
539 ClassInfoList() { setAutoDelete( TRUE ); }
540};
541
542class parser_reg {
543 public:
544 parser_reg();
545 ~parser_reg();
546
547 // some temporary values
548 QCString tmpExpression; // Used to store the characters the lexer
549 // is currently skipping (see addExpressionChar and friends)
550 QCString fileName; // file name
551 QCString outputFile; // output file name
552 QCString pchFile; // name of PCH file (used on Windows)
553 QStrList includeFiles; // name of #include files
554 QCString includePath; // #include file path
555 QCString qtPath; // #include qt file path
556 int gen_count; //number of classes generated
557 bool noInclude; // no #include <filename>
558 bool generatedCode; // no code generated
559 bool mocError; // moc parsing error occurred
560 bool hasVariantIncluded; //whether or not qvariant.h was included yet
561 QCString className; // name of parsed class
562 QCString superClassName; // name of first super class
563 QStrList multipleSuperClasses; // other superclasses
564 FuncList signals; // signal interface
565 FuncList slots; // slots interface
566 FuncList propfuncs; // all possible property access functions
567 FuncList funcs; // all parsed functions, including signals
568 EnumList enums; // enums used in properties
569 PropList props; // list of all properties
570 ClassInfoList infos; // list of all class infos
571
572// Used to store the values in the Q_PROPERTY macro
573 QCString propWrite; // set function
574 QCString propRead; // get function
575 QCString propReset; // reset function
576 QCString propStored; //
577 QCString propDesignable; // "true", "false" or function or empty if not specified
578 QCString propScriptable; // "true", "false" or function or empty if not specified
579 bool propOverride; // Wether OVERRIDE was detected
580
581 QStrList qtEnums; // Used to store the contents of Q_ENUMS
582 QStrList qtSets; // Used to store the contents of Q_SETS
583
584};
585
586static parser_reg *g = 0;
587
588ArgList *addArg( Argument * ); // add arg to tmpArgList
589
590enum Member { SignalMember,
591 SlotMember,
592 PropertyCandidateMember
593 };
594
595void addMember( Member ); // add tmpFunc to current class
596void addEnum(); // add tmpEnum to current class
597
598char *stradd( const char *, const char * ); // add two strings
599char *stradd( const char *, const char *, // add three strings
600 const char * );
601char *stradd( const char *, const char *, // adds 4 strings
602 const char *, const char * );
603
604char *straddSpc( const char *, const char * );
605char *straddSpc( const char *, const char *,
606 const char * );
607char *straddSpc( const char *, const char *,
608 const char *, const char * );
609
610extern int yydebug;
611bool lexDebug = FALSE;
612int lineNo; // current line number
613bool errorControl = FALSE; // controled errors
614bool displayWarnings = TRUE;
615bool skipClass; // don't generate for class
616bool skipFunc; // don't generate for func
617bool templateClass; // class is a template
618bool templateClassOld; // previous class is a template
619
620ArgList *tmpArgList; // current argument list
621Function *tmpFunc; // current member function
622Enum *tmpEnum; // current enum
623Access tmpAccess; // current access permission
624Access subClassPerm; // current access permission
625
626bool Q_OBJECTdetected; // TRUE if current class
627 // contains the Q_OBJECT macro
628bool Q_PROPERTYdetected; // TRUE if current class
629 // contains at least one Q_PROPERTY,
630 // Q_OVERRIDE, Q_SETS or Q_ENUMS macro
631bool tmpPropOverride; // current property override setting
632
633int tmpYYStart; // Used to store the lexers current mode
634int tmpYYStart2; // Used to store the lexers current mode
635 // (if tmpYYStart is already used)
636
637// if the format revision changes, you MUST change it in qmetaobject.h too
638const int formatRevision = 26; // moc output format revision
639
640// if the flags change, you HAVE to change it in qmetaobject.h too
641enum Flags {
642 Invalid = 0x00000000,
643 Readable = 0x00000001,
644 Writable = 0x00000002,
645 EnumOrSet = 0x00000004,
646 UnresolvedEnum = 0x00000008,
647 StdSet = 0x00000100,
648 Override = 0x00000200,
649 NotDesignable = 0x00001000,
650 DesignableOverride = 0x00002000,
651 NotScriptable = 0x00004000,
652 ScriptableOverride = 0x00008000,
653 NotStored = 0x00010000,
654 StoredOverride = 0x00020000
655};
656
657%}
658
659
660
661
662%union {
663 char char_val;
664 int int_val;
665 double double_val;
666 char *string;
667 Access access;
668 Function *function;
669 ArgList *arg_list;
670 Argument *arg;
671}
672
673%start declaration_seq
674
675%token <char_val> CHAR_VAL /* value types */
676%token <int_val> INT_VAL
677%token <double_val> DOUBLE_VAL
678%token <string> STRING
679%token <string> IDENTIFIER /* identifier string */
680
681%token FRIEND /* declaration keywords */
682%token TYPEDEF
683%token AUTO
684%token REGISTER
685%token STATIC
686%token EXTERN
687%token INLINE
688%token VIRTUAL
689%token CONST
690%token VOLATILE
691%token CHAR
692%token SHORT
693%token INT
694%token LONG
695%token SIGNED
696%token UNSIGNED
697%token FLOAT
698%token DOUBLE
699%token VOID
700%token ENUM
701%token CLASS
702%token STRUCT
703%token UNION
704%token ASM
705%token PRIVATE
706%token PROTECTED
707%token PUBLIC
708%token OPERATOR
709%token DBL_COLON
710%token TRIPLE_DOT
711%token TEMPLATE
712%token NAMESPACE
713%token USING
714%token MUTABLE
715%token THROW
716
717%token SIGNALS
718%token SLOTS
719%token Q_OBJECT
720%token Q_PROPERTY
721%token Q_OVERRIDE
722%token Q_CLASSINFO
723%token Q_ENUMS
724%token Q_SETS
725
726%token READ
727%token WRITE
728%token STORED
729%token DESIGNABLE
730%token SCRIPTABLE
731%token RESET
732
733%type <string> class_name
734%type <string> template_class_name
735%type <string> template_spec
736%type <string> opt_base_spec
737
738%type <string> base_spec
739%type <string> base_list
740%type <string> qt_macro_name
741%type <string> base_specifier
742%type <access> access_specifier
743%type <string> fct_name
744%type <string> type_name
745%type <string> simple_type_names
746%type <string> simple_type_name
747%type <string> class_key
748%type <string> complete_class_name
749%type <string> qualified_class_name
750%type <string> elaborated_type_specifier
751%type <string> whatever
752
753%type <arg_list> argument_declaration_list
754%type <arg_list> arg_declaration_list
755%type <arg_list> arg_declaration_list_opt
756%type <string> abstract_decl_opt
757%type <string> abstract_decl
758%type <arg> argument_declaration
759%type <arg> opt_exception_argument
760%type <string> cv_qualifier_list_opt
761%type <string> cv_qualifier_list
762%type <string> cv_qualifier
763%type <string> decl_specifiers
764%type <string> decl_specifier
765%type <string> decl_specs_opt
766%type <string> decl_specs
767%type <string> type_specifier
768%type <string> fct_specifier
769%type <string> declarator
770%type <string> ptr_operator
771%type <string> ptr_operators
772%type <string> ptr_operators_opt
773
774%type <string> dname
775
776%%
777declaration_seq: /* empty */
778 | declaration_seq declaration
779 ;
780
781declaration: class_def
782/* | template_declaration */
783 | namespace_def
784 | namespace_alias_def
785 | using_declaration
786 | using_directive
787 ;
788
789namespace_def: named_namespace_def
790 | unnamed_namespace_def
791 ;
792
793named_namespace_def: NAMESPACE
794 IDENTIFIER { enterNameSpace($2); }
795 '{' { BEGIN IN_NAMESPACE; }
796 namespace_body
797 '}' { leaveNameSpace();
798 selectOutsideClassState();
799 }
800 ;
801
802unnamed_namespace_def: NAMESPACE { enterNameSpace(); }
803 '{' { BEGIN IN_NAMESPACE; }
804 namespace_body
805 '}' { leaveNameSpace();
806 selectOutsideClassState();
807 }
808 ;
809
810namespace_body: declaration_seq
811 ;
812
813namespace_alias_def: NAMESPACE IDENTIFIER '=' complete_class_name ';'
814 { selectOutsideClassState(); }
815 ;
816
817
818using_directive: USING NAMESPACE { selectOutsideClassState(); } /* Skip namespace */
819 ;
820
821using_declaration: USING IDENTIFIER { selectOutsideClassState(); }
822 | USING DBL_COLON { selectOutsideClassState(); }
823 ;
824
825class_def: { initClass(); }
826 class_specifier ';' { generateClass();
827 registerClassInNamespace();
828 selectOutsideClassState(); }
829 ;
830
831
832/***** r.17.1 (ARM p.387 ): Keywords *****/
833
834class_name: IDENTIFIER { $$ = $1; }
835 | template_class_name { $$ = $1; }
836 ;
837
838template_class_name: IDENTIFIER '<' template_args '>'
839 { g->tmpExpression = rmWS( g->tmpExpression );
840 $$ = stradd( $1, "<",
841 g->tmpExpression, ">" ); }
842 ;
843
844/*
845 template_args skips all characters until it encounters a ">" (it
846 handles and discards sublevels of parentheses). Since the rule is
847 empty it must be used with care!
848*/
849
850template_args: /* empty */ { initExpression();
851 templLevel = 1;
852 BEGIN IN_TEMPL_ARGS; }
853 ;
854
855/***** r.17.2 (ARM p.388): Expressions *****/
856
857
858/* const_expression skips all characters until it encounters either one
859 of "]", ")" or "," (it handles and discards sublevels of parentheses).
860 Since the rule is empty it must be used with care!
861*/
862
863const_expression: /* empty */ { initExpression();
864 BEGIN IN_EXPR; }
865 ;
866
867/* def_argument is just like const expression but handles the ","
868 slightly differently. It was added for 3.0 as quick solution. TODO:
869 merge with const_expression.
870 */
871
872def_argument: /* empty */ { BEGIN IN_DEF_ARG; }
873 ;
874
875enumerator_expression: /* empty */ { initExpression();
876 BEGIN IN_ENUM; }
877 ;
878
879/***** r.17.3 (ARM p.391): Declarations *****/
880
881decl_specifier: storage_class_specifier { $$ = ""; }
882 | type_specifier { $$ = $1; }
883 | fct_specifier { $$ = ""; }
884 | FRIEND { skipFunc = TRUE; $$ = ""; }
885 | TYPEDEF { skipFunc = TRUE; $$ = ""; }
886 ;
887
888decl_specifiers: decl_specs_opt type_name decl_specs_opt
889 { $$ = straddSpc($1,$2,$3); }
890 ;
891decl_specs_opt: /* empty */ { $$ = ""; }
892 | decl_specs { $$ = $1; }
893 ;
894
895decl_specs: decl_specifier { $$ = $1; }
896 | decl_specs decl_specifier { $$ = straddSpc($1,$2); }
897 ;
898
899storage_class_specifier: AUTO
900 | REGISTER
901 | STATIC { skipFunc = TRUE; }
902 | EXTERN
903 ;
904
905fct_specifier: INLINE { }
906 | VIRTUAL { }
907 ;
908
909type_specifier: CONST { $$ = "const"; }
910 | VOLATILE { $$ = "volatile"; }
911 ;
912
913type_name: elaborated_type_specifier { $$ = $1; }
914 | complete_class_name { $$ = $1; }
915 | simple_type_names { $$ = $1; }
916 ;
917
918simple_type_names: simple_type_names simple_type_name
919 { $$ = straddSpc($1,$2); }
920 | simple_type_name { $$ = $1; }
921 ;
922
923simple_type_name: CHAR { $$ = "char"; }
924 | SHORT { $$ = "short"; }
925 | INT { $$ = "int"; }
926 | LONG { $$ = "long"; }
927 | SIGNED { $$ = "signed"; }
928 | UNSIGNED { $$ = "unsigned"; }
929 | FLOAT { $$ = "float"; }
930 | DOUBLE { $$ = "double"; }
931 | VOID { $$ = "void"; }
932 ;
933
934template_spec: TEMPLATE '<' template_args '>'
935 { g->tmpExpression = rmWS( g->tmpExpression );
936 $$ = stradd( "template<",
937 g->tmpExpression, ">" ); }
938 ;
939
940opt_template_spec: /* empty */
941 | template_spec { templateClassOld = templateClass;
942 templateClass = TRUE;
943 }
944 ;
945
946
947class_key: opt_template_spec CLASS { $$ = "class"; }
948 | opt_template_spec STRUCT { $$ = "struct"; }
949 ;
950
951complete_class_name: qualified_class_name { $$ = $1; }
952 | DBL_COLON qualified_class_name
953 { $$ = stradd( "::", $2 ); }
954 ;
955
956qualified_class_name: qualified_class_name DBL_COLON class_name
957 { $$ = stradd( $1, "::", $3 );}
958 | class_name { $$ = $1; }
959 ;
960
961elaborated_type_specifier:
962 class_key IDENTIFIER { $$ = straddSpc($1,$2); }
963 | ENUM IDENTIFIER { $$ = stradd("enum ",$2); }
964 | UNION IDENTIFIER { $$ = stradd("union ",$2); }
965 ;
966
967/***** r.17.4 (ARM p.393): Declarators *****/
968
969argument_declaration_list: arg_declaration_list_opt triple_dot_opt { $$ = $1;}
970 | arg_declaration_list ',' TRIPLE_DOT { $$ = $1;
971 func_warn("Ellipsis not supported"
972 " in signals and slots.\n"
973 "Ellipsis argument ignored."); }
974 ;
975
976arg_declaration_list_opt: /* empty */ { $$ = tmpArgList; }
977 | arg_declaration_list { $$ = $1; }
978 ;
979
980opt_exception_argument: /* empty */ { $$ = 0; }
981 | argument_declaration
982 ;
983
984triple_dot_opt: /* empty */
985 | TRIPLE_DOT { func_warn("Ellipsis not supported"
986 " in signals and slots.\n"
987 "Ellipsis argument ignored."); }
988
989 ;
990
991arg_declaration_list: arg_declaration_list
992 ','
993 argument_declaration { $$ = addArg($3); }
994 | argument_declaration { $$ = addArg($1); }
995 ;
996
997argument_declaration: decl_specifiers abstract_decl_opt
998 { $$ = new Argument(straddSpc($1,$2),""); }
999 | decl_specifiers abstract_decl_opt
1000 '=' { expLevel = 1; }
1001 def_argument
1002 { $$ = new Argument(straddSpc($1,$2),"", 0, TRUE ); }
1003 | decl_specifiers abstract_decl_opt dname
1004 abstract_decl_opt
1005 { $$ = new Argument(straddSpc($1,$2),$4, $3); }
1006 | decl_specifiers abstract_decl_opt dname
1007 abstract_decl_opt
1008 '=' { expLevel = 1; }
1009 def_argument
1010 { $$ = new Argument(straddSpc($1,$2),$4, $3, TRUE); }
1011 ;
1012
1013
1014abstract_decl_opt: /* empty */ { $$ = ""; }
1015 | abstract_decl { $$ = $1; }
1016 ;
1017
1018abstract_decl: abstract_decl ptr_operator
1019 { $$ = straddSpc($1,$2); }
1020 | '[' { expLevel = 1; }
1021 const_expression ']'
1022 { $$ = stradd( "[",
1023 g->tmpExpression =
1024 g->tmpExpression.stripWhiteSpace(), "]" ); }
1025 | abstract_decl '[' { expLevel = 1; }
1026 const_expression ']'
1027 { $$ = stradd( $1,"[",
1028 g->tmpExpression =
1029 g->tmpExpression.stripWhiteSpace(),"]" ); }
1030 | ptr_operator { $$ = $1; }
1031 | '(' abstract_decl ')' { $$ = $2; }
1032 ;
1033
1034declarator: dname { $$ = ""; }
1035 | declarator ptr_operator
1036 { $$ = straddSpc($1,$2);}
1037 | declarator '[' { expLevel = 1; }
1038 const_expression ']'
1039 { $$ = stradd( $1,"[",
1040 g->tmpExpression =
1041 g->tmpExpression.stripWhiteSpace(),"]" ); }
1042 | '(' declarator ')' { $$ = $2; }
1043 ;
1044
1045dname: IDENTIFIER
1046 ;
1047
1048fct_decl: '('
1049 argument_declaration_list
1050 ')'
1051 cv_qualifier_list_opt
1052 ctor_initializer_opt
1053 exception_spec_opt
1054 opt_identifier
1055 fct_body_or_semicolon
1056 { tmpFunc->args = $2;
1057 tmpFunc->qualifier = $4; }
1058 ;
1059
1060fct_name: IDENTIFIER /* NOTE: simplified! */
1061 | IDENTIFIER array_decls
1062 { func_warn("Variable as signal or slot."); }
1063 | IDENTIFIER '=' { expLevel=0; }
1064 const_expression /* probably const member */
1065 { skipFunc = TRUE; }
1066 | IDENTIFIER array_decls '=' { expLevel=0; }
1067 const_expression /* probably const member */
1068 { skipFunc = TRUE; }
1069 ;
1070
1071
1072array_decls: '[' { expLevel = 1; }
1073 const_expression ']'
1074 | array_decls '[' { expLevel = 1; }
1075 const_expression ']'
1076
1077 ;
1078
1079ptr_operators_opt: /* empty */ { $$ = ""; }
1080 | ptr_operators { $$ = $1; }
1081 ;
1082
1083ptr_operators: ptr_operator { $$ = $1; }
1084 | ptr_operators ptr_operator { $$ = straddSpc($1,$2);}
1085 ;
1086
1087ptr_operator: '*' cv_qualifier_list_opt { $$ = straddSpc("*",$2);}
1088 | '&' cv_qualifier_list_opt { $$ = stradd("&",$2);}
1089/*! | complete_class_name
1090 DBL_COLON
1091 '*'
1092 cv_qualifier_list_opt { $$ = stradd($1,"::*",$4); }*/
1093 ;
1094
1095cv_qualifier_list_opt: /* empty */ { $$ = ""; }
1096 | cv_qualifier_list { $$ = $1; }
1097 ;
1098
1099cv_qualifier_list: cv_qualifier { $$ = $1; }
1100 | cv_qualifier_list cv_qualifier
1101 { $$ = straddSpc($1,$2); }
1102 ;
1103
1104cv_qualifier: CONST { $$ = "const"; }
1105 | VOLATILE { $$ = "volatile"; }
1106 ;
1107
1108fct_body_or_semicolon: ';'
1109 | fct_body
1110 | '=' INT_VAL ';' /* abstract func, INT_VAL = 0 */
1111 ;
1112
1113fct_body: '{' { BEGIN IN_FCT; fctLevel = 1;}
1114 '}' { BEGIN QT_DEF; }
1115 ;
1116
1117
1118/***** r.17.5 (ARM p.395): Class Declarations *****/
1119
1120class_specifier: full_class_head
1121 '{' { BEGIN IN_CLASS;
1122 classPLevel = 1;
1123 }
1124 opt_obj_member_list
1125 '}' { BEGIN QT_DEF; } /*catch ';'*/
1126 | class_head { BEGIN QT_DEF; /* -- " -- */
1127 skipClass = TRUE; }
1128 | class_head '*' IDENTIFIER { BEGIN QT_DEF; /* -- " -- */
1129 skipClass = TRUE; }
1130 | class_head '&' IDENTIFIER { BEGIN QT_DEF; /* -- " -- */
1131 skipClass = TRUE; }
1132 | class_head
1133 '(' IDENTIFIER ')' /* Qt macro name */
1134 { BEGIN QT_DEF; /* catch ';' */
1135 skipClass = TRUE; }
1136 | template_spec whatever { skipClass = TRUE;
1137 BEGIN GIMME_SEMICOLON; }
1138 ;
1139
1140whatever: IDENTIFIER
1141 | simple_type_name
1142 | type_specifier
1143 | storage_class_specifier { $$ = ""; }
1144 | fct_specifier
1145 ;
1146
1147
1148class_head: class_key
1149 qualified_class_name { g->className = $2;
1150 if ( g->className == "QObject" )
1151 Q_OBJECTdetected = TRUE;
1152 }
1153 | class_key
1154 IDENTIFIER /* possible DLL EXPORT macro */
1155 class_name { g->className = $3;
1156 if ( g->className == "QObject" )
1157 Q_OBJECTdetected = TRUE;
1158 }
1159 ;
1160
1161full_class_head: class_head
1162 opt_base_spec { g->superClassName = $2; }
1163 ;
1164
1165nested_class_head: class_key
1166 qualified_class_name
1167 opt_base_spec { templateClass = templateClassOld; }
1168 ;
1169
1170exception_spec_opt: /* empty */
1171 | exception_spec
1172 ;
1173
1174/* looser than the real thing */
1175exception_spec: THROW '(' opt_exception_argument ')'
1176 ;
1177
1178ctor_initializer_opt: /* empty */
1179 | ctor_initializer
1180 ;
1181
1182ctor_initializer: ':' mem_initializer_list
1183 ;
1184
1185mem_initializer_list: mem_initializer
1186 | mem_initializer ',' mem_initializer_list
1187 ;
1188
1189/* complete_class_name also represents IDENTIFIER */
1190mem_initializer: complete_class_name '(' { expLevel = 1; }
1191 const_expression ')'
1192 ;
1193
1194
1195opt_base_spec: /* empty */ { $$ = 0; }
1196 | base_spec { $$ = $1; }
1197 ;
1198
1199opt_obj_member_list: /* empty */
1200 | obj_member_list
1201 ;
1202
1203obj_member_list: obj_member_list obj_member_area
1204 | obj_member_area
1205 ;
1206
1207
1208qt_access_specifier: access_specifier { tmpAccess = $1; }
1209 | SLOTS { moc_err( "Missing access specifier"
1210 " before \"slots:\"." ); }
1211 ;
1212
1213obj_member_area: qt_access_specifier { BEGIN QT_DEF; }
1214 slot_area
1215 | SIGNALS { BEGIN QT_DEF; }
1216 ':' opt_signal_declarations
1217 | Q_OBJECT {
1218 if ( tmpAccess )
1219 moc_warn("Q_OBJECT is not in the private"
1220 " section of the class.\n"
1221 "Q_OBJECT is a macro that resets"
1222 " access permission to \"private\".");
1223 Q_OBJECTdetected = TRUE;
1224 }
1225 | Q_PROPERTY { tmpYYStart = YY_START;
1226 tmpPropOverride = FALSE;
1227 BEGIN IN_PROPERTY; }
1228 '(' property ')' {
1229 BEGIN tmpYYStart;
1230 }
1231 opt_property_candidates
1232 | Q_OVERRIDE { tmpYYStart = YY_START;
1233 tmpPropOverride = TRUE;
1234 BEGIN IN_PROPERTY; }
1235 '(' property ')' {
1236 BEGIN tmpYYStart;
1237 }
1238 opt_property_candidates
1239 | Q_CLASSINFO { tmpYYStart = YY_START; BEGIN IN_CLASSINFO; }
1240 '(' STRING ',' STRING ')'
1241 {
1242 g->infos.append( new ClassInfo( $4, $6 ) );
1243 BEGIN tmpYYStart;
1244 }
1245 opt_property_candidates
1246 | Q_ENUMS { tmpYYStart = YY_START; BEGIN IN_PROPERTY; }
1247 '(' qt_enums ')' {
1248 Q_PROPERTYdetected = TRUE;
1249 BEGIN tmpYYStart;
1250 }
1251 opt_property_candidates
1252 | Q_SETS { tmpYYStart = YY_START; BEGIN IN_PROPERTY; }
1253 '(' qt_sets ')' {
1254 Q_PROPERTYdetected = TRUE;
1255 BEGIN tmpYYStart;
1256 }
1257 opt_property_candidates
1258 ;
1259
1260slot_area: SIGNALS ':' { moc_err( "Signals cannot "
1261 "have access specifiers" ); }
1262 | SLOTS ':' opt_slot_declarations
1263 | ':' { if ( tmpAccess == Public && Q_PROPERTYdetected )
1264 BEGIN QT_DEF;
1265 else
1266 BEGIN IN_CLASS;
1267 suppress_func_warn = TRUE;
1268 }
1269 opt_property_candidates
1270 {
1271 suppress_func_warn = FALSE;
1272 }
1273 | IDENTIFIER { BEGIN IN_CLASS;
1274 if ( classPLevel != 1 )
1275 moc_warn( "unexpected access"
1276 "specifier" );
1277 }
1278 ;
1279
1280opt_property_candidates: /*empty*/
1281 | property_candidate_declarations
1282 ;
1283
1284property_candidate_declarations: property_candidate_declarations property_candidate_declaration
1285 | property_candidate_declaration
1286 ;
1287
1288property_candidate_declaration: signal_or_slot { addMember( PropertyCandidateMember ); }
1289 ;
1290
1291opt_signal_declarations: /* empty */
1292 | signal_declarations
1293 ;
1294
1295signal_declarations: signal_declarations signal_declaration
1296 | signal_declaration
1297 ;
1298
1299
1300signal_declaration: signal_or_slot { addMember( SignalMember ); }
1301 ;
1302
1303opt_slot_declarations: /* empty */
1304 | slot_declarations
1305 ;
1306
1307slot_declarations: slot_declarations slot_declaration
1308 | slot_declaration
1309 ;
1310
1311slot_declaration: signal_or_slot { addMember( SlotMember ); }
1312 ;
1313
1314opt_semicolons: /* empty */
1315 | opt_semicolons ';'
1316 ;
1317
1318base_spec: ':' base_list { $$=$2; }
1319 ;
1320
1321base_list : base_list ',' base_specifier { g->multipleSuperClasses.append( $3 ); }
1322 | base_specifier
1323 ;
1324
1325qt_macro_name: IDENTIFIER '(' IDENTIFIER ')'
1326 { $$ = stradd( $1, "(", $3, ")" ); }
1327 | IDENTIFIER '(' simple_type_name ')'
1328 { $$ = stradd( $1, "(", $3, ")" ); }
1329 ;
1330
1331base_specifier: complete_class_name {$$=$1;}
1332 | VIRTUAL access_specifier complete_class_name {$$=$3;}
1333 | VIRTUAL complete_class_name {$$=$2;}
1334 | access_specifier VIRTUAL complete_class_name {$$=$3;}
1335 | access_specifier complete_class_name {$$=$2;}
1336 | qt_macro_name {$$=$1;}
1337 | VIRTUAL access_specifier qt_macro_name {$$=$3;}
1338 | VIRTUAL qt_macro_name {$$=$2;}
1339 | access_specifier VIRTUAL qt_macro_name {$$=$3;}
1340 | access_specifier qt_macro_name {$$=$2;}
1341 ;
1342
1343access_specifier: PRIVATE { $$=Private; }
1344 | PROTECTED { $$=Protected; }
1345 | PUBLIC { $$=Public; }
1346 ;
1347
1348operator_name: decl_specs_opt IDENTIFIER ptr_operators_opt { }
1349 | decl_specs_opt simple_type_name ptr_operators_opt { }
1350 | '+'
1351 | '-'
1352 | '*'
1353 | '/'
1354 | '%'
1355 | '^'
1356 | '&'
1357 | '|'
1358 | '~'
1359 | '!'
1360 | '='
1361 | '<'
1362 | '>'
1363 | '+' '='
1364 | '-' '='
1365 | '*' '='
1366 | '/' '='
1367 | '%' '='
1368 | '^' '='
1369 | '&' '='
1370 | '|' '='
1371 | '~' '='
1372 | '!' '='
1373 | '=' '='
1374 | '<' '='
1375 | '>' '='
1376 | '<' '<'
1377 | '>' '>'
1378 | '<' '<' '='
1379 | '>' '>' '='
1380 | '&' '&'
1381 | '|' '|'
1382 | '+' '+'
1383 | '-' '-'
1384 | ','
1385 | '-' '>' '*'
1386 | '-' '>'
1387 | '(' ')'
1388 | '[' ']'
1389 ;
1390
1391
1392opt_virtual: /* empty */
1393 | VIRTUAL
1394 ;
1395
1396type_and_name: type_name fct_name
1397 { tmpFunc->type = $1;
1398 tmpFunc->name = $2; }
1399 | fct_name
1400 { tmpFunc->type = "int";
1401 tmpFunc->name = $1;
1402 if ( tmpFunc->name == g->className )
1403 func_warn( "Constructors cannot be"
1404 " signals or slots.");
1405 }
1406 | opt_virtual '~' fct_name
1407 { tmpFunc->type = "void";
1408 tmpFunc->name = "~";
1409 tmpFunc->name += $3;
1410 func_warn( "Destructors cannot be"
1411 " signals or slots.");
1412 }
1413 | decl_specs type_name decl_specs_opt
1414 ptr_operators_opt fct_name
1415 {
1416 char *tmp =
1417 straddSpc($1,$2,$3,$4);
1418 tmpFunc->type = rmWS(tmp);
1419 delete [] tmp;
1420 tmpFunc->name = $5; }
1421 | decl_specs type_name /* probably friend decl */
1422 { skipFunc = TRUE; }
1423 | type_name ptr_operators fct_name
1424 { tmpFunc->type =
1425 straddSpc($1,$2);
1426 tmpFunc->name = $3; }
1427 | type_name decl_specs ptr_operators_opt
1428 fct_name
1429 { tmpFunc->type =
1430 straddSpc($1,$2,$3);
1431 tmpFunc->name = $4; }
1432 | type_name OPERATOR operator_name
1433 { operatorError(); }
1434 | OPERATOR operator_name
1435 { operatorError(); }
1436 | decl_specs type_name decl_specs_opt
1437 ptr_operators_opt OPERATOR operator_name
1438 { operatorError(); }
1439 | type_name ptr_operators OPERATOR operator_name
1440 { operatorError(); }
1441 | type_name decl_specs ptr_operators_opt
1442 OPERATOR operator_name
1443 { operatorError(); }
1444 ;
1445
1446
1447signal_or_slot: type_and_name fct_decl opt_semicolons
1448 | type_and_name opt_bitfield ';' opt_semicolons
1449 { func_warn("Unexpected variable declaration."); }
1450 | type_and_name opt_bitfield ','member_declarator_list
1451 ';' opt_semicolons
1452 { func_warn("Unexpected variable declaration."); }
1453 | enum_specifier opt_identifier ';' opt_semicolons
1454 { func_warn("Unexpected enum declaration."); }
1455 | USING complete_class_name ';' opt_semicolons
1456 { func_warn("Unexpected using declaration."); }
1457 | USING NAMESPACE complete_class_name ';' opt_semicolons
1458 { func_warn("Unexpected using declaration."); }
1459 | NAMESPACE IDENTIFIER '{'
1460 { classPLevel++;
1461 moc_err("Unexpected namespace declaration."); }
1462 | nested_class_head ';' opt_semicolons
1463 { func_warn("Unexpected class declaration.");}
1464 | nested_class_head
1465 '{' { func_warn("Unexpected class declaration.");
1466 BEGIN IN_FCT; fctLevel=1;
1467 }
1468 '}' { BEGIN QT_DEF; }
1469 ';' opt_semicolons
1470 ;
1471
1472
1473member_declarator_list: member_declarator
1474 | member_declarator_list ',' member_declarator
1475 ;
1476
1477member_declarator: declarator { }
1478 | IDENTIFIER ':' { expLevel = 0; }
1479 const_expression
1480 | ':' { expLevel = 0; }
1481 const_expression
1482 ;
1483
1484opt_bitfield: /* empty */
1485 | ':' { expLevel = 0; }
1486 const_expression
1487 ;
1488
1489
1490enum_specifier: ENUM enum_tail
1491 ;
1492
1493/* optional final comma at the end of an enum list. Not really C++ but
1494some people still use it */
1495opt_komma: /*empty*/
1496 | ','
1497 ;
1498
1499enum_tail: IDENTIFIER '{' enum_list opt_komma
1500 '}' { BEGIN QT_DEF;
1501 if ( tmpAccess == Public) {
1502 tmpEnum->name = $1;
1503 addEnum();
1504 }
1505 }
1506 | '{' enum_list opt_komma
1507 '}' { tmpEnum->clear();}
1508 ;
1509
1510opt_identifier: /* empty */
1511 | IDENTIFIER { }
1512 ;
1513
1514enum_list: /* empty */
1515 | enumerator
1516 | enum_list ',' enumerator
1517 ;
1518
1519enumerator: IDENTIFIER { if ( tmpAccess == Public) tmpEnum->append( $1 ); }
1520 | IDENTIFIER '=' { enumLevel=0; }
1521 enumerator_expression { if ( tmpAccess == Public) tmpEnum->append( $1 ); }
1522 ;
1523
1524property: IDENTIFIER IDENTIFIER
1525 {
1526 g->propWrite = "";
1527 g->propRead = "";
1528 g->propOverride = tmpPropOverride;
1529 g->propReset = "";
1530 if ( g->propOverride ) {
1531 g->propStored = "";
1532 g->propDesignable = "";
1533 g->propScriptable = "";
1534 } else {
1535 g->propStored = "true";
1536 g->propDesignable = "true";
1537 g->propScriptable = "true";
1538 }
1539 }
1540 prop_statements
1541 {
1542 if ( g->propRead.isEmpty() && !g->propOverride )
1543 moc_err( "A property must at least feature a read method." );
1544 checkPropertyName( $2 );
1545 Q_PROPERTYdetected = TRUE;
1546 // Avoid duplicates
1547 for( QPtrListIterator<Property> lit( g->props ); lit.current(); ++lit ) {
1548 if ( lit.current()->name == $2 ) {
1549 if ( displayWarnings )
1550 moc_err( "Property '%s' defined twice.",
1551 (const char*)lit.current()->name );
1552 }
1553 }
1554 g->props.append( new Property( lineNo, $1, $2,
1555 g->propWrite, g->propRead, g->propReset,
1556 g->propStored, g->propDesignable,
1557 g->propScriptable, g->propOverride ) );
1558 }
1559 ;
1560
1561prop_statements: /* empty */
1562 | READ IDENTIFIER prop_statements { g->propRead = $2; }
1563 | WRITE IDENTIFIER prop_statements { g->propWrite = $2; }
1564 | RESET IDENTIFIER prop_statements { g->propReset = $2; }
1565 | STORED IDENTIFIER prop_statements { g->propStored = $2; }
1566 | DESIGNABLE IDENTIFIER prop_statements { g->propDesignable = $2; }
1567 | SCRIPTABLE IDENTIFIER prop_statements { g->propScriptable = $2; }
1568 ;
1569
1570qt_enums: /* empty */ { }
1571 | IDENTIFIER qt_enums { g->qtEnums.append( $1 ); }
1572 ;
1573
1574qt_sets: /* empty */ { }
1575 | IDENTIFIER qt_sets { g->qtSets.append( $1 ); }
1576 ;
1577
1578%%
1579
1580#if defined(Q_OS_WIN32)
1581#include <io.h>
1582#undef isatty
1583extern "C" int hack_isatty( int )
1584{
1585 return 0;
1586}
1587#define isatty hack_isatty
1588#else
1589#include <unistd.h>
1590#endif
1591
1592#include "moc_lex.cpp"
1593
1594void cleanup();
1595QCString combinePath( const char *, const char * );
1596
1597FILE *out; // output file
1598
1599parser_reg::parser_reg() : funcs(TRUE)
1600{
1601 gen_count = 0;
1602 noInclude = FALSE; // no #include <filename>
1603 generatedCode = FALSE; // no code generated
1604 mocError = FALSE; // moc parsing error occurred
1605 hasVariantIncluded = FALSE;
1606}
1607
1608
1609parser_reg::~parser_reg()
1610{
1611 slots.clear();
1612 signals.clear();
1613 propfuncs.clear();
1614 funcs.clear();
1615 infos.clear();
1616 props.clear();
1617 infos.clear();
1618}
1619
1620int yyparse();
1621
1622void replace( char *s, char c1, char c2 );
1623
1624void setDefaultIncludeFile()
1625{
1626 if ( g->includeFiles.isEmpty() ) {
1627 if ( g->includePath.isEmpty() ) {
1628 if ( !g->fileName.isEmpty() && !g->outputFile.isEmpty() ) {
1629 g->includeFiles.append( combinePath(g->fileName, g->outputFile) );
1630 } else {
1631 g->includeFiles.append( g->fileName );
1632 }
1633 } else {
1634 g->includeFiles.append( combinePath(g->fileName, g->fileName) );
1635 }
1636 }
1637}
1638
1639#ifdef Q_CC_MSVC
1640#define ErrorFormatString "%s(%d):"
1641#else
1642#define ErrorFormatString "%s:%d:"
1643#endif
1644
1645#ifndef MOC_MWERKS_PLUGIN
1646int main( int argc, char **argv )
1647{
1648 init();
1649
1650 bool autoInclude = TRUE;
1651 const char *error = 0;
1652 g->qtPath = "";
1653 for ( int n=1; n<argc && error==0; n++ ) {
1654 QCString arg = argv[n];
1655 if ( arg[0] == '-' ) { // option
1656 QCString opt = &arg[1];
1657 if ( opt[0] == 'o' ) { // output redirection
1658 if ( opt[1] == '\0' ) {
1659 if ( !(n < argc-1) ) {
1660 error = "Missing output file name";
1661 break;
1662 }
1663 g->outputFile = argv[++n];
1664 } else
1665 g->outputFile = &opt[1];
1666 } else if ( opt == "i" ) { // no #include statement
1667 g->noInclude = TRUE;
1668 autoInclude = FALSE;
1669 } else if ( opt[0] == 'f' ) { // produce #include statement
1670 g->noInclude = FALSE;
1671 autoInclude = FALSE;
1672 if ( opt[1] ) // -fsomething.h
1673 g->includeFiles.append( &opt[1] );
1674 } else if ( opt == "pch" ) { // produce #include statement for PCH
1675 if ( !(n < argc-1) ) {
1676 error = "Missing name of PCH file";
1677 break;
1678 }
1679 g->pchFile = argv[++n];
1680 } else if ( opt[0] == 'p' ) { // include file path
1681 if ( opt[1] == '\0' ) {
1682 if ( !(n < argc-1) ) {
1683 error = "Missing path name for the -p option.";
1684 break;
1685 }
1686 g->includePath = argv[++n];
1687 } else {
1688 g->includePath = &opt[1];
1689 }
1690 } else if ( opt[0] == 'q' ) { // qt include file path
1691 if ( opt[1] == '\0' ) {
1692 if ( !(n < argc-1) ) {
1693 error = "Missing path name for the -q option.";
1694 break;
1695 }
1696 g->qtPath = argv[++n];
1697 } else {
1698 g->qtPath = &opt[1];
1699 }
1700 replace(g->qtPath.data(),'\\','/');
1701 if ( g->qtPath.right(1) != "/" )
1702 g->qtPath += '/';
1703 } else if ( opt == "v" ) { // version number
1704 fprintf( stderr, "Qt Meta Object Compiler version %d"
1705 " (Qt %s)\n", formatRevision,
1706 QT_VERSION_STR );
1707 cleanup();
1708 return 1;
1709 } else if ( opt == "k" ) { // stop on errors
1710 errorControl = TRUE;
1711 } else if ( opt == "nw" ) { // don't display warnings
1712 displayWarnings = FALSE;
1713 } else if ( opt == "ldbg" ) { // lex debug output
1714 lexDebug = TRUE;
1715 } else if ( opt == "ydbg" ) { // yacc debug output
1716 yydebug = TRUE;
1717 } else {
1718 error = "Invalid argument";
1719 }
1720 } else {
1721 if ( !g->fileName.isNull() ) // can handle only one file
1722 error = "Too many input files specified";
1723 else
1724 g->fileName = arg.copy();
1725 }
1726 }
1727
1728 if ( autoInclude ) {
1729 int ppos = g->fileName.findRev('.');
1730 if ( ppos != -1 && tolower( g->fileName[ppos + 1] ) == 'h' )
1731 g->noInclude = FALSE;
1732 else
1733 g->noInclude = TRUE;
1734 }
1735 setDefaultIncludeFile();
1736
1737 if ( g->fileName.isNull() && !error ) {
1738 g->fileName = "standard input";
1739 yyin = stdin;
1740 } else if ( argc < 2 || error ) { // incomplete/wrong args
1741 fprintf( stderr, "Qt meta object compiler\n" );
1742 if ( error )
1743 fprintf( stderr, "moc: %s\n", error );
1744 fprintf( stderr, "Usage: moc [options] <header-file>\n"
1745 "\t-o file Write output to file rather than stdout\n"
1746 "\t-f[file] Force #include, optional file name\n"
1747 "\t-p path Path prefix for included file\n"
1748 "\t-i Do not generate an #include statement\n"
1749 "\t-k Do not stop on errors\n"
1750 "\t-nw Do not display warnings\n"
1751 "\t-v Display version of moc\n" );
1752 cleanup();
1753 return 1;
1754 } else {
1755 yyin = fopen( (const char *)g->fileName, "r" );
1756 if ( !yyin ) {
1757 fprintf( stderr, "moc: %s: No such file\n", (const char*)g->fileName);
1758 cleanup();
1759 return 1;
1760 }
1761 }
1762 if ( !g->outputFile.isEmpty() ) { // output file specified
1763 out = fopen( (const char *)g->outputFile, "w" ); // create output file
1764 if ( !out ) {
1765 fprintf( stderr, "moc: Cannot create %s\n",
1766 (const char*)g->outputFile );
1767 cleanup();
1768 return 1;
1769 }
1770 } else { // use stdout
1771 out = stdout;
1772 }
1773 yyparse();
1774 fclose( yyin );
1775 if ( !g->outputFile.isNull() )
1776 fclose( out );
1777
1778 if ( !g->generatedCode && displayWarnings && !g->mocError ) {
1779 fprintf( stderr, ErrorFormatString" Warning: %s\n", g->fileName.data(), 0,
1780 "No relevant classes found. No output generated." );
1781 }
1782
1783 int ret = g->mocError ? 1 : 0;
1784 cleanup();
1785 return ret;
1786}
1787#else
1788bool qt_is_gui_used = FALSE;
1789#include <ctype.h>
1790#include <stdio.h>
1791#include <string.h>
1792#ifdef Q_OS_MAC9
1793# include <Files.h>
1794# include <Strings.h>
1795# include <Errors.h>
1796# include "Aliases.h"
1797#endif
1798#include "CWPluginErrors.h"
1799#include <CWPlugins.h>
1800#include "DropInCompilerLinker.h"
1801#include <stat.h>
1802
1803const unsigned char *p_str(const char *, int =-1);
1804
1805CWPluginContext g_ctx;
1806
1807moc_status do_moc( CWPluginContext ctx, const QCString &fin, const QCString &fout, CWFileSpec *dspec, bool i)
1808{
1809 init();
1810
1811 g_ctx = ctx;
1812 g->noInclude = i;
1813 g->fileName = fin;
1814 g->outputFile = fout;
1815
1816 setDefaultIncludeFile();
1817
1818 CWFileInfo fi;
1819 memset(&fi, 0, sizeof(fi));
1820 fi.fullsearch = TRUE;
1821 fi.dependencyType = cwNormalDependency;
1822 fi.isdependentoffile = kCurrentCompiledFile;
1823 if(CWFindAndLoadFile( ctx, fin.data(), &fi) != cwNoErr) {
1824 cleanup();
1825 return moc_no_source;
1826 }
1827
1828 if(dspec) {
1829 memcpy(dspec, &fi.filespec, sizeof(fi.filespec));
1830 const unsigned char *f = p_str(fout.data());
1831 memcpy(dspec->name, f, f[0]+1);
1832 free(f);
1833 }
1834 buf_size_total = fi.filedatalength;
1835 buf_buffer = fi.filedata;
1836
1837 QCString path("");
1838 AliasHandle alias;
1839 Str63 str;
1840 AliasInfoType x = 1;
1841 char tmp[sizeof(Str63)+2];
1842 if(NewAlias( NULL, &fi.filespec, &alias) != noErr) {
1843 cleanup();
1844 return moc_general_error;
1845 }
1846 for(;;) {
1847 GetAliasInfo(alias, x++, str);
1848 if(!str[0])
1849 break;
1850 strncpy((char *)tmp, (const char *)str+1, str[0]);
1851 tmp[str[0]] = '\0';
1852 path.prepend(":");
1853 path.prepend((char *)tmp);
1854 }
1855 path.prepend("MacOS 9:"); //FIXME
1856
1857 QString inpath = path + fin, outpath = path + fout;
1858 struct stat istat, ostat;
1859 if(stat(inpath, &istat) == -1) {
1860 cleanup();
1861 return moc_no_source;
1862 }
1863 if(stat(outpath, &ostat) == 0 && istat.st_mtime < ostat.st_mtime) {
1864 cleanup();
1865 return moc_not_time;
1866 }
1867
1868 unlink(outpath.data());
1869 out = fopen(outpath.data(), "w+");
1870 if(!out) {
1871 cleanup();
1872 return moc_general_error;
1873 }
1874
1875 yyparse();
1876 if(out != stdout)
1877 fclose(out);
1878
1879 if(g->mocError || !g->generatedCode) {
1880 unlink(outpath.data());
1881 moc_status ret = !g->generatedCode ? moc_no_qobject : moc_parse_error;
1882 cleanup();
1883 return ret;
1884 }
1885
1886 cleanup();
1887 return moc_success;
1888}
1889#endif
1890void replace( char *s, char c1, char c2 )
1891{
1892 if ( !s )
1893 return;
1894 while ( *s ) {
1895 if ( *s == c1 )
1896 *s = c2;
1897 s++;
1898 }
1899}
1900
1901/*
1902 This function looks at two file names and returns the name of the
1903 infile with a path relative to outfile.
1904
1905 Examples:
1906
1907 /tmp/abc, /tmp/bcd -> abc
1908 xyz/a/bc, xyz/b/ac -> ../a/bc
1909 /tmp/abc, xyz/klm -> /tmp/abc
1910 */
1911
1912QCString combinePath( const char *infile, const char *outfile )
1913{
1914 QFileInfo inFileInfo( QDir::current(), QFile::decodeName(infile) );
1915 QFileInfo outFileInfo( QDir::current(), QFile::decodeName(outfile) );
1916 int numCommonComponents = 0;
1917
1918 QStringList inSplitted =
1919 QStringList::split( '/', inFileInfo.dir().canonicalPath(), TRUE );
1920 QStringList outSplitted =
1921 QStringList::split( '/', outFileInfo.dir().canonicalPath(), TRUE );
1922
1923 while ( !inSplitted.isEmpty() && !outSplitted.isEmpty() &&
1924 inSplitted.first() == outSplitted.first() ) {
1925 inSplitted.remove( inSplitted.begin() );
1926 outSplitted.remove( outSplitted.begin() );
1927 numCommonComponents++;
1928 }
1929
1930 if ( numCommonComponents < 2 ) {
1931 /*
1932 The paths don't have the same drive, or they don't have the
1933 same root directory. Use an absolute path.
1934 */
1935 return QFile::encodeName( inFileInfo.absFilePath() );
1936 } else {
1937 /*
1938 The paths have something in common. Use a path relative to
1939 the output file.
1940 */
1941 while ( !outSplitted.isEmpty() ) {
1942 outSplitted.remove( outSplitted.begin() );
1943 inSplitted.prepend( ".." );
1944 }
1945 inSplitted.append( inFileInfo.fileName() );
1946 return QFile::encodeName( inSplitted.join("/") );
1947 }
1948}
1949
1950
1951#define getenv hack_getenv // workaround for byacc
1952char *getenv() { return 0; }
1953char *getenv( const char * ) { return 0; }
1954
1955void init() // initialize
1956{
1957 BEGIN OUTSIDE;
1958 if(g)
1959 delete g;
1960 g = new parser_reg;
1961 lineNo = 1;
1962 skipClass = FALSE;
1963 skipFunc = FALSE;
1964 tmpArgList = new ArgList;
1965 tmpFunc = new Function;
1966 tmpEnum = new Enum;
1967
1968#ifdef MOC_MWERKS_PLUGIN
1969 buf_buffer = NULL;
1970 buf_index = 0;
1971 buf_size_total = 0;
1972#endif
1973}
1974
1975void cleanup()
1976{
1977 delete g;
1978 g = NULL;
1979
1980#ifdef MOC_MWERKS_PLUGIN
1981 if(buf_buffer && g_ctx)
1982 CWReleaseFileText(g_ctx, buf_buffer);
1983#endif
1984}
1985
1986void initClass() // prepare for new class
1987{
1988 tmpAccess = Private;
1989 subClassPerm = Private;
1990 Q_OBJECTdetected = FALSE;
1991 Q_PROPERTYdetected = FALSE;
1992 skipClass = FALSE;
1993 templateClass = FALSE;
1994 g->slots.clear();
1995 g->signals.clear();
1996 g->propfuncs.clear();
1997 g->enums.clear();
1998 g->funcs.clear();
1999 g->props.clear();
2000 g->infos.clear();
2001 g->qtSets.clear();
2002 g->qtEnums.clear();
2003 g->multipleSuperClasses.clear();
2004}
2005
2006struct NamespaceInfo
2007{
2008 QCString name;
2009 int pLevelOnEntering; // Parenthesis level on entering the namespace
2010 QDict<char> definedClasses; // Classes defined in the namespace
2011};
2012
2013QPtrList<NamespaceInfo> namespaces;
2014
2015void enterNameSpace( const char *name ) // prepare for new class
2016{
2017 static bool first = TRUE;
2018 if ( first ) {
2019 namespaces.setAutoDelete( TRUE );
2020 first = FALSE;
2021 }
2022
2023 NamespaceInfo *tmp = new NamespaceInfo;
2024 if ( name )
2025 tmp->name = name;
2026 tmp->pLevelOnEntering = namespacePLevel;
2027 namespaces.append( tmp );
2028}
2029
2030void leaveNameSpace() // prepare for new class
2031{
2032 NamespaceInfo *tmp = namespaces.last();
2033 namespacePLevel = tmp->pLevelOnEntering;
2034 namespaces.remove();
2035}
2036
2037QCString nameQualifier()
2038{
2039 QPtrListIterator<NamespaceInfo> iter( namespaces );
2040 NamespaceInfo *tmp;
2041 QCString qualifier = "";
2042 for( ; (tmp = iter.current()) ; ++iter ) {
2043 if ( !tmp->name.isNull() ) { // If not unnamed namespace
2044 qualifier += tmp->name;
2045 qualifier += "::";
2046 }
2047 }
2048 return qualifier;
2049}
2050
2051int openNameSpaceForMetaObject( FILE *out )
2052{
2053 int levels = 0;
2054 QPtrListIterator<NamespaceInfo> iter( namespaces );
2055 NamespaceInfo *tmp;
2056 QCString indent = "";
2057 for( ; (tmp = iter.current()) ; ++iter ) {
2058 if ( !tmp->name.isNull() ) { // If not unnamed namespace
2059 fprintf( out, "%snamespace %s {\n", (const char *)indent,
2060 (const char *) tmp->name );
2061 indent += " ";
2062 levels++;
2063 }
2064 }
2065 QCString nm = g->className;
2066 int pos;
2067 while( (pos = nm.find( "::" )) != -1 ) {
2068 QCString spaceName = nm.left( pos );
2069 nm = nm.right( nm.length() - pos - 2 );
2070 if ( !spaceName.isEmpty() ) {
2071 fprintf( out, "%snamespace %s {\n", (const char *)indent,
2072 (const char *) spaceName );
2073 indent += " ";
2074 levels++;
2075 }
2076 }
2077 return levels;
2078}
2079
2080void closeNameSpaceForMetaObject( FILE *out, int levels )
2081{
2082 int i;
2083 for( i = 0 ; i < levels ; i++ )
2084 fprintf( out, "}" );
2085 if ( levels )
2086 fprintf( out, "\n" );
2087
2088}
2089
2090void selectOutsideClassState()
2091{
2092 if ( namespaces.count() == 0 )
2093 BEGIN OUTSIDE;
2094 else
2095 BEGIN IN_NAMESPACE;
2096}
2097
2098void registerClassInNamespace()
2099{
2100 if ( namespaces.count() == 0 )
2101 return;
2102 namespaces.last()->definedClasses.insert((const char *)g->className,(char*)1);
2103}
2104
2105//
2106// Remove white space from SIGNAL and SLOT names.
2107// This function has been copied from qobject.cpp.
2108//
2109
2110inline bool isIdentChar( char x )
2111{ // Avoid bug in isalnum
2112 return x == '_' || (x >= '0' && x <= '9') ||
2113 (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z');
2114}
2115
2116inline bool isSpace( char x )
2117{
2118#if defined(Q_CC_BOR)
2119 /*
2120 Borland C++ 4.5 has a weird isspace() bug.
2121 isspace() usually works, but not here.
2122 This implementation is sufficient for our internal use: rmWS()
2123 */
2124 return (uchar) x <= 32;
2125#else
2126 return isspace( (uchar) x );
2127#endif
2128}
2129
2130static QCString rmWS( const char *src )
2131{
2132 QCString result( qstrlen(src)+1 );
2133 char *d = result.data();
2134 char *s = (char *)src;
2135 char last = 0;
2136 while( *s && isSpace(*s) ) // skip leading space
2137 s++;
2138 while ( *s ) {
2139 while ( *s && !isSpace(*s) )
2140 last = *d++ = *s++;
2141 while ( *s && isSpace(*s) )
2142 s++;
2143 if ( *s && isIdentChar(*s) && isIdentChar(last) )
2144 last = *d++ = ' ';
2145 }
2146 result.truncate( (int)(d - result.data()) );
2147 return result;
2148}
2149
2150
2151void initExpression()
2152{
2153 g->tmpExpression = "";
2154}
2155
2156void addExpressionString( const char *s )
2157{
2158 g->tmpExpression += s;
2159}
2160
2161void addExpressionChar( const char c )
2162{
2163 g->tmpExpression += c;
2164}
2165
2166void yyerror( const char *msg ) // print yacc error message
2167{
2168 g->mocError = TRUE;
2169#ifndef MOC_MWERKS_PLUGIN
2170 fprintf( stderr, ErrorFormatString" Error: %s\n", g->fileName.data(), lineNo, msg );
2171#else
2172 char msg2[200];
2173 sprintf(msg2, ErrorFormatString" Error: %s", g->fileName.data(), lineNo, msg);
2174 CWReportMessage(g_ctx, NULL, msg2, NULL, messagetypeError, 0);
2175#endif
2176 if ( errorControl ) {
2177 if ( !g->outputFile.isEmpty() && yyin && fclose(yyin) == 0 )
2178 remove( g->outputFile );
2179 exit( -1 );
2180 }
2181}
2182
2183void moc_err( const char *s )
2184{
2185 yyerror( s );
2186}
2187
2188void moc_err( const char *s1, const char *s2 )
2189{
2190 static char tmp[1024];
2191 sprintf( tmp, s1, s2 );
2192 yyerror( tmp );
2193}
2194
2195void moc_warn( const char *msg )
2196{
2197 if ( displayWarnings )
2198 fprintf( stderr, ErrorFormatString" Warning: %s\n", g->fileName.data(), lineNo, msg);
2199}
2200
2201void moc_warn( char *s1, char *s2 )
2202{
2203 static char tmp[1024];
2204 sprintf( tmp, s1, s2 );
2205 if ( displayWarnings )
2206 fprintf( stderr, ErrorFormatString" Warning: %s\n", g->fileName.data(), lineNo, tmp);
2207}
2208
2209void func_warn( const char *msg )
2210{
2211 if ( !suppress_func_warn )
2212 moc_warn( msg );
2213 skipFunc = TRUE;
2214}
2215
2216void operatorError()
2217{
2218 if ( !suppress_func_warn )
2219 moc_warn("Operator functions cannot be signals or slots.");
2220 skipFunc = TRUE;
2221}
2222
2223#ifndef yywrap
2224int yywrap() // more files?
2225{
2226 return 1; // end of file
2227}
2228#endif
2229
2230char *stradd( const char *s1, const char *s2 ) // adds two strings
2231{
2232 char *n = new char[qstrlen(s1)+qstrlen(s2)+1];
2233 qstrcpy( n, s1 );
2234 strcat( n, s2 );
2235 return n;
2236}
2237
2238char *stradd( const char *s1, const char *s2, const char *s3 )// adds 3 strings
2239{
2240 char *n = new char[qstrlen(s1)+qstrlen(s2)+qstrlen(s3)+1];
2241 qstrcpy( n, s1 );
2242 strcat( n, s2 );
2243 strcat( n, s3 );
2244 return n;
2245}
2246
2247char *stradd( const char *s1, const char *s2,
2248 const char *s3, const char *s4 )// adds 4 strings
2249{
2250 char *n = new char[qstrlen(s1)+qstrlen(s2)+qstrlen(s3)+qstrlen(s4)+1];
2251 qstrcpy( n, s1 );
2252 strcat( n, s2 );
2253 strcat( n, s3 );
2254 strcat( n, s4 );
2255 return n;
2256}
2257
2258
2259char *straddSpc( const char *s1, const char *s2 )
2260{
2261 char *n = new char[qstrlen(s1)+qstrlen(s2)+2];
2262 qstrcpy( n, s1 );
2263 strcat( n, " " );
2264 strcat( n, s2 );
2265 return n;
2266}
2267
2268char *straddSpc( const char *s1, const char *s2, const char *s3 )
2269{
2270 char *n = new char[qstrlen(s1)+qstrlen(s2)+qstrlen(s3)+3];
2271 qstrcpy( n, s1 );
2272 strcat( n, " " );
2273 strcat( n, s2 );
2274 strcat( n, " " );
2275 strcat( n, s3 );
2276 return n;
2277}
2278
2279char *straddSpc( const char *s1, const char *s2,
2280 const char *s3, const char *s4 )
2281{
2282 char *n = new char[qstrlen(s1)+qstrlen(s2)+qstrlen(s3)+qstrlen(s4)+4];
2283 qstrcpy( n, s1 );
2284 strcat( n, " " );
2285 strcat( n, s2 );
2286 strcat( n, " " );
2287 strcat( n, s3 );
2288 strcat( n, " " );
2289 strcat( n, s4 );
2290 return n;
2291}
2292
2293// Generate C++ code for building member function table
2294
2295
2296/*
2297 We call B::qt_invoke() rather than A::B::qt_invoke() to
2298 work around a bug in MSVC 6. The bug occurs if the
2299 super-class is in a namespace and the sub-class isn't.
2300
2301 Exception: If the superclass has the same name as the subclass, we
2302 want non-MSVC users to have a working generated files.
2303*/
2304QCString purestSuperClassName()
2305{
2306 QCString sc = g->superClassName;
2307 QCString c = g->className;
2308 /*
2309 Make sure qualified template arguments (e.g., foo<bar::baz>)
2310 don't interfere.
2311 */
2312 int pos = sc.findRev( "::", sc.find( '<' ) );
2313 if ( pos != -1 ) {
2314 sc = sc.right( sc.length() - pos - 2 );
2315 pos = c.findRev( "::" );
2316 if ( pos != -1 )
2317 c = c.right( c.length() - pos - 2 );
2318 if ( sc == c )
2319 sc = g->superClassName;
2320 }
2321 return sc;
2322}
2323
2324QCString qualifiedClassName()
2325{
2326 return nameQualifier() + g->className;
2327}
2328
2329const int Slot_Num = 1;
2330const int Signal_Num = 2;
2331const int Prop_Num = 3;
2332
2333void generateFuncs( FuncList *list, const char *functype, int num )
2334{
2335 Function *f;
2336 for ( f=list->first(); f; f=list->next() ) {
2337 bool hasReturnValue = f->type != "void" && (validUType( f->type ) || isVariantType( f->type) );
2338
2339 if ( hasReturnValue || !f->args->isEmpty() ) {
2340 fprintf( out, " static const QUParameter param_%s_%d[] = {\n", functype, list->at() );
2341 if ( hasReturnValue ) {
2342 if ( validUType( f->type ) )
2343 fprintf( out, "\t{ 0, &static_QUType_%s, %s, QUParameter::Out }", uType(f->type).data(), uTypeExtra(f->type).data() );
2344 else
2345 fprintf( out, "\t{ 0, &static_QUType_QVariant, %s, QUParameter::Out }", uTypeExtra(f->type).data() );
2346 if ( !f->args->isEmpty() )
2347 fprintf( out, ",\n" );
2348 }
2349 Argument* a = f->args->first();
2350 while ( a ) {
2351 QCString type = a->leftType + ' ' + a->rightType;
2352 type = type.simplifyWhiteSpace();
2353 if( a->name.isEmpty() )
2354 fprintf( out, "\t{ 0, &static_QUType_%s, %s, QUParameter::%s }",
2355 uType( type ).data(), uTypeExtra( type ).data(),
2356 isInOut( type ) ? "InOut" : "In" );
2357 else
2358 fprintf( out, "\t{ \"%s\", &static_QUType_%s, %s, QUParameter::%s }",
2359 a->name.data(), uType( type ).data(), uTypeExtra( type ).data(),
2360 isInOut( type ) ? "InOut" : "In" );
2361 a = f->args->next();
2362 if ( a )
2363 fprintf( out, ",\n" );
2364 }
2365 fprintf( out, "\n };\n");
2366 }
2367
2368 fprintf( out, " static const QUMethod %s_%d = {", functype, list->at() );
2369 int n = f->args->count();
2370 if ( hasReturnValue )
2371 n++;
2372 fprintf( out, "\"%s\", %d,", f->name.data(), n );
2373 if ( n )
2374 fprintf( out, " param_%s_%d };\n", functype, list->at() );
2375 else
2376 fprintf( out, " 0 };\n" );
2377
2378 QCString typstr = "";
2379 int count = 0;
2380 Argument *a = f->args->first();
2381 while ( a ) {
2382 if ( !a->leftType.isEmpty() || ! a->rightType.isEmpty() ) {
2383 if ( count++ )
2384 typstr += ",";
2385 typstr += a->leftType;
2386 typstr += a->rightType;
2387 }
2388 a = f->args->next();
2389 }
2390 f->signature = f->name;
2391 f->signature += "(";
2392 f->signature += typstr;
2393 f->signature += ")";
2394 }
2395 if ( list->count() ) {
2396 fprintf(out," static const QMetaData %s_tbl[] = {\n", functype );
2397 f = list->first();
2398 while ( f ) {
2399 fprintf( out, "\t{ \"%s\",", f->signature.data() );
2400 fprintf( out, " &%s_%d,", functype, list->at() );
2401 fprintf( out, " QMetaData::%s }", f->accessAsString() );
2402 f = list->next();
2403 if ( f )
2404 fprintf( out, ",\n");
2405 }
2406 fprintf( out, "\n };\n" );
2407 }
2408}
2409
2410
2411int enumIndex( const char* type )
2412{
2413 int index = 0;
2414 for( QPtrListIterator<Enum> lit( g->enums ); lit.current(); ++lit ) {
2415 if ( lit.current()->name == type )
2416 return index;
2417 index++;
2418 }
2419 return -1;
2420}
2421
2422bool isEnumType( const char* type )
2423{
2424 return enumIndex( type ) >= 0 || ( g->qtEnums.contains( type ) || g->qtSets.contains( type ) );
2425}
2426
2427bool isPropertyType( const char* type )
2428{
2429 if ( isVariantType( type ) )
2430 return TRUE;
2431
2432 return isEnumType( type );
2433}
2434
2435int generateEnums()
2436{
2437 if ( g->enums.count() == 0 )
2438 return 0;
2439
2440 fprintf( out, "#ifndef QT_NO_PROPERTIES\n" );
2441 int i = 0;
2442 for ( QPtrListIterator<Enum> it( g->enums ); it.current(); ++it, ++i ) {
2443 fprintf( out, " static const QMetaEnum::Item enum_%i[] = {\n", i );
2444 int k = 0;
2445 for( QStrListIterator eit( *it.current() ); eit.current(); ++eit, ++k ) {
2446 if ( k )
2447 fprintf( out, ",\n" );
2448 fprintf( out, "\t{ \"%s\", (int) %s::%s }", eit.current(), (const char*) g->className, eit.current() );
2449 }
2450 fprintf( out, "\n };\n" );
2451 }
2452 fprintf( out, " static const QMetaEnum enum_tbl[] = {\n" );
2453 i = 0;
2454 for ( QPtrListIterator<Enum> it2( g->enums ); it2.current(); ++it2, ++i ) {
2455 if ( i )
2456 fprintf( out, ",\n" );
2457 fprintf( out, "\t{ \"%s\", %u, enum_%i, %s }",
2458 (const char*)it2.current()->name,
2459 it2.current()->count(),
2460 i,
2461 it2.current()->set ? "TRUE" : "FALSE" );
2462 }
2463 fprintf( out, "\n };\n" );
2464 fprintf( out, "#endif // QT_NO_PROPERTIES\n" );
2465
2466 return g->enums.count();
2467}
2468
2469int generateProps()
2470{
2471 //
2472 // Resolve and verify property access functions
2473 //
2474 for( QPtrListIterator<Property> it( g->props ); it.current(); ) {
2475 Property* p = it.current();
2476 ++it;
2477
2478 // verify get function
2479 if ( !p->get.isEmpty() ) {
2480 FuncList candidates = g->propfuncs.find( p->get );
2481 for ( Function* f = candidates.first(); f; f = candidates.next() ) {
2482 if ( f->qualifier != "const" ) // get functions must be const
2483 continue;
2484 if ( f->args && !f->args->isEmpty() ) // and must not take any arguments
2485 continue;
2486 QCString tmp = f->type;
2487 Property::Specification spec = Property::Unspecified;
2488 if ( p->type == "QCString" && (tmp == "const char*" || tmp == "const char *" ) ) {
2489 tmp = "QCString";
2490 spec = Property::ConstCharStar;
2491 } else if ( tmp.right(1) == "&" ) {
2492 tmp = tmp.left( tmp.length() - 1 );
2493 spec = Property::Reference;
2494 } else if ( tmp.right(1) == "*" ) {
2495 tmp = tmp.left( tmp.length() - 1 );
2496 spec = Property::Pointer;
2497 } else {
2498 spec = Property::Class;
2499 }
2500 if ( tmp.left(6) == "const " )
2501 tmp = tmp.mid( 6, tmp.length() - 6 );
2502 tmp = tmp.simplifyWhiteSpace();
2503 if ( p->type == tmp ) {
2504 // If it is an enum then it may not be a set
2505 bool ok = TRUE;
2506 for( QPtrListIterator<Enum> lit( g->enums ); lit.current(); ++lit )
2507 if ( lit.current()->name == p->type && lit.current()->set )
2508 ok = FALSE;
2509 if ( !ok ) continue;
2510 p->gspec = spec;
2511 p->getfunc = f;
2512 p->oredEnum = 0;
2513 break;
2514 }
2515 else if ( !isVariantType( p->type ) ) {
2516 if ( tmp == "int" || tmp == "uint" || tmp == "unsigned int" ) {
2517 // Test whether the enum is really a set (unfortunately we don't know enums of super classes)
2518 bool ok = TRUE;
2519 for( QPtrListIterator<Enum> lit( g->enums ); lit.current(); ++lit )
2520 if ( lit.current()->name == p->type && !lit.current()->set )
2521 ok = FALSE;
2522 if ( !ok ) continue;
2523 p->gspec = spec;
2524 p->getfunc = f;
2525 p->oredEnum = 1;
2526 p->enumgettype = tmp;
2527 }
2528 }
2529 }
2530 if ( p->getfunc == 0 ) {
2531 if ( displayWarnings ) {
2532
2533 // Is the type a set, that means, mentioned in Q_SETS?
2534 bool set = FALSE;
2535 for( QPtrListIterator<Enum> lit( g->enums ); lit.current(); ++lit )
2536 if ( lit.current()->name == p->type && lit.current()->set )
2537 set = TRUE;
2538
2539 fprintf( stderr, ErrorFormatString" Warning: Property '%s' not available.\n",
2540 g->fileName.data(), p->lineNo, (const char*) p->name );
2541 fprintf( stderr, " Have been looking for public get functions \n");
2542 if ( !set ) {
2543 fprintf( stderr,
2544 " %s %s() const\n"
2545 " %s& %s() const\n"
2546 " const %s& %s() const\n"
2547 " %s* %s() const\n",
2548 (const char*) p->type, (const char*) p->get,
2549 (const char*) p->type, (const char*) p->get,
2550 (const char*) p->type, (const char*) p->get,
2551 (const char*) p->type, (const char*) p->get );
2552 }
2553 if ( set || !isPropertyType( p->type ) ) {
2554 fprintf( stderr,
2555 " int %s() const\n"
2556 " uint %s() const\n"
2557 " unsigned int %s() const\n",
2558 (const char*) p->get,
2559 (const char*) p->get,
2560 (const char*) p->get );
2561 }
2562 if ( p->type == "QCString" )
2563 fprintf( stderr, " const char* %s() const\n",
2564 (const char*)p->get );
2565
2566 if ( candidates.isEmpty() ) {
2567 fprintf( stderr, " but found nothing.\n");
2568 } else {
2569 fprintf( stderr, " but only found the mismatching candidate(s)\n");
2570 for ( Function* f = candidates.first(); f; f = candidates.next() ) {
2571 QCString typstr = "";
2572 Argument *a = f->args->first();
2573 int count = 0;
2574 while ( a ) {
2575 if ( !a->leftType.isEmpty() || ! a->rightType.isEmpty() ) {
2576 if ( count++ )
2577 typstr += ",";
2578 typstr += a->leftType;
2579 typstr += a->rightType;
2580 }
2581 a = f->args->next();
2582 }
2583 fprintf( stderr, " %s:%d: %s %s(%s) %s\n", g->fileName.data(), f->lineNo,
2584 (const char*) f->type,(const char*) f->name, (const char*) typstr,
2585 f->qualifier.isNull()?"":(const char*) f->qualifier );
2586 }
2587 }
2588 }
2589 }
2590 }
2591
2592 // verify set function
2593 if ( !p->set.isEmpty() ) {
2594 FuncList candidates = g->propfuncs.find( p->set );
2595 for ( Function* f = candidates.first(); f; f = candidates.next() ) {
2596 if ( !f->args || f->args->isEmpty() )
2597 continue;
2598 QCString tmp = f->args->first()->leftType;
2599 tmp = tmp.simplifyWhiteSpace();
2600 Property::Specification spec = Property::Unspecified;
2601 if ( tmp.right(1) == "&" ) {
2602 tmp = tmp.left( tmp.length() - 1 );
2603 spec = Property::Reference;
2604 }
2605 else {
2606 spec = Property::Class;
2607 }
2608 if ( p->type == "QCString" && (tmp == "const char*" || tmp == "const char *" ) ) {
2609 tmp = "QCString";
2610 spec = Property::ConstCharStar;
2611 }
2612 if ( tmp.left(6) == "const " )
2613 tmp = tmp.mid( 6, tmp.length() - 6 );
2614 tmp = tmp.simplifyWhiteSpace();
2615
2616 if ( p->type == tmp && f->args->count() == 1 ) {
2617 // If it is an enum then it may not be a set
2618 if ( p->oredEnum == 1 )
2619 continue;
2620 bool ok = TRUE;
2621 for( QPtrListIterator<Enum> lit( g->enums ); lit.current(); ++lit )
2622 if ( lit.current()->name == p->type && lit.current()->set )
2623 ok = FALSE;
2624 if ( !ok ) continue;
2625 p->sspec = spec;
2626 p->setfunc = f;
2627 p->oredEnum = 0;
2628 break;
2629 } else if ( !isVariantType( p->type ) && f->args->count() == 1 ) {
2630 if ( tmp == "int" || tmp == "uint" || tmp == "unsigned int" ) {
2631 if ( p->oredEnum == 0 )
2632 continue;
2633 // Test wether the enum is really a set (unfortunately we don't know enums of super classes)
2634 bool ok = TRUE;
2635 for( QPtrListIterator<Enum> lit( g->enums ); lit.current(); ++lit )
2636 if ( lit.current()->name == p->type && !lit.current()->set )
2637 ok = FALSE;
2638 if ( !ok ) continue;
2639 p->sspec = spec;
2640 p->setfunc = f;
2641 p->oredEnum = 1;
2642 p->enumsettype = tmp;
2643 }
2644 }
2645 }
2646 if ( p->setfunc == 0 ) {
2647 if ( displayWarnings ) {
2648
2649 // Is the type a set, that means, mentioned in Q_SETS ?
2650 bool set = FALSE;
2651 for( QPtrListIterator<Enum> lit( g->enums ); lit.current(); ++lit )
2652 if ( lit.current()->name == p->type && lit.current()->set )
2653 set = TRUE;
2654
2655 fprintf( stderr, ErrorFormatString" Warning: Property '%s' not writable.\n",
2656 g->fileName.data(), p->lineNo, (const char*) p->name );
2657 fprintf( stderr, " Have been looking for public set functions \n");
2658 if ( !set && p->oredEnum != 1 ) {
2659 fprintf( stderr,
2660 " void %s( %s )\n"
2661 " void %s( %s& )\n"
2662 " void %s( const %s& )\n",
2663 (const char*) p->set, (const char*) p->type,
2664 (const char*) p->set, (const char*) p->type,
2665 (const char*) p->set, (const char*) p->type );
2666 }
2667 if ( set || ( !isPropertyType( p->type ) && p->oredEnum != 0 ) ) {
2668 fprintf( stderr,
2669 " void %s( int )\n"
2670 " void %s( uint )\n"
2671 " void %s( unsigned int )\n",
2672 (const char*) p->set,
2673 (const char*) p->set,
2674 (const char*) p->set );
2675 }
2676
2677 if ( p->type == "QCString" )
2678 fprintf( stderr, " void %s( const char* ) const\n",
2679 (const char*) p->set );
2680
2681 if ( !candidates.isEmpty() ) {
2682 fprintf( stderr, " but only found the mismatching candidate(s)\n");
2683 for ( Function* f = candidates.first(); f; f = candidates.next() ) {
2684 QCString typstr = "";
2685 Argument *a = f->args->first();
2686 int count = 0;
2687 while ( a ) {
2688 if ( !a->leftType.isEmpty() || ! a->rightType.isEmpty() ) {
2689 if ( count++ )
2690 typstr += ",";
2691 typstr += a->leftType;
2692 typstr += a->rightType;
2693 }
2694 a = f->args->next();
2695 }
2696 fprintf( stderr, " %s:%d: %s %s(%s)\n", g->fileName.data(), f->lineNo,
2697 (const char*) f->type,(const char*) f->name, (const char*) typstr );
2698 }
2699 }
2700 }
2701 }
2702 }
2703 }
2704
2705 //
2706 // Create meta data
2707 //
2708 if ( g->props.count() ) {
2709 if ( displayWarnings && !Q_OBJECTdetected )
2710 moc_err("The declaration of the class \"%s\" contains properties"
2711 " but no Q_OBJECT macro.", g->className.data());
2712
2713 fprintf( out, "#ifndef QT_NO_PROPERTIES\n" );
2714
2715 fprintf( out, " static const QMetaProperty props_tbl[%d] = {\n ", g->props.count() );
2716 for( QPtrListIterator<Property> it( g->props ); it.current(); ++it ) {
2717
2718 fprintf( out, "\t{ \"%s\",\"%s\", ", it.current()->type.data(), it.current()->name.data() );
2719 int flags = Invalid;
2720 if ( !isVariantType( it.current()->type ) ) {
2721 flags |= EnumOrSet;
2722 if ( !isEnumType( it.current()->type ) )
2723 flags |= UnresolvedEnum;
2724 } else {
2725 flags |= qvariant_nameToType( it.current()->type ) << 24;
2726 }
2727 if ( it.current()->getfunc )
2728 flags |= Readable;
2729 if ( it.current()->setfunc ) {
2730 flags |= Writable;
2731 if ( it.current()->stdSet() )
2732 flags |= StdSet;
2733 }
2734 if ( it.current()->override )
2735 flags |= Override;
2736
2737 if ( it.current()->designable.isEmpty() )
2738 flags |= DesignableOverride;
2739 else if ( it.current()->designable == "false" )
2740 flags |= NotDesignable;
2741
2742 if ( it.current()->scriptable.isEmpty() )
2743 flags |= ScriptableOverride;
2744 else if ( it.current()->scriptable == "false" )
2745 flags |= NotScriptable;
2746
2747 if ( it.current()->stored.isEmpty() )
2748 flags |= StoredOverride;
2749 else if ( it.current()->stored == "false" )
2750 flags |= NotStored;
2751
2752
2753 fprintf( out, "0x%.4x, ", flags );
2754 fprintf( out, "&%s::metaObj, ", (const char*) qualifiedClassName() );
2755 if ( !isVariantType( it.current()->type ) ) {
2756 int enumpos = -1;
2757 int k = 0;
2758 for( QPtrListIterator<Enum> eit( g->enums ); eit.current(); ++eit, ++k ) {
2759 if ( eit.current()->name == it.current()->type )
2760 enumpos = k;
2761 }
2762
2763 // Is it an enum of this class ?
2764 if ( enumpos != -1 )
2765 fprintf( out, "&enum_tbl[%i], ", enumpos );
2766 else
2767 fprintf( out, "0, ");
2768 } else {
2769 fprintf( out, "0, ");
2770 }
2771 fprintf( out, "-1 }" );
2772 if ( !it.atLast() )
2773 fprintf( out, ",\n" );
2774 else
2775 fprintf( out, "\n" );
2776 }
2777 fprintf( out, " };\n" );
2778 fprintf( out, "#endif // QT_NO_PROPERTIES\n" );
2779 }
2780
2781 return g->props.count();
2782}
2783
2784
2785
2786int generateClassInfos()
2787{
2788 if ( g->infos.isEmpty() )
2789 return 0;
2790
2791 if ( displayWarnings && !Q_OBJECTdetected )
2792 moc_err("The declaration of the class \"%s\" contains class infos"
2793 " but no Q_OBJECT macro.", g->className.data());
2794
2795 fprintf( out, " static const QClassInfo classinfo_tbl[] = {\n" );
2796 int i = 0;
2797 for( QPtrListIterator<ClassInfo> it( g->infos ); it.current(); ++it, ++i ) {
2798 if ( i )
2799 fprintf( out, ",\n" );
2800 fprintf( out, "\t{ \"%s\", \"%s\" }", it.current()->name.data(),it.current()->value.data() );
2801 }
2802 fprintf( out, "\n };\n" );
2803 return i;
2804}
2805
2806
2807void generateClass() // generate C++ source code for a class
2808{
2809 const char *hdr1 = "/****************************************************************************\n"
2810 "** %s meta object code from reading C++ file '%s'\n**\n";
2811 const char *hdr2 = "** Created: %s\n"
2812 "** by: The Qt MOC ($Id: moc.y 2 2005-11-16 15:49:26Z dmik $)\n**\n";
2813 const char *hdr3 = "** WARNING! All changes made in this file will be lost!\n";
2814 const char *hdr4 = "*****************************************************************************/\n\n";
2815 int i;
2816
2817 if ( skipClass ) // don't generate for class
2818 return;
2819
2820 if ( !Q_OBJECTdetected ) {
2821 if ( g->signals.count() == 0 && g->slots.count() == 0 && g->props.count() == 0 && g->infos.count() == 0 )
2822 return;
2823 if ( displayWarnings && (g->signals.count() + g->slots.count()) != 0 )
2824 moc_err("The declaration of the class \"%s\" contains signals "
2825 "or slots\n\t but no Q_OBJECT macro.", g->className.data());
2826 } else {
2827 if ( g->superClassName.isEmpty() )
2828 moc_err("The declaration of the class \"%s\" contains the\n"
2829 "\tQ_OBJECT macro but does not inherit from any class!\n"
2830 "\tInherit from QObject or one of its descendants"
2831 " or remove Q_OBJECT.", g->className.data() );
2832 }
2833 if ( templateClass ) { // don't generate for class
2834 moc_err( "Sorry, Qt does not support templates that contain\n"
2835 "\tsignals, slots or Q_OBJECT." );
2836 return;
2837 }
2838 g->generatedCode = TRUE;
2839 g->gen_count++;
2840
2841 if ( g->gen_count == 1 ) { // first class to be generated
2842 QDateTime dt = QDateTime::currentDateTime();
2843 QCString dstr = dt.toString().ascii();
2844 QCString fn = g->fileName;
2845 i = g->fileName.length()-1;
2846 while ( i>0 && g->fileName[i-1] != '/' && g->fileName[i-1] != '\\' )
2847 i--; // skip path
2848 if ( i >= 0 )
2849 fn = &g->fileName[i];
2850 fprintf( out, hdr1, (const char*)qualifiedClassName(),(const char*)fn);
2851 fprintf( out, hdr2, (const char*)dstr );
2852 fprintf( out, hdr3 );
2853 fprintf( out, hdr4 );
2854
2855 if ( !g->noInclude ) {
2856 /*
2857 The header file might be a Qt header file with
2858 QT_NO_COMPAT macros around signals, slots or
2859 properties. Without the #undef, we cannot compile the
2860 Qt library with QT_NO_COMPAT defined.
2861
2862 Header files of libraries build around Qt can also use
2863 QT_NO_COMPAT, so this #undef might be beneficial to
2864 users of Qt, and not only to developers of Qt.
2865 */
2866 fprintf( out, "#undef QT_NO_COMPAT\n" );
2867
2868 if ( !g->pchFile.isEmpty() )
2869 fprintf( out, "#include \"%s\" // PCH include\n", (const char*)g->pchFile );
2870 if ( !g->includePath.isEmpty() && g->includePath.right(1) != "/" )
2871 g->includePath += "/";
2872
2873 g->includeFiles.first();
2874 while ( g->includeFiles.current() ) {
2875 QCString inc = g->includeFiles.current();
2876 if ( inc[0] != '<' && inc[0] != '"' ) {
2877 if ( !g->includePath.isEmpty() && g->includePath != "./" )
2878 inc.prepend( g->includePath );
2879 inc = "\"" + inc + "\"";
2880 }
2881 fprintf( out, "#include %s\n", (const char *)inc );
2882 g->includeFiles.next();
2883 }
2884 }
2885 fprintf( out, "#include <%sqmetaobject.h>\n", (const char*)g->qtPath );
2886 fprintf( out, "#include <%sqapplication.h>\n\n", (const char*)g->qtPath );
2887 fprintf( out, "#include <%sprivate/qucomextra_p.h>\n", (const char*)g->qtPath );
2888 fprintf( out, "#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != %d)\n", formatRevision );
2889 fprintf( out, "#error \"This file was generated using the moc from %s."
2890 " It\"\n#error \"cannot be used with the include files from"
2891 " this version of Qt.\"\n#error \"(The moc has changed too"
2892 " much.)\"\n", QT_VERSION_STR );
2893 fprintf( out, "#endif\n\n" );
2894 } else {
2895 fprintf( out, "\n\n" );
2896 }
2897
2898 if ( !g->hasVariantIncluded ) {
2899 bool needToIncludeVariant = !g->props.isEmpty();
2900 for ( Function* f =g->slots.first(); f && !needToIncludeVariant; f=g->slots.next() )
2901 needToIncludeVariant = ( f->type != "void" && !validUType( f->type ) && isVariantType( f->type) );
2902
2903 if ( needToIncludeVariant ) {
2904 fprintf( out, "#include <%sqvariant.h>\n", (const char*)g->qtPath );
2905 g->hasVariantIncluded = TRUE;
2906 }
2907 }
2908
2909 bool isQObject = g->className == "QObject" ;
2910
2911
2912//
2913// Generate virtual function className()
2914//
2915 fprintf( out, "const char *%s::className() const\n{\n ",
2916 (const char*)qualifiedClassName() );
2917 fprintf( out, "return \"%s\";\n}\n\n", (const char*)qualifiedClassName() );
2918
2919//
2920// Generate static metaObj variable
2921//
2922 fprintf( out, "QMetaObject *%s::metaObj = 0;\n", (const char*)qualifiedClassName());
2923
2924//
2925// Generate static cleanup object variable
2926//
2927 QCString cleanup = qualifiedClassName().copy();
2928 for ( int cnpos = 0; cnpos < cleanup.length(); cnpos++ ) {
2929 if ( cleanup[cnpos] == ':' )
2930 cleanup[cnpos] = '_';
2931 }
2932
2933 fprintf( out, "static QMetaObjectCleanUp cleanUp_%s( \"%s\", &%s::staticMetaObject );\n\n", (const char*)cleanup, (const char*)qualifiedClassName(), (const char*)qualifiedClassName() );
2934
2935//
2936// Generate tr and trUtf8 member functions
2937//
2938 fprintf( out, "#ifndef QT_NO_TRANSLATION\n" );
2939 fprintf( out, "QString %s::tr( const char *s, const char *c )\n{\n",
2940 (const char*)qualifiedClassName() );
2941 fprintf( out, " if ( qApp )\n" );
2942 fprintf( out, "\treturn qApp->translate( \"%s\", s, c,"
2943 " QApplication::DefaultCodec );\n",
2944 (const char*)qualifiedClassName() );
2945 fprintf( out, " else\n" );
2946 fprintf( out, "\treturn QString::fromLatin1( s );\n");
2947 fprintf( out, "}\n" );
2948 fprintf( out, "#ifndef QT_NO_TRANSLATION_UTF8\n" );
2949 fprintf( out, "QString %s::trUtf8( const char *s, const char *c )\n{\n",
2950 (const char*)qualifiedClassName() );
2951 fprintf( out, " if ( qApp )\n" );
2952 fprintf( out, "\treturn qApp->translate( \"%s\", s, c,"
2953 " QApplication::UnicodeUTF8 );\n",
2954 (const char*)qualifiedClassName() );
2955 fprintf( out, " else\n" );
2956 fprintf( out, "\treturn QString::fromUtf8( s );\n" );
2957 fprintf( out, "}\n" );
2958 fprintf( out, "#endif // QT_NO_TRANSLATION_UTF8\n\n" );
2959 fprintf( out, "#endif // QT_NO_TRANSLATION\n\n" );
2960
2961//
2962// Generate staticMetaObject member function
2963//
2964 fprintf( out, "QMetaObject* %s::staticMetaObject()\n{\n", (const char*)qualifiedClassName() );
2965 fprintf( out, " if ( metaObj )\n\treturn metaObj;\n" );
2966 if ( isQObject )
2967 fprintf( out, " QMetaObject* parentObject = staticQtMetaObject();\n" );
2968 else if ( !g->superClassName.isEmpty() )
2969 fprintf( out, " QMetaObject* parentObject = %s::staticMetaObject();\n", (const char*)g->superClassName );
2970 else
2971 fprintf( out, " QMetaObject* parentObject = 0;\n" );
2972
2973//
2974// Build the classinfo array
2975//
2976 int n_infos = generateClassInfos();
2977
2978// Build the enums array
2979// Enums HAVE to be generated BEFORE the properties and slots
2980//
2981 int n_enums = generateEnums();
2982
2983//
2984// Build slots array in staticMetaObject()
2985//
2986 generateFuncs( &g->slots, "slot", Slot_Num );
2987
2988//
2989// Build signals array in staticMetaObject()
2990//
2991 generateFuncs( &g->signals, "signal", Signal_Num );
2992
2993//
2994// Build property array in staticMetaObject()
2995//
2996 int n_props = generateProps();
2997
2998//
2999// Finally code to create and return meta object
3000//
3001 fprintf( out, " metaObj = QMetaObject::new_metaobject(\n"
3002 "\t\"%s\", parentObject,\n", (const char*)qualifiedClassName() );
3003
3004 if ( g->slots.count() )
3005 fprintf( out, "\tslot_tbl, %d,\n", g->slots.count() );
3006 else
3007 fprintf( out, "\t0, 0,\n" );
3008
3009 if ( g->signals.count() )
3010 fprintf( out, "\tsignal_tbl, %d,\n", g->signals.count() );
3011 else
3012 fprintf( out, "\t0, 0,\n" );
3013
3014 fprintf( out, "#ifndef QT_NO_PROPERTIES\n" );
3015 if ( n_props )
3016 fprintf( out, "\tprops_tbl, %d,\n", n_props );
3017 else
3018 fprintf( out, "\t0, 0,\n" );
3019 if ( n_enums )
3020 fprintf( out, "\tenum_tbl, %d,\n", n_enums );
3021 else
3022 fprintf( out, "\t0, 0,\n" );
3023 fprintf( out, "#endif // QT_NO_PROPERTIES\n" );
3024
3025 if ( n_infos )
3026 fprintf( out, "\tclassinfo_tbl, %d );\n", n_infos );
3027 else
3028 fprintf( out, "\t0, 0 );\n" );
3029
3030
3031//
3032// Setup cleanup handler and return meta object
3033//
3034 fprintf( out, " cleanUp_%s.setMetaObject( metaObj );\n", cleanup.data() );
3035 fprintf( out, " return metaObj;\n}\n" );
3036
3037//
3038// End of function staticMetaObject()
3039//
3040
3041//
3042// Generate smart cast function
3043//
3044 fprintf( out, "\nvoid* %s::qt_cast( const char* clname )\n{\n",
3045 (const char*)qualifiedClassName() );
3046 fprintf( out, " if ( !qstrcmp( clname, \"%s\" ) )\n"
3047 "\treturn this;\n",
3048 (const char*)qualifiedClassName() );
3049 for ( const char* cname = g->multipleSuperClasses.first(); cname; cname = g->multipleSuperClasses.next() )
3050 fprintf( out, " if ( !qstrcmp( clname, \"%s\" ) )\n"
3051 "\treturn (%s*)this;\n", cname, cname );
3052 if ( !g->superClassName.isEmpty() && !isQObject )
3053 fprintf( out, " return %s::qt_cast( clname );\n",
3054 (const char*)purestSuperClassName() );
3055 else
3056 fprintf( out, " return 0;\n" );
3057 fprintf( out, "}\n" );
3058
3059//
3060// Generate internal signal functions
3061//
3062 Function *f;
3063 f = g->signals.first(); // make internal signal methods
3064 static bool included_list_headers = FALSE;
3065 int sigindex = 0;
3066 while ( f ) {
3067 QCString argstr;
3068 char buf[12];
3069 Argument *a = f->args->first();
3070 int offset = 0;
3071 const char *predef_call_func = 0;
3072 bool hasReturnValue = f->type != "void" && (validUType( f->type ) || isVariantType( f->type) );
3073 if ( hasReturnValue ) {
3074 ; // no predefined function available
3075 } else if ( !a ) {
3076 predef_call_func = "activate_signal";
3077 } else if ( f->args->count() == 1 ) {
3078 QCString ctype = (a->leftType + ' ' + a->rightType).simplifyWhiteSpace();
3079 if ( !isInOut( ctype ) ) {
3080 QCString utype = uType( ctype );
3081 if ( utype == "bool" )
3082 predef_call_func = "activate_signal_bool";
3083 else if ( utype == "QString" || utype == "int" || utype == "double" )
3084 predef_call_func = "activate_signal";
3085 }
3086 }
3087
3088 if ( !predef_call_func && !included_list_headers ) {
3089 // yes we need it, because otherwise QT_VERSION may not be defined
3090 fprintf( out, "\n#include <%sqobjectdefs.h>\n", (const char*)g->qtPath );
3091 fprintf( out, "#include <%sqsignalslotimp.h>\n", (const char*)g->qtPath );
3092 included_list_headers = TRUE;
3093 }
3094
3095 while ( a ) { // argument list
3096 if ( !a->leftType.isEmpty() || !a->rightType.isEmpty() ) {
3097 argstr += a->leftType;
3098 argstr += " ";
3099 sprintf( buf, "t%d", offset++ );
3100 argstr += buf;
3101 argstr += a->rightType;
3102 a = f->args->next();
3103 if ( a )
3104 argstr += ", ";
3105 } else {
3106 a = f->args->next();
3107 }
3108 }
3109
3110 fixRightAngles( &argstr );
3111
3112 fprintf( out, "\n// SIGNAL %s\n", (const char*)f->name );
3113 fprintf( out, "%s %s::%s(", (const char*) f->type,
3114 (const char*)qualifiedClassName(),
3115 (const char*)f->name );
3116
3117 if ( argstr.isEmpty() )
3118 fprintf( out, ")\n{\n" );
3119 else
3120 fprintf( out, " %s )\n{\n", (const char*)argstr );
3121
3122 if ( predef_call_func ) {
3123 fprintf( out, " %s( staticMetaObject()->signalOffset() + %d", predef_call_func, sigindex );
3124 if ( !argstr.isEmpty() )
3125 fprintf( out, ", t0" );
3126 fprintf( out, " );\n}\n" );
3127 } else {
3128 if ( hasReturnValue )
3129 fprintf( out, " %s something;\n", f->type.data() );
3130 int nargs = f->args->count();
3131 fprintf( out, " if ( signalsBlocked() )\n\treturn%s;\n", hasReturnValue ? " something" : "" );
3132 fprintf( out, " QConnectionList *clist = receivers( staticMetaObject()->signalOffset() + %d );\n",
3133 sigindex );
3134 fprintf( out, " if ( !clist )\n\treturn%s;\n", hasReturnValue ? " something" : "" );
3135 fprintf( out, " QUObject o[%d];\n", f->args->count() + 1 );
3136
3137 // initialize return value to something
3138 if ( hasReturnValue ) {
3139 if ( validUType( f->type ) ) {
3140 QCString utype = uType( f->type );
3141 fprintf( out, " static_QUType_%s.set(o,something);\n", utype.data() );
3142 } else if ( uType( f->type ) == "varptr" ) {
3143 fprintf( out, " static_QUType_varptr.set(o,&something);\n" );
3144 } else {
3145 fprintf( out, " static_QUType_ptr.set(o,&something);\n" );
3146 }
3147 }
3148
3149 // initialize arguments
3150 if ( !f->args->isEmpty() ) {
3151 offset = 0;
3152 Argument* a = f->args->first();
3153 while ( a ) {
3154 QCString type = a->leftType + ' ' + a->rightType;
3155 type = type.simplifyWhiteSpace();
3156 if ( validUType( type ) ) {
3157 QCString utype = uType( type );
3158 fprintf( out, " static_QUType_%s.set(o+%d,t%d);\n", utype.data(), offset+1, offset );
3159 } else if ( uType( type ) == "varptr" ) {
3160 fprintf( out, " static_QUType_varptr.set(o+%d,&t%d);\n", offset+1, offset );
3161 } else {
3162 fprintf( out, " static_QUType_ptr.set(o+%d,&t%d);\n", offset+1, offset );
3163 }
3164 a = f->args->next();
3165 offset++;
3166 }
3167 }
3168 fprintf( out, " activate_signal( clist, o );\n" );
3169
3170 // get return values from inOut parameters
3171 if ( !f->args->isEmpty() ) {
3172 offset = 0;
3173 Argument* a = f->args->first();
3174 while ( a ) {
3175 QCString type = a->leftType + ' ' + a->rightType;
3176 type = type.simplifyWhiteSpace();
3177 if ( validUType( type ) && isInOut( type ) ) {
3178 QCString utype = uType( type );
3179 if ( utype == "enum" )
3180 fprintf( out, " t%d = (%s)static_QUType_%s.get(o+%d);\n", offset, type.data(), utype.data(), offset+1 );
3181 else if ( utype == "ptr" && type.right(2) == "**" )
3182 fprintf( out, " if (t%d) *t%d = *(%s)static_QUType_ptr.get(o+%d);\n", offset, offset, type.data(), offset+1 );
3183 else
3184 fprintf( out, " t%d = static_QUType_%s.get(o+%d);\n", offset, utype.data(), offset+1 );
3185 }
3186 a = f->args->next();
3187 offset++;
3188 }
3189 }
3190
3191 // get and return return value
3192 if ( hasReturnValue ) {
3193 QCString utype = uType( f->type );
3194 if ( utype == "enum" || utype == "ptr" || utype == "varptr" ) // need cast
3195 fprintf( out, " return (%s)static_QUType_%s.get(o);\n", f->type.data(), utype.data() );
3196 else
3197 fprintf( out, " return static_QUType_%s.get(o);\n", utype.data() );
3198 }
3199
3200 fprintf( out, "}\n" );
3201 }
3202
3203 f = g->signals.next();
3204 sigindex++;
3205 }
3206
3207
3208//
3209// Generate internal qt_invoke() function
3210//
3211 fprintf( out, "\nbool %s::qt_invoke( int _id, QUObject* _o )\n{\n", qualifiedClassName().data() );
3212
3213 if( !g->slots.isEmpty() ) {
3214 fprintf( out, " switch ( _id - staticMetaObject()->slotOffset() ) {\n" );
3215 int slotindex = -1;
3216 for ( f = g->slots.first(); f; f = g->slots.next() ) {
3217 slotindex ++;
3218 if ( f->type == "void" && f->args->isEmpty() ) {
3219 fprintf( out, " case %d: %s(); break;\n", slotindex, f->name.data() );
3220 continue;
3221 }
3222
3223 fprintf( out, " case %d: ", slotindex );
3224 bool hasReturnValue = FALSE;
3225 bool hasVariantReturn = FALSE;
3226 if ( f->type != "void" ) {
3227 if ( validUType( f->type )) {
3228 hasReturnValue = TRUE;
3229 fprintf( out, "static_QUType_%s.set(_o,", uType(f->type).data() );
3230 } else if ( isVariantType( f->type ) ) {
3231 hasReturnValue = hasVariantReturn = TRUE;
3232 // do not need special handling for bool since this is handled as utype
3233 fprintf( out, "static_QUType_QVariant.set(_o,QVariant(" );
3234 }
3235 }
3236 int offset = 0;
3237 fprintf( out, "%s(", f->name.data() );
3238 Argument* a = f->args->first();
3239 while ( a ) {
3240 QCString type = a->leftType + ' ' + a->rightType;
3241 type = type.simplifyWhiteSpace();
3242 fixRightAngles( &type );
3243 if ( validUType( type ) ) {
3244 QCString utype = uType( type );
3245 if ( utype == "ptr" || utype == "varptr" || utype == "enum" )
3246 fprintf( out, "(%s)static_QUType_%s.get(_o+%d)", type.data(), utype.data(), offset+1 );
3247 else
3248 fprintf( out, "(%s)static_QUType_%s.get(_o+%d)", type.data(), utype.data(), offset+1 );
3249 } else {
3250 QCString castType = castToUType( type );
3251 if(castType == type)
3252 fprintf( out, "(%s)(*((%s*)static_QUType_ptr.get(_o+%d)))", type.data(),
3253 castType.data(), offset+1 );
3254 else
3255 fprintf( out, "(%s)*((%s*)static_QUType_ptr.get(_o+%d))", type.data(),
3256 castType.data(), offset+1 );
3257 }
3258 a = f->args->next();
3259 if ( a )
3260 fprintf( out, "," );
3261 offset++;
3262 }
3263 fprintf( out, ")" );
3264 if ( hasReturnValue )
3265 fprintf( out, ")" );
3266 if ( hasVariantReturn )
3267 fprintf( out, ")" );
3268 fprintf( out, "; break;\n" );
3269 }
3270 fprintf( out, " default:\n" );
3271
3272 if ( !g->superClassName.isEmpty() && !isQObject ) {
3273 fprintf( out, "\treturn %s::qt_invoke( _id, _o );\n",
3274 (const char *) purestSuperClassName() );
3275 } else {
3276 fprintf( out, "\treturn FALSE;\n" );
3277 }
3278 fprintf( out, " }\n" );
3279 fprintf( out, " return TRUE;\n}\n" );
3280 } else {
3281 if ( !g->superClassName.isEmpty() && !isQObject )
3282 fprintf( out, " return %s::qt_invoke(_id,_o);\n}\n",
3283 (const char *) purestSuperClassName() );
3284 else
3285 fprintf( out, " return FALSE;\n}\n" );
3286 }
3287
3288
3289//
3290// Generate internal qt_emit() function
3291//
3292 fprintf( out, "\nbool %s::qt_emit( int _id, QUObject* _o )\n{\n", qualifiedClassName().data() );
3293
3294 if ( !g->signals.isEmpty() ) {
3295 fprintf( out, " switch ( _id - staticMetaObject()->signalOffset() ) {\n" );
3296 int signalindex = -1;
3297 for ( f = g->signals.first(); f; f = g->signals.next() ) {
3298 signalindex++;
3299 if ( f->type == "void" && f->args->isEmpty() ) {
3300 fprintf( out, " case %d: %s(); break;\n", signalindex, f->name.data() );
3301 continue;
3302 }
3303
3304 fprintf( out, " case %d: ", signalindex );
3305 bool hasReturnValue = FALSE;
3306 if ( f->type != "void" && validUType( f->type )) {
3307 hasReturnValue = TRUE;
3308 fprintf( out, "static_QUType_%s.set(_o,", uType(f->type).data() );
3309 }
3310 int offset = 0;
3311 fprintf( out, "%s(", f->name.data() );
3312 Argument* a = f->args->first();
3313 while ( a ) {
3314 QCString type = a->leftType + ' ' + a->rightType;
3315 type = type.simplifyWhiteSpace();
3316 fixRightAngles( &type );
3317 if ( validUType( type ) ) {
3318 QCString utype = uType( type );
3319 if ( utype == "ptr" || utype == "varptr" || utype == "enum" )
3320 fprintf( out, "(%s)static_QUType_%s.get(_o+%d)", type.data(), utype.data(), offset+1 );
3321 else
3322 fprintf( out, "(%s)static_QUType_%s.get(_o+%d)", type.data(), utype.data(), offset+1 );
3323 } else {
3324 QCString castType = castToUType( type );
3325 if(castType == type)
3326 fprintf( out, "(%s)(*((%s*)static_QUType_ptr.get(_o+%d)))", type.data(),
3327 castType.data(), offset+1 );
3328 else
3329 fprintf( out, "(%s)*((%s*)static_QUType_ptr.get(_o+%d))", type.data(),
3330 castType.data(), offset+1 );
3331 }
3332 a = f->args->next();
3333 if ( a )
3334 fprintf( out, "," );
3335 offset++;
3336 }
3337 fprintf( out, ")" );
3338 if ( hasReturnValue )
3339 fprintf( out, ")" );
3340 fprintf( out, "; break;\n" );
3341 }
3342 fprintf( out, " default:\n" );
3343 if ( !g->superClassName.isEmpty() && !isQObject )
3344 fprintf( out, "\treturn %s::qt_emit(_id,_o);\n",
3345 (const char *) purestSuperClassName() );
3346 else
3347 fprintf( out, "\treturn FALSE;\n" );
3348 fprintf( out, " }\n" );
3349 fprintf( out, " return TRUE;\n}\n" );
3350 } else {
3351 if ( !g->superClassName.isEmpty() && !isQObject )
3352 fprintf( out, " return %s::qt_emit(_id,_o);\n}\n",
3353 (const char *) purestSuperClassName() );
3354 else
3355 fprintf( out, " return FALSE;\n}\n" );
3356 }
3357
3358
3359 fprintf( out, "#ifndef QT_NO_PROPERTIES\n" );
3360//
3361// Generate internal qt_property() functions
3362//
3363
3364 fprintf( out, "\nbool %s::qt_property( int id, int f, QVariant* v)\n{\n", qualifiedClassName().data() );
3365
3366 if ( !g->props.isEmpty() ) {
3367 fprintf( out, " switch ( id - staticMetaObject()->propertyOffset() ) {\n" );
3368 int propindex = -1;
3369 bool need_resolve = FALSE;
3370
3371 for( QPtrListIterator<Property> it( g->props ); it.current(); ++it ){
3372 propindex ++;
3373 fprintf( out, " case %d: ", propindex );
3374 fprintf( out, "switch( f ) {\n" );
3375
3376 uint flag_break = 0;
3377 uint flag_propagate = 0;
3378
3379 if ( it.current()->setfunc ) {
3380 fprintf( out, "\tcase 0: %s(", it.current()->setfunc->name.data() );
3381 QCString type = it.current()->type.copy(); // detach on purpose
3382 if ( it.current()->oredEnum )
3383 type = it.current()->enumsettype;
3384 if ( type == "uint" )
3385 fprintf( out, "v->asUInt()" );
3386 else if ( type == "unsigned int" )
3387 fprintf( out, "(uint)v->asUInt()" );
3388 else if ( type == "QMap<QString,QVariant>" )
3389 fprintf( out, "v->asMap()" );
3390 else if ( type == "QValueList<QVariant>" )
3391 fprintf( out, "v->asList()" );
3392 else if ( type == "Q_LLONG" )
3393 fprintf( out, "v->asLongLong()" );
3394 else if ( type == "Q_ULLONG" )
3395 fprintf( out, "v->asULongLong()" );
3396 else if ( isVariantType( type ) ) {
3397 if ( type[0] == 'Q' )
3398 type = type.mid(1);
3399 else
3400 type[0] = toupper( type[0] );
3401 fprintf( out, "v->as%s()", type.data() );
3402 } else {
3403 fprintf( out, "(%s&)v->asInt()", type.data() );
3404 }
3405 fprintf( out, "); break;\n" );
3406
3407 } else if ( it.current()->override ) {
3408 flag_propagate |= 1 << (0+1);
3409 }
3410 if ( it.current()->getfunc ) {
3411 if ( it.current()->gspec == Property::Pointer )
3412 fprintf( out, "\tcase 1: if ( this->%s() ) *v = QVariant( %s*%s()%s ); break;\n",
3413 it.current()->getfunc->name.data(),
3414 !isVariantType( it.current()->type ) ? "(int)" : "",
3415 it.current()->getfunc->name.data(),
3416 it.current()->type == "bool" ? ", 0" : "" );
3417 else
3418 fprintf( out, "\tcase 1: *v = QVariant( %sthis->%s()%s ); break;\n",
3419 !isVariantType( it.current()->type ) ? "(int)" : "",
3420 it.current()->getfunc->name.data(),
3421 it.current()->type == "bool" ? ", 0" : "" );
3422 } else if ( it.current()->override ) {
3423 flag_propagate |= 1<< (1+1);
3424 }
3425
3426 if ( !it.current()->reset.isEmpty() )
3427 fprintf( out, "\tcase 2: this->%s(); break;\n", it.current()->reset.data() );
3428
3429 if ( it.current()->designable.isEmpty() )
3430 flag_propagate |= 1 << (3+1);
3431 else if ( it.current()->designable == "true" )
3432 flag_break |= 1 << (3+1);
3433 else if ( it.current()->designable != "false" )
3434 fprintf( out, "\tcase 3: return this->%s();\n", it.current()->designable.data() );
3435
3436 if ( it.current()->scriptable.isEmpty() )
3437 flag_propagate |= 1 << (4+1);
3438 else if ( it.current()->scriptable == "true" )
3439 flag_break |= 1 << (4+1);
3440 else if ( it.current()->scriptable != "false" )
3441 fprintf( out, "\tcase 4: return this->%s();\n", it.current()->scriptable.data() );
3442
3443 if ( it.current()->stored.isEmpty() )
3444 flag_propagate |= 1 << (5+1);
3445 else if ( it.current()->stored == "true" )
3446 flag_break |= 1 << (5+1);
3447 else if ( it.current()->stored != "false" )
3448 fprintf( out, "\tcase 5: return this->%s();\n", it.current()->stored.data() );
3449
3450 int i = 0;
3451 if ( flag_propagate != 0 ) {
3452 fprintf( out, "\t" );
3453 for ( i = 0; i <= 5; i++ ) {
3454 if ( flag_propagate & (1 << (i+1) ) )
3455 fprintf( out, "case %d: ", i );
3456 }
3457 if (!g->superClassName.isEmpty() && !isQObject ) {
3458 fprintf( out, "goto resolve;\n" );
3459 need_resolve = TRUE;
3460 } else {
3461 fprintf( out, " return FALSE;\n" );
3462 }
3463 }
3464 if ( flag_break != 0 ) {
3465 fprintf( out, "\t" );
3466 for ( i = 0; i <= 5; i++ ) {
3467 if ( flag_break & (1 << (i+1) ) )
3468 fprintf( out, "case %d: ", i );
3469 }
3470 fprintf( out, "break;\n");
3471 }
3472
3473 fprintf( out, "\tdefault: return FALSE;\n } break;\n" );
3474 }
3475 fprintf( out, " default:\n" );
3476 if ( !g->superClassName.isEmpty() && !isQObject )
3477 fprintf( out, "\treturn %s::qt_property( id, f, v );\n",
3478 (const char *) purestSuperClassName() );
3479 else
3480 fprintf( out, "\treturn FALSE;\n" );
3481 fprintf( out, " }\n" );
3482 fprintf( out, " return TRUE;\n" );
3483
3484 if ( need_resolve )
3485 fprintf( out, "resolve:\n return %s::qt_property( staticMetaObject()->resolveProperty(id), f, v );\n",
3486 (const char *) purestSuperClassName() );
3487 fprintf( out, "}\n" );
3488 } else {
3489 if ( !g->superClassName.isEmpty() && !isQObject )
3490 fprintf( out, " return %s::qt_property( id, f, v);\n}\n",
3491 (const char *) purestSuperClassName() );
3492 else
3493 fprintf( out, " return FALSE;\n}\n" );
3494 }
3495
3496 fprintf( out, "\nbool %s::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; }\n", qualifiedClassName().data() );
3497 fprintf( out, "#endif // QT_NO_PROPERTIES\n" );
3498}
3499
3500
3501ArgList *addArg( Argument *a ) // add argument to list
3502{
3503 if ( (!a->leftType.isEmpty() || !a->rightType.isEmpty() ) ) //filter out truely void arguments
3504 tmpArgList->append( a );
3505 return tmpArgList;
3506}
3507
3508void addEnum()
3509{
3510 // Avoid duplicates
3511 for( QPtrListIterator<Enum> lit( g->enums ); lit.current(); ++lit ) {
3512 if ( lit.current()->name == tmpEnum->name )
3513 {
3514 if ( displayWarnings )
3515 moc_err( "Enum %s defined twice.", (const char*)tmpEnum->name );
3516 }
3517 }
3518
3519 // Only look at types mentioned in Q_ENUMS and Q_SETS
3520 if ( g->qtEnums.contains( tmpEnum->name ) || g->qtSets.contains( tmpEnum->name ) )
3521 {
3522 g->enums.append( tmpEnum );
3523 if ( g->qtSets.contains( tmpEnum->name ) )
3524 tmpEnum->set = TRUE;
3525 else
3526 tmpEnum->set = FALSE;
3527 }
3528 else
3529 delete tmpEnum;
3530 tmpEnum = new Enum;
3531}
3532
3533void addMember( Member m )
3534{
3535 if ( skipFunc ) {
3536 tmpFunc->args = tmpArgList; // just to be sure
3537 delete tmpFunc;
3538 tmpArgList = new ArgList; // ugly but works
3539 tmpFunc = new Function;
3540 skipFunc = FALSE;
3541 return;
3542 }
3543
3544 tmpFunc->type = tmpFunc->type.simplifyWhiteSpace();
3545 tmpFunc->access = tmpAccess;
3546 tmpFunc->args = tmpArgList;
3547 tmpFunc->lineNo = lineNo;
3548
3549 for ( ;; ) {
3550 g->funcs.append( tmpFunc );
3551
3552 if ( m == SignalMember ) {
3553 g->signals.append( tmpFunc );
3554 break;
3555 } else {
3556 if ( m == SlotMember )
3557 g->slots.append( tmpFunc );
3558 // PropertyCandidateMember or SlotMember
3559 if ( !tmpFunc->name.isEmpty() && tmpFunc->access == Public )
3560 g->propfuncs.append( tmpFunc );
3561 if ( !tmpFunc->args || !tmpFunc->args->hasDefaultArguments() )
3562 break;
3563 tmpFunc = new Function( *tmpFunc );
3564 tmpFunc->args = tmpFunc->args->magicClone();
3565 }
3566 }
3567
3568 skipFunc = FALSE;
3569 tmpFunc = new Function;
3570 tmpArgList = new ArgList;
3571}
3572
3573void checkPropertyName( const char* ident )
3574{
3575 if ( ident[0] == '_' ) {
3576 moc_err( "Invalid property name '%s'.", ident );
3577 return;
3578 }
3579}
Note: See TracBrowser for help on using the repository browser.