[prev in list] [next in list] [prev in thread] [next in thread] 

List:       koffice
Subject:    Re: USE_QFD, moc & dcopidl
From:       Reginald Stadlbauer <reggie () troll ! no>
Date:       2000-01-18 22:48:00
[Download RAW message or body]

On Tue, 18 Jan 2000, David Faure wrote:
>On Tue, Jan 18, 2000 at 10:47:17PM +0100, Reginald Stadlbauer wrote:
>> On Tue, 18 Jan 2000, David Faure wrote:
>> >On Tue, Jan 18, 2000 at 10:26:25PM +0100, Werner Trobin wrote:
>> >> Hi!
>> >> 
>> >> It seems that these programs are a little bit broken at the
>> >> moment. moc is unable to handle killustrator/share/GObject.h
>> >> (some enums and structs) and dcopidl barfs on kspread and
>> >> kpresenter...
>> >
>> >coolo is working on dcopidl, and I reported the moc bug to both
>> >qt-bugs and kde-cvs ;)
>> >(and got a reply from Torben about him fixing it...)
>> 
>> According to this p4 log he did it sunday afternoon
>> 
>> -------------
>> weis  17:57:12
>> Ignore nested classes. Fixed a bug reported
>> by David Faure.
>> 
>> edit   main    src/moc/moc.l  #45
>> edit   main    src/moc/moc.y  #154
>> -------------
>
>Great. Reggie, can you apply the fix to qt-copy ?
>That would make killu compileable again.

I don't want to checkout qt-copy. I attached these two files.

-- 
Reggie

["moc.l" (text/english)]

/****************************************************************************
** $Id: //depot/qt/main/src/moc/moc.l#36 $
**
** Lexical analyzer for meta object compiler
**
** Created : 930417
**
** Copyright (C) 1993-1999 by Troll Tech AS.  All rights reserved.
**
** This file is part of the Qt GUI Toolkit.
**
** This file may be distributed under the terms of the Q Public License
** as defined by Troll Tech AS of Norway and appearing in the file
** LICENSE.QPL included in the packaging of this file.
**
** Licensees holding valid Qt Professional Edition licenses may use this
** file in accordance with the Qt Professional Edition License Agreement
** provided with the Qt Professional Edition.
**
** See http://www.troll.no/pricing.html or email sales@troll.no for
** information about the Professional Edition licensing, or see
** http://www.troll.no/qpl/ for QPL licensing information.
**
*****************************************************************************/

%{
#include "qstring.h"


#define input yyinput				// yyinput in C++

#define X if(lexDebug){fprintf(stderr,"LEX (%i) : %s\n",lineNo,yytext);};
#define Y if(lexDebug){fprintf(stderr,"LEX (%i) : %s\n",lineNo,yytext);};
// #define Y if(lexDebug){fprintf(stderr,"LEX (%i) : %s updates level to %i\n"\
//                                 ,lineNo,yytext,templLevel);};
#define Z if(lexDebug){fprintf(stderr,"LEX (%i) : skipped the string %s\"\n"\
                               ,lineNo,yytext);};
#define BEGIN_INSIDE


#define  linput() (c = input()) == '\n' ? (lineNo++,c) : c

#include <string.h>
#include <stdlib.h>

/* char c,c1; */
int classPLevel      = 1;  /* Depth of nested curly braces in IN_CLASS*/
int namespacePLevel  = 1;  /* Depth of nested curly braces in IN_NAMESPACE*/
int expLevel         = 1;  /* Depth of nested parentheses in IN_EXPR */
int fctLevel         = 1;  /* Depth of nested parentheses in IN_FCT */
int templLevel       = 1;  /* Depth of levels in IN_TEMPL_ARGS */

int lastState        = 0;  /* Remembers the state when a
                              MOC_SKIP_BEGIN is encountered */
int skipLevel        = 0; /* Depth of MOC_SKIP_BEGINs */


class QString;

extern void addExpressionChar( char );
extern void addExpressionString( char * );
extern void moc_warn( char *msg );
%}

%start OUTSIDE QT_DEF IN_CLASS IN_NAMESPACE IN_ENUM IN_EXPR IN_FCT IN_TEMPL_ARGS \
GIMME_SEMICOLON SKIP IN_PROPERTY

%%
<OUTSIDE>"class"		{ X;
				  BEGIN QT_DEF;
				  return CLASS; }
<OUTSIDE>"namespace"		{ X;
				  BEGIN QT_DEF;
				  return NAMESPACE; }
<OUTSIDE>"using"		{ X;
                                  BEGIN QT_DEF;
				  return USING; }
<OUTSIDE>"template"		{ X;
				  BEGIN QT_DEF;
				  return TEMPLATE; }
<QT_DEF>"signals"		{ X; return SIGNALS; }
<QT_DEF>"slots"			{ X; return SLOTS; }
<QT_DEF>"Q_PROPERTY"		{ X; return Q_PROPERTY; }

<IN_FCT>"{"			{ fctLevel++;Y; }
<IN_FCT>"}"			{ fctLevel--;Y;if (fctLevel==0){X;return '}';}}
<IN_CLASS>"{"			{ classPLevel++;Y; }
<IN_CLASS>"}"			{ classPLevel--;Y;if (classPLevel == 0)
                                                      {X;return '}';} }
<IN_CLASS>"public"		{ X;if( classPLevel == 1 ) return PUBLIC; }
<IN_CLASS>"protected"		{ X;if( classPLevel == 1 )return PROTECTED; }
<IN_CLASS>"private"		{ X;if( classPLevel == 1 )return PRIVATE; }
<IN_CLASS>"signals"		{ X;if( classPLevel == 1 )return SIGNALS; }
<IN_CLASS>"slots"		{ X;if( classPLevel == 1 )return SLOTS; }
<IN_CLASS>"enum"		{ X;if( classPLevel == 1 )return ENUM_IN_CLASS; }
<IN_CLASS>"Q_OBJECT"		{ X;if( classPLevel == 1 )return Q_OBJECT; }
<IN_CLASS>"Q_PROPERTY"		{ X;if( classPLevel == 1 )return Q_PROPERTY; }
<IN_CLASS>"Q_CLASSINFO"		{ X;if( classPLevel == 1 )return Q_CLASSINFO; }

<IN_NAMESPACE>"{"		{ namespacePLevel++;Y; }
<IN_NAMESPACE>"}"		{ namespacePLevel--;Y;if (namespacePLevel == 0)
                                                          {X;return '}';}}
<IN_NAMESPACE>"class" 		{ X;
                                  BEGIN QT_DEF;
				  return CLASS; }
<IN_NAMESPACE>"template"	{ X;
                                  BEGIN QT_DEF;
                                  return TEMPLATE; }
<IN_NAMESPACE>"namespace"	{ X;
				  BEGIN QT_DEF;
				  return NAMESPACE; }
<IN_NAMESPACE>"using"		{ X;
                                  BEGIN QT_DEF;
				  return USING; }

<QT_DEF>"Q_OBJECT"		{ X; return Q_OBJECT; }
<QT_DEF>"Q_CLASSINFO"		{ X;return Q_CLASSINFO; }

<IN_PROPERTY>"("		{ X; return '('; }
<IN_PROPERTY>","		{ X; return ','; }
<IN_PROPERTY>")"		{ X; return ')'; }
<IN_PROPERTY>"0"		{ X; return '0'; }

<IN_EXPR>"("			{ expLevel++;X; }
<IN_EXPR>")"			{ expLevel--;Y;if (expLevel == 0)
					{ X; BEGIN QT_DEF; return ')';} }
<IN_EXPR>"["			{ expLevel++;X; }
<IN_EXPR>"]"			{ expLevel--;X;if (expLevel == 0)
					{ X; BEGIN QT_DEF; return ']';} }
<IN_EXPR>","			{ if (expLevel == 0)
					{ X; BEGIN QT_DEF; return ',' ;} }
<IN_EXPR>";"			{ if (expLevel == 0)
					{ X; BEGIN QT_DEF; return ';' ;} }
<IN_ENUM>"("			{ expLevel++;X; }
<IN_ENUM>")"			{ expLevel--;X;if (expLevel == 0)
					{ X; BEGIN QT_DEF; return ')';} }
<IN_ENUM>"["			{ expLevel++;X; }
<IN_ENUM>"]"			{ expLevel--;X;if (expLevel == 0)
					{ X; BEGIN QT_DEF; return ']';} }
<IN_ENUM>","			{ if (expLevel == 0)
					{ X; BEGIN QT_DEF; return ',' ;} }
<IN_ENUM>";"			{ if (expLevel == 0)
					{ X; BEGIN QT_DEF; return ';' ;} }
<IN_ENUM>"}"			{ if (expLevel == 0)
					{ X; BEGIN QT_DEF; return '}' ;} }
<IN_TEMPL_ARGS>"<"		{ templLevel++;Y; }
<IN_TEMPL_ARGS>">"		{ templLevel--;Y;if (templLevel == 0)
					{ X; BEGIN QT_DEF; return '>';} }
<IN_TEMPL_ARGS>"("		{ templLevel++;Y; }
<IN_TEMPL_ARGS>")"		{ templLevel--;Y;if (templLevel == 0)
					{ X; BEGIN QT_DEF; return ')';} }
<IN_TEMPL_ARGS>"["		{ templLevel++;Y; }
<IN_TEMPL_ARGS>"]"		{ templLevel--;Y;if (templLevel == 0)
					{ X; BEGIN QT_DEF; return ']';} }
<QT_DEF>"friend"		{ X;return FRIEND; }
<QT_DEF>"typedef"		{ X;return TYPEDEF; }
<QT_DEF>"auto"			{ X;return AUTO; }
<QT_DEF>"register"		{ X;return REGISTER; }
<QT_DEF>"static"		{ X;return STATIC; }
<QT_DEF>"extern"		{ X;return EXTERN; }
<QT_DEF>"inline"		{ X;return INLINE; }
<QT_DEF>"virtual"		{ X;return VIRTUAL; }
<QT_DEF>"const"			{ X;return CONST; }
<QT_DEF>"volatile"		{ X;return VOLATILE; }
<QT_DEF>"char"			{ X;return CHAR; }
<QT_DEF>"short"			{ X;return SHORT; }
<QT_DEF>"int"			{ X;return INT; }
<QT_DEF>"long"			{ X;return LONG; }
<QT_DEF>"signed"		{ X;return SIGNED; }
<QT_DEF>"unsigned"		{ X;return UNSIGNED; }
<QT_DEF>"float"			{ X;return FLOAT; }
<QT_DEF>"double"		{ X;return DOUBLE; }
<QT_DEF>"void"			{ X;return VOID; }
<QT_DEF>"enum"			{ X;return ENUM; }
<QT_DEF>"class"			{ X;return CLASS; }
<QT_DEF>"struct"		{ X;return STRUCT; }
<QT_DEF>"union"			{ X;return UNION; }
<QT_DEF>"asm"			{ X;return ASM; }
<QT_DEF>"private"		{ X;return PRIVATE; }
<QT_DEF>"protected"		{ X;return PROTECTED; }
<QT_DEF>"public"		{ X;return PUBLIC; }
<QT_DEF>"operator"		{ X;return OPERATOR; }
<QT_DEF>"::"			{ X;return DBL_COLON; }
<QT_DEF>"..."			{ X;return TRIPLE_DOT; }
<QT_DEF>"template"		{ X;return TEMPLATE; }
<QT_DEF>"mutable"		{ X;return MUTABLE; }
<QT_DEF>"using"		        { X;return USING; }
<QT_DEF>"namespace"		{ X;return NAMESPACE; }

<QT_DEF>[_a-zA-Z][_a-zA-Z0-9]* {
			  X;
			  yylval.string = qstrdup(yytext);
			  return IDENTIFIER;
			}

<IN_PROPERTY>[_a-zA-Z][_a-zA-Z0-9]* {
			  X;
			  yylval.string = qstrdup(yytext);
			  return IDENTIFIER;
			}


<OUTSIDE>[_a-zA-Z][_a-zA-Z0-9]*  ;
<IN_CLASS>[_a-zA-Z][_a-zA-Z0-9]* ;
<IN_NAMESPACE>[_a-zA-Z][_a-zA-Z0-9]* ;

<OUTSIDE>\"[^"]*	{			/* discard strings */
			  if (yytext[yyleng - 1] == '\\') {
			    yymore();
			  }
			  else {
			    Z;
			    input();		/* discard the '"' */
			  }
			}

<IN_CLASS>\"[^"]*	{			/* discard strings */
			  if (yytext[yyleng - 1] == '\\') {
			    yymore();
			  }
			  else {
			    Z;
			    input();		/* discard the '"' */
			  }
			}

<IN_NAMESPACE>\"[^"]*	{			/* discard strings */
			  if (yytext[yyleng - 1] == '\\') {
			    yymore();
			  }
			  else {
			    Z;
			    input();		/* discard the '"' */
			  }
			}

<IN_FCT>\"[^"]*		{			/* discard strings */
			  if (yytext[yyleng - 1] == '\\') {
			    yymore();
			  }
			  else {
			    Z;
			    addExpressionString(yytext);
			    input();		/* discard the '"' */
			  }
			}


<IN_TEMPL_ARGS>\"[^"]*	  { if (yytext[yyleng - 1] == '\\') {
			      yymore();
			  }
			  else {
			      X;
			      addExpressionString(yytext);
			      input();		/* discard the '"' */
			      return STRING;
			 }
			}


<QT_DEF>\"[^"]*	     { if (yytext[yyleng - 1] == '\\') {
			      yymore();
			  }
			  else {
			      X;
			      yylval.string = qstrdup(yytext+1);
			      input();		/* discard the '"' */
			      return STRING;
			 }
			}


<IN_PROPERTY>\"[^"]*	     { if (yytext[yyleng - 1] == '\\') {
			      yymore();
			  }
			  else {
			      X;
			      yylval.string = qstrdup(yytext+1);
			      input();		/* discard the '"' */
			      return STRING;
			 }
			}


<QT_DEF>'.'	     { X;
			  yylval.char_val = yytext[1];
			  return CHAR_VAL;
			}

<QT_DEF>'\\a'	    { X;
			 yylval.char_val = '\a';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\b'	    { X;
			 yylval.char_val = '\b';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\f'	    { X;
			 yylval.char_val = '\f';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\n'	    { X;
			 yylval.char_val = '\n';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\r'	    { X;
			 yylval.char_val = '\r';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\t'	    { X;
			 yylval.char_val = '\t';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\v'	    { X;
			 yylval.char_val = '\v';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\\\'	    { X;
			 yylval.char_val = '\\';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\?'	    { X;
			 yylval.char_val = '\?';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\''	    { X;
			 yylval.char_val = '\'';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\\"'	    { X;
			 yylval.char_val = '\"';	/* " */
			 return CHAR_VAL;
		       }

<QT_DEF>'\\0'	    { X;
			 yylval.char_val = '\0';
			 return CHAR_VAL;
		       }

<QT_DEF>'\\[0-7]+'  { X;
			 yylval.char_val =
			   (char)strtol( &yytext[1], 0, 8 );
			 return CHAR_VAL;
		       }

<QT_DEF>'\\x[0-9a-fA-F]+' { X;
			 yylval.char_val =
			   (char)strtol( &yytext[2], 0, 16 );
			 return CHAR_VAL;
		       }

<QT_DEF>'\\.'	    { X;
			 yylval.char_val = ' ';
			 return CHAR_VAL;
		       }

<QT_DEF>[0-9]+	     { X;
			  yylval.int_val = atoi(yytext);
			  return INT_VAL;
			}

<QT_DEF>[0-9]+\.[0-9]* { X;
			  yylval.double_val = atof(yytext);
			  return DOUBLE_VAL;
			}

<QT_DEF>\.[0-9]+     { X;
			  yylval.double_val = atof(yytext);
			  return DOUBLE_VAL;
			}


^#define.*\\$		{ /* skip multi-line macro-definitions */
			  char c, c1;
			  input();   /* Discard the '\n'. */
			  do {
			      c1=' ';
			      while((c = linput()) != '\n' && c != 0) c1=c;
			      if (c == 0) break;
			  } while(c1=='\\');
			  unput(c);  /* put back the '\n' or the EOF */
			}

^[ \t]*#.*		{ /* preprocessor commands are skipped */}
"//"[^\n]*		{ /* C++ comment */
			  QCString s = yytext;
                          if ( s.contains( "MOC_SKIP_BEGIN" ) ) {
                            skipLevel++;
                            if ( skipLevel == 1 ) {
                              lastState = YYSTATE;
                              BEGIN SKIP;
                            }
                          } else
                          if ( s.contains( "MOC_SKIP_END" ) ) {
                            if ( skipLevel == 0 ) {
                              moc_warn(" MOC_SKIP_END without MOC_SKIP_BEGIN");
                            } else {
                              skipLevel--;
                              if ( skipLevel == 0 ) {
                                BEGIN lastState;
                              }
                            }
                          }
                        }
"/*"			{ /* C	 comment */
			  char c = ' ';
			  do {
			      if ( c!= '*' ) {
				  while((c = linput()) != '*' && c != 0)
				      ;
			      }
			      if (c == 0) break;
			  } while(((c = linput())) != '/' && c != 0);
			  if (c == 0)
			      unput(c);
			}

[ \t\r\b\f]+   		;
<IN_CLASS>.		;
<IN_NAMESPACE>.		;
<IN_FCT>.		;
<IN_EXPR>.		  { addExpressionChar( yytext[0] ); }
<IN_ENUM>.		  { addExpressionChar( yytext[0] ); }
<IN_TEMPL_ARGS>.	  { addExpressionChar( yytext[0] ); }
<IN_PROPERTY>.		  { return CHAR_VAL; }
<OUTSIDE>.		;
<SKIP>.		        ;
<QT_DEF>.		{
			  X;
			  return yytext[0];
			}
<GIMME_SEMICOLON>.	{
			  X;
			  return ';';
			}
\n			{
			  lineNo++;
			}


%%


["moc.y" (text/english)]

/****************************************************************************
** $Id: //depot/qt/main/src/moc/moc.y#125 $
**
** Parser and code generator for meta object compiler
**
** Created : 930417
**
** Copyright (C) 1993-1999 by Troll Tech AS.  All rights reserved.
**
** This file is part of the Qt GUI Toolkit.
**
** This file may be distributed under the terms of the Q Public License
** as defined by Troll Tech AS of Norway and appearing in the file
** LICENSE.QPL included in the packaging of this file.
**
** Licensees holding valid Qt Professional Edition licenses may use this
** file in accordance with the Qt Professional Edition License Agreement
** provided with the Qt Professional Edition.
**
** See http://www.troll.no/pricing.html or email sales@troll.no for
** information about the Professional Edition licensing, or see
** http://www.troll.no/qpl/ for QPL licensing information.
**
** --------------------------------------------------------------------------
**
** This compiler reads a C++ header file with class definitions and ouputs
** C++ code to build a meta class. The meta data includes public methods
** (not constructors, destructors or operator functions), signals and slot
** definitions. The output file should be compiled and linked into the
** target application.
**
** C++ header files are assumed to have correct syntax, and we are therefore
** doing less strict checking than C++ compilers.
**
** The C++ grammar has been adopted from the "The Annotated C++ Reference
** Manual" (ARM), by Ellis and Stroustrup (Addison Wesley, 1992).
**
** Notice that this code is not possible to compile with GNU bison, instead
** use standard AT&T yacc or Berkeley yacc.
*****************************************************************************/

%{
void yyerror( char *msg );

#include "qlist.h"
#include "qasciidict.h"
#include "qdict.h"
#include "qstrlist.h"
#include "qdatetime.h"
#include "qfile.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>



static QCString rmWS( const char * );

enum AccessPerm { _PRIVATE, _PROTECTED, _PUBLIC };


struct Argument					// single arg meta data
{
    Argument( char *left, char *right )
	{ leftType  = rmWS( left );
	  rightType = rmWS( right );
	  if ( leftType == "void" && rightType.isEmpty() )
	      leftType = "";
	}
    QCString leftType;
    QCString rightType;
};

class ArgList : public QList<Argument> {	// member function arg list
public:
    ArgList() { setAutoDelete( TRUE ); }
   ~ArgList() { clear(); }
};


struct Function					// member function meta data
{						//   used for signals and slots
    AccessPerm accessPerm;
    QCString    qualifier;			// const or volatile
    QCString    name;
    QCString    type;
    int	       lineNo;
    ArgList   *args;
    Function() { args=0; }
   ~Function() { delete args; }
};

class FuncList : public QList<Function> {	// list of member functions
public:
    FuncList( bool autoDelete = FALSE ) { setAutoDelete( autoDelete ); }

    FuncList find( const char* name )
    {
	FuncList result;
	for ( QListIterator<Function> it( *this); it.current(); ++it ) {
	    if ( it.current()->name == name )
		result.append( it.current() );
	}
	return result;
    }
};

class Enum : public QStrList
{
public:
    QCString name;
};

class EnumList : public QList<Enum> {		// list of property enums
public:
    EnumList() { setAutoDelete(TRUE); }
};


struct Property
{
    Property( int l, const char* t, const char* n, const char* s, const char* g)
	: lineNo(l), type(t), name(n), set(s), get(g), setfunc(0), getfunc(0),
	  sspec(Unspecified), gspec(Unspecified)
    {}

    int lineNo;
    QCString type;
    QCString name;
    QCString set;
    QCString get;

    Function* setfunc;
    Function* getfunc;

    enum Specification  { Unspecified, Class, Reference, Pointer, ConstCharStar };
    Specification sspec;
    Specification gspec;

    static const char* specToString( Specification s )
    {
	switch ( s ) {
	case Class:
	    return "Class";
	case Reference:
	    return "Reference";
	case Pointer:
	    return "Pointer";
	case ConstCharStar:
	    return "ConstCharStar";
	default:
	    return "Unspecified";
	}
    }
};

class PropList : public QList<Property> {	// list of properties
public:
    PropList() { setAutoDelete( TRUE ); }
};


struct ClassInfo
{
    ClassInfo( const char* n, const char* v )
	: name(n), value(v)
    {}
    QCString name;
    QCString value;
};

class ClassInfoList : public QList<ClassInfo> {	// list of class infos
public:
    ClassInfoList() { setAutoDelete( TRUE ); }
};


/*
  Attention!
  This table is copied from qvariant.cpp. If you change
  one, change both.
*/
static const int ntypes = 20;
static const char* type_map[ntypes] =
{
    0,
    "QMap<QString,QVariant>",
    "QValueList<QVariant>",
    "QString",
    "QStringList",
    "QFont",
    "QPixmap",
    "QBrush",
    "QRect",
    "QSize",
    "QColor",
    "QPalette",
    "QColorGroup",
    "QIconSet",
    "QPoint",
    "QImage",
    "int",
    "bool",
    "double",
    "QCString"
};

int qvariant_nameToType( const char* name )
{
    for ( int i = 0; i < ntypes; i++ ) {
	if ( !qstrcmp( type_map[i], name ) )
	    return i;
    }
    return 0;
}


ArgList *addArg( Argument * );			// add arg to tmpArgList

enum Member { SignalMember,
	      SlotMember,
	      PropertyCandidateMember,
	    };

void	 addMember( Member );			// add tmpFunc to current class
void     addEnum();				// add tmpEnum to current class

char	*strnew( const char * );		// returns a new string (copy)
char	*stradd( const char *, const char * );	// add two strings
char	*stradd( const char *, const char *,	// add three strings
			       const char * );
char	*straddSpc( const char *, const char * );
char	*straddSpc( const char *, const char *,
			       const char * );
char	*straddSpc( const char *, const char *,
		    const char *, const char * );

extern int yydebug;
bool	   lexDebug	   = FALSE;
int	   lineNo;				// current line number
bool	   errorControl	   = FALSE;		// controlled errors
bool	   displayWarnings = TRUE;
bool	   doEnums	   = TRUE;
bool	   skipClass;				// don't generate for class
bool	   skipFunc;				// don't generate for func
bool	   templateClass;			// class is a template
bool	   templateClassOld;			// previous class is a template

ArgList	  *tmpArgList;				// current argument list
Function  *tmpFunc;				// current member function
Enum      *tmpEnum;				// current enum
AccessPerm tmpAccessPerm;			// current access permission
AccessPerm subClassPerm;			// current access permission
bool	   Q_OBJECTdetected;			// TRUE if current class
						// contains the Q_OBJECT macro
bool	   Q_PROPERTYdetected;			// TRUE if current class
						// contains at least one Q_PROPERTY macro

// some temporary values
QCString   tmpExpression;
int	   tmpYYStart;

const int  formatRevision = 7;			// moc output format revision

%}


%union {
    char	char_val;
    int		int_val;
    double	double_val;
    char       *string;
    AccessPerm	access;
    Function   *function;
    ArgList    *arg_list;
    Argument   *arg;
}

%start declaration_seq

%token <char_val>	CHAR_VAL		/* value types */
%token <int_val>	INT_VAL
%token <double_val>	DOUBLE_VAL
%token <string>		STRING
%token <string>		IDENTIFIER		/* identifier string */

%token			FRIEND			/* declaration keywords */
%token			TYPEDEF
%token			AUTO
%token			REGISTER
%token			STATIC
%token			EXTERN
%token			INLINE
%token			VIRTUAL
%token			CONST
%token			VOLATILE
%token			CHAR
%token			SHORT
%token			INT
%token			LONG
%token			SIGNED
%token			UNSIGNED
%token			FLOAT
%token			DOUBLE
%token			VOID
%token			ENUM
%token			ENUM_IN_CLASS
%token			CLASS
%token			STRUCT
%token			UNION
%token			ASM
%token			PRIVATE
%token			PROTECTED
%token			PUBLIC
%token			OPERATOR
%token			DBL_COLON
%token			TRIPLE_DOT
%token			TEMPLATE
%token			NAMESPACE
%token			USING
%token			MUTABLE

%token			SIGNALS
%token			SLOTS
%token			Q_OBJECT
%token			Q_PROPERTY
%token			Q_CLASSINFO

%type  <string>		class_name
%type  <string>		template_class_name
%type  <string>		template_spec
%type  <string>		opt_base_spec

%type  <string>		base_spec
%type  <string>		base_list
%type  <string>		qt_macro_name
%type  <string>		base_specifier
%type  <access>		access_specifier
%type  <string>		fct_name
%type  <string>		type_name
%type  <string>		simple_type_names
%type  <string>		simple_type_name
%type  <string>		class_key
%type  <string>		complete_class_name
%type  <string>		qualified_class_name
%type  <string>		elaborated_type_specifier

%type  <arg_list>	argument_declaration_list
%type  <arg_list>	arg_declaration_list
%type  <arg_list>	arg_declaration_list_opt
%type  <string>		abstract_decl_opt
%type  <string>		abstract_decl
%type  <arg>		argument_declaration
%type  <string>		cv_qualifier_list_opt
%type  <string>		cv_qualifier_list
%type  <string>		cv_qualifier
%type  <string>		decl_specifiers
%type  <string>		decl_specifier
%type  <string>		decl_specs_opt
%type  <string>		decl_specs
%type  <string>		type_specifier
%type  <string>		declarator
%type  <string>		ptr_operator
%type  <string>		ptr_operators
%type  <string>		ptr_operators_opt
%type  <string>		prop_access_function

%%
declaration_seq:	  /* empty */
                        | declaration_seq declaration
			;

declaration:		  class_def
/* | template_declaration */
                        | namespace_def
                        | namespace_alias_def
                        | using_declaration
                        | using_directive
                        ;

namespace_def:            named_namespace_def
                        | unnamed_namespace_def
                        ;

named_namespace_def:      NAMESPACE
                          IDENTIFIER         { enterNameSpace($2); }
                          '{'                { BEGIN IN_NAMESPACE; }
                          namespace_body
                          '}'                { leaveNameSpace();
			                       selectOutsideClassState();
                                             }
                        ;

unnamed_namespace_def:    NAMESPACE          { enterNameSpace(); }
                          '{'                { BEGIN IN_NAMESPACE; }
                          namespace_body
                          '}'                { leaveNameSpace();
  			                       selectOutsideClassState();
			                     }
                        ;

namespace_body:           declaration_seq
                        ;

namespace_alias_def:      NAMESPACE IDENTIFIER '=' complete_class_name ';'
                                            { selectOutsideClassState(); }
                        ;


using_directive:          USING NAMESPACE   { selectOutsideClassState(); } /* Skip namespace */
                        ;

using_declaration:        USING IDENTIFIER  { selectOutsideClassState(); }
                        | USING DBL_COLON   { selectOutsideClassState(); }
                        ;

class_def:				      { initClass(); }
			  class_specifier ';' { generateClass();
			                        registerClassInNamespace();
						selectOutsideClassState(); }
			;


/***** r.17.1 (ARM p.387 ): Keywords	*****/

class_name:		  IDENTIFIER	      { $$ = $1; }
			| template_class_name { $$ = $1; }
			;

template_class_name:	  IDENTIFIER '<' template_args '>'
				   { $$ = stradd( $1, "<",
				     tmpExpression =
				     tmpExpression.stripWhiteSpace(), ">" ); }
			;

/*
   template_args skips all characters until it encounters a ">" (it
   handles and discards sublevels of parentheses).  Since the rule is
   empty it must be used with care!
*/

template_args:		  /* empty */		  { initExpression();
						    templLevel = 1;
						    BEGIN IN_TEMPL_ARGS; }
			;

/***** r.17.2 (ARM p.388): Expressions	*****/


/* const_expression skips all characters until it encounters either one
   of "]", ")" or "," (it handles and discards sublevels of parentheses).
   Since the rule is empty it must be used with care!
*/

const_expression:	   /* empty */		  { initExpression();
						    BEGIN IN_EXPR; }
			;

enumerator_expression:	   /* empty */		  { initExpression();
						    BEGIN IN_ENUM; }
			;

/***** r.17.3 (ARM p.391): Declarations *****/

decl_specifier:		  storage_class_specifier { $$ = ""; }
			| type_specifier	  { $$ = $1; }
			| fct_specifier		  { $$ = ""; }
			| FRIEND		  { skipFunc = TRUE; $$ = ""; }
			| TYPEDEF		  { skipFunc = TRUE; $$ = ""; }
			;

decl_specifiers:	  decl_specs_opt type_name decl_specs_opt
						  { $$ = straddSpc($1,$2,$3); }
			;

decl_specs_opt:			/* empty */	  { $$ = ""; }
			| decl_specs		  { $$ = $1; }
			;

decl_specs:		  decl_specifier	    { $$ = $1; }
			| decl_specs decl_specifier { $$ = straddSpc($1,$2); }
			;

storage_class_specifier:  AUTO
			| REGISTER
			| STATIC		{ skipFunc = TRUE; }
			| EXTERN
			;

fct_specifier:		  INLINE
			| VIRTUAL
			;

type_specifier:		  CONST			{ $$ = "const"; }
			| VOLATILE		{ $$ = "volatile"; }
			;

type_name:		  elaborated_type_specifier { $$ = $1; }
			| complete_class_name	    { $$ = $1; }
			| simple_type_names	    { $$ = $1; }
			;

simple_type_names:	  simple_type_names simple_type_name
						    { $$ = straddSpc($1,$2); }
			| simple_type_name	    { $$ = $1; }

simple_type_name:	  CHAR			    { $$ = "char"; }
			| SHORT			    { $$ = "short"; }
			| INT			    { $$ = "int"; }
			| LONG			    { $$ = "long"; }
			| SIGNED		    { $$ = "signed"; }
			| UNSIGNED		    { $$ = "unsigned"; }
			| FLOAT			    { $$ = "float"; }
			| DOUBLE		    { $$ = "double"; }
			| VOID			    { $$ = "void"; }
			;

template_spec:		  TEMPLATE '<' template_args '>'
				   { $$ = stradd( "template<",
				     tmpExpression =
				     tmpExpression.stripWhiteSpace(), ">" ); }
			;

opt_template_spec:	  /* empty */
			| template_spec		{ templateClassOld = templateClass;
						  templateClass = TRUE;
						}
			;


class_key:		  opt_template_spec CLASS	{ $$ = "class"; }
			| opt_template_spec STRUCT	{ $$ = "struct"; }
			;

complete_class_name:	  qualified_class_name	{ $$ = $1; }
			| DBL_COLON  qualified_class_name
						{ $$ = stradd( "::", $2 ); }
			;

qualified_class_name:	  qualified_class_name DBL_COLON class_name
						{ $$ = stradd( $1, "::", $3 );}
			| class_name		{ $$ = $1; }
			;

elaborated_type_specifier:
			  class_key IDENTIFIER	{ $$ = straddSpc($1,$2); }
			| ENUM IDENTIFIER	{ $$ = stradd("enum ",$2); }
			| UNION IDENTIFIER	{ $$ = stradd("union ",$2); }
			;

/***** r.17.4 (ARM p.393): Declarators	*****/

argument_declaration_list:  arg_declaration_list_opt triple_dot_opt { $$ = $1;}
			|   arg_declaration_list ',' TRIPLE_DOT	    { $$ = $1;
				       func_warn("Ellipsis not supported"
						 " in signals and slots.\n"
						 "Ellipsis argument ignored."); }
			;

arg_declaration_list_opt:	/* empty */	{ $$ = tmpArgList; }
			| arg_declaration_list	{ $$ = $1; }
			;

triple_dot_opt:			/* empty */
			| TRIPLE_DOT { func_warn("Ellipsis not supported"
						 " in signals and slots.\n"
						 "Ellipsis argument ignored."); }

			;

arg_declaration_list:	  arg_declaration_list
			  ','
			  argument_declaration	{ $$ = addArg($3); }
			| argument_declaration	{ $$ = addArg($1); }

argument_declaration:	  decl_specifiers abstract_decl_opt
				{ $$ = new Argument(straddSpc($1,$2),""); }
			| decl_specifiers abstract_decl_opt
			  '=' { expLevel = 1; }
			  const_expression
				{ $$ = new Argument(straddSpc($1,$2),""); }
			| decl_specifiers abstract_decl_opt dname
				abstract_decl_opt
				{ $$ = new Argument(straddSpc($1,$2),$4); }
			| decl_specifiers abstract_decl_opt dname
				abstract_decl_opt
			  '='	{ expLevel = 1; }
			  const_expression
				{ $$ = new Argument(straddSpc($1,$2),$4); }
			;


abstract_decl_opt:	  /* empty */		{ $$ = ""; }
			| abstract_decl		{ $$ = $1; }
			;

abstract_decl:		  abstract_decl ptr_operator
						{ $$ = straddSpc($1,$2); }
			| '['			{ expLevel = 1; }
			  const_expression ']'
				   { $$ = stradd( "[",
				     tmpExpression =
				     tmpExpression.stripWhiteSpace(), "]" ); }
			| abstract_decl '['	{ expLevel = 1; }
			  const_expression ']'
				   { $$ = stradd( $1,"[",
				     tmpExpression =
				     tmpExpression.stripWhiteSpace(),"]" ); }
			| ptr_operator		{ $$ = $1; }
			| '(' abstract_decl ')' { $$ = $2; }
			;

declarator:		  dname			{ $$ = ""; }
			| declarator ptr_operator
						{ $$ = straddSpc($1,$2);}
			| declarator '['	{ expLevel = 1; }
			  const_expression ']'
				   { $$ = stradd( $1,"[",
				     tmpExpression =
				     tmpExpression.stripWhiteSpace(),"]" ); }
			| '(' declarator ')'	{ $$ = $2; }
			;

dname:			  IDENTIFIER
			;

fct_decl:		  '('
			  argument_declaration_list
			  ')'
			  cv_qualifier_list_opt
			  ctor_initializer_opt
			  fct_body_or_semicolon
						{ tmpFunc->args	     = $2;
						  tmpFunc->qualifier = $4; }
			;

fct_name:		  IDENTIFIER		/* NOTE: simplified! */
			| IDENTIFIER array_decls
				{ func_warn("Variable as signal or slot."); }
			| IDENTIFIER '=' { expLevel=0; }
			  const_expression     /* probably const member */
						{ skipFunc = TRUE; }
			| IDENTIFIER array_decls '=' { expLevel=0; }
			  const_expression     /* probably const member */
						{ skipFunc = TRUE; }
			;


array_decls:		 '['			{ expLevel = 1; }
			  const_expression ']'
			| array_decls '['	 { expLevel = 1; }
			  const_expression ']'

			;

ptr_operators_opt:	   /* empty */		{ $$ = ""; }
			| ptr_operators		 { $$ = $1; }
			;

ptr_operators:		  ptr_operator		{ $$ = $1; }
			| ptr_operators ptr_operator { $$ = straddSpc($1,$2);}
			;

ptr_operator:		  '*' cv_qualifier_list_opt { $$ = straddSpc("*",$2);}
			| '&' cv_qualifier_list_opt { $$ = stradd("&",$2);}
/*!			| complete_class_name
			  DBL_COLON
			  '*'
			  cv_qualifier_list_opt { $$ = stradd($1,"::*",$4); }*/
			;

cv_qualifier_list_opt:		/* empty */	{ $$ = ""; }
			| cv_qualifier_list	{ $$ = $1; }
			;

cv_qualifier_list:	  cv_qualifier		{ $$ = $1; }
			| cv_qualifier_list cv_qualifier
						{ $$ = straddSpc($1,$2); }
			;

cv_qualifier:		  CONST			{ $$ = "const"; }
			| VOLATILE		{ $$ = "volatile"; }
			;

fct_body_or_semicolon:	  ';'
			| fct_body
			| '=' INT_VAL ';'   /* abstract func, INT_VAL = 0 */
			;

fct_body:		  '{' { BEGIN IN_FCT; fctLevel = 1;}
			  '}' { BEGIN QT_DEF; }
			;


/***** r.17.5 (ARM p.395): Class Declarations *****/

class_specifier:	  full_class_head
			  '{'			{ BEGIN IN_CLASS;
                                                  classPLevel = 1;
						}
			  opt_obj_member_list
			  '}'			{ BEGIN QT_DEF; } /*catch ';'*/
			| class_head		{ BEGIN QT_DEF;	  /* -- " -- */
						  skipClass = TRUE; }
			| class_head
			  '(' IDENTIFIER ')' /* Qt macro name */
						{ BEGIN QT_DEF; /* catch ';' */
						  skipClass = TRUE; }
			| template_spec whatever { skipClass = TRUE;
						  BEGIN GIMME_SEMICOLON; }
			;

whatever:		  IDENTIFIER
			| simple_type_name
			| type_specifier
			| storage_class_specifier
			| fct_specifier
			;


class_head:		  class_key
			  qualified_class_name	{ className = $2; }
			| class_key
			  IDENTIFIER		/* possible DLL EXPORT macro */
			  class_name		{ className = $3; }
			;

full_class_head:	  class_head
			  opt_base_spec		{ superclassName = $2; }
			;

nested_class_head:	  class_key
			  qualified_class_name
			  opt_base_spec		{ templateClass = templateClassOld; }

ctor_initializer_opt:		/* empty */
			| ctor_initializer
			;

ctor_initializer:	':' mem_initializer_list
			;

mem_initializer_list:	mem_initializer
			| mem_initializer ',' mem_initializer_list
			;

/* complete_class_name also represents IDENTIFIER */
mem_initializer:	complete_class_name '('	{ expLevel = 1; }
			const_expression ')'
			;


opt_base_spec:			/* empty */	{ $$ = 0; }
			| base_spec		{ $$ = $1; }
			;

opt_obj_member_list:		/* empty */
			| obj_member_list
			;

obj_member_list:	  obj_member_list obj_member_area
			| obj_member_area
			;


qt_access_specifier:	  access_specifier	{ tmpAccessPerm = $1; }
			| SLOTS	      { moc_err( "Missing access specifier"
						   " before \"slots:\"." ); }
			;

obj_member_area:	  qt_access_specifier	{ BEGIN QT_DEF; }
			  slot_area
			| SIGNALS		{ BEGIN QT_DEF; }
			  ':'  opt_signal_declarations
			| Q_OBJECT		{
			      if ( tmpAccessPerm )
				  moc_warn("Q_OBJECT is not in the private"
					   " section of the class.\n"
					   "Q_OBJECT is a macro that resets"
					   " access permission to \"private\".");
			      Q_OBJECTdetected = TRUE;
			  }
			| Q_PROPERTY { tmpYYStart = YY_START; BEGIN IN_PROPERTY; }
			  '(' IDENTIFIER ',' STRING ',' prop_access_function ',' prop_access_function ')'
				  {
				      checkIdentifier( $6 );
				      Q_PROPERTYdetected = TRUE;
				      props.append( new Property( lineNo, $4,$6,$10,$8) );
				      BEGIN tmpYYStart;
				  }
			  opt_property_candidates
			| Q_CLASSINFO { tmpYYStart = YY_START; BEGIN IN_PROPERTY; }
			  '(' STRING ',' STRING ')'
				  {
				      infos.append( new ClassInfo( $4, $6 ) );
				      BEGIN tmpYYStart;
				  }
			  opt_property_candidates
			| ENUM_IN_CLASS { BEGIN QT_DEF; }
			  enum_in_class_tail { BEGIN IN_CLASS;}
			  opt_semicolons
			;

slot_area:		  SIGNALS ':'	{ moc_err( "Signals cannot "
						 "have access specifiers" ); }
			| SLOTS	  ':' opt_slot_declarations
			| ':'		{ if ( tmpAccessPerm == _PUBLIC && Q_PROPERTYdetected )
                                                  BEGIN QT_DEF;
                                              else
                                                  BEGIN IN_CLASS;
					  suppress_func_warn = TRUE;
                                        }
			  opt_property_candidates
					{
					  suppress_func_warn = FALSE;
					}
			| IDENTIFIER	{ BEGIN IN_CLASS;
					   if ( classPLevel != 1 )
					       moc_warn( "unexpected access"
							 "specifier" );
					}
			;

opt_property_candidates:	  /*empty*/
				| property_candidate_declarations
			;

property_candidate_declarations:	  property_candidate_declarations property_candidate_declaration
					| property_candidate_declaration
				;

property_candidate_declaration:	signal_or_slot { addMember( PropertyCandidateMember ); }
				;

opt_signal_declarations:	/* empty */
			| signal_declarations
			;

signal_declarations:	  signal_declarations signal_declaration
			| signal_declaration
			;


signal_declaration:	  signal_or_slot	{ addMember( SignalMember ); }
			;

opt_slot_declarations:		/* empty */
			| slot_declarations
			;

slot_declarations:	  slot_declarations slot_declaration
			| slot_declaration
			;

slot_declaration:	  signal_or_slot		{ addMember( SlotMember ); }
			;

opt_semicolons:			/* empty */
			| opt_semicolons ';'
			;

base_spec:		  ':' base_list		{ $$=$2; }
			;

base_list		: base_list ',' base_specifier
			| base_specifier
			;

qt_macro_name:		  IDENTIFIER '(' IDENTIFIER ')'
					   { $$ = stradd( $1, "(", $3, ")" ); }
			| IDENTIFIER '(' simple_type_name ')'
					   { $$ = stradd( $1, "(", $3, ")" ); }
			;

base_specifier:		  complete_class_name			       {$$=$1;}
			| VIRTUAL access_specifier complete_class_name {$$=$3;}
			| VIRTUAL complete_class_name		       {$$=$2;}
			| access_specifier VIRTUAL complete_class_name {$$=$3;}
			| access_specifier complete_class_name	       {$$=$2;}
			| qt_macro_name				       {$$=$1;}
			| VIRTUAL access_specifier qt_macro_name       {$$=$3;}
			| VIRTUAL qt_macro_name			       {$$=$2;}
			| access_specifier VIRTUAL qt_macro_name       {$$=$3;}
			| access_specifier qt_macro_name	       {$$=$2;}
			;

access_specifier:	  PRIVATE		{ $$=_PRIVATE; }
			| PROTECTED		{ $$=_PROTECTED; }
			| PUBLIC		{ $$=_PUBLIC; }
			;

operator_name:		  decl_specs_opt IDENTIFIER ptr_operators_opt
			| decl_specs_opt simple_type_name ptr_operators_opt
			| '+'
			| '-'
			| '*'
			| '/'
			| '%'
			| '^'
			| '&'
			| '|'
			| '~'
			| '!'
			| '='
			| '<'
			| '>'
			| '+' '='
			| '-' '='
			| '*' '='
			| '/' '='
			| '%' '='
			| '^' '='
			| '&' '='
			| '|' '='
			| '~' '='
			| '!' '='
			| '=' '='
			| '<' '='
			| '>' '='
			| '<' '<'
			| '>' '>'
			| '<' '<' '='
			| '>' '>' '='
			| '&' '&'
			| '|' '|'
			| '+' '+'
			| '-' '-'
			| ','
			| '-' '>' '*'
			| '-' '>'
			| '(' ')'
			| '[' ']'
			;


opt_virtual:		  /* empty */
			| VIRTUAL
			;

type_and_name:		  type_name fct_name
						{ tmpFunc->type = $1;
						  tmpFunc->name = $2; }
			| fct_name
						{ tmpFunc->type = "int";
						  tmpFunc->name = $1;
				  if ( tmpFunc->name == className )
				      func_warn( "Constructors cannot be"
						 " signals or slots.");
						}
			| opt_virtual '~' fct_name
						{ tmpFunc->type = "void";
						  tmpFunc->name = "~";
						  tmpFunc->name += $3;
				       func_warn( "Destructors cannot be"
						  " signals or slots.");
						}
			| decl_specs type_name decl_specs_opt
			  ptr_operators_opt fct_name
						{
						    char *tmp =
							straddSpc($1,$2,$3,$4);
						    tmpFunc->type = rmWS(tmp);
						    delete tmp;
						    tmpFunc->name = $5; }
			| decl_specs type_name /* probably friend decl */
						{ skipFunc = TRUE; }
			| type_name ptr_operators fct_name
						{ tmpFunc->type =
						      straddSpc($1,$2);
						  tmpFunc->name = $3; }
			| type_name decl_specs ptr_operators_opt
			  fct_name
						{ tmpFunc->type =
						      straddSpc($1,$2,$3);
						  tmpFunc->name = $4; }
			| type_name OPERATOR operator_name
						{ operatorError();    }
			| OPERATOR operator_name
						{ operatorError();    }
			| decl_specs type_name decl_specs_opt
			  ptr_operators_opt OPERATOR operator_name
						{ operatorError();    }
			| type_name ptr_operators OPERATOR  operator_name
						{ operatorError();    }
			| type_name decl_specs ptr_operators_opt
			  OPERATOR  operator_name
						{ operatorError();    }
			;


signal_or_slot:		type_and_name fct_decl opt_semicolons
			| type_and_name opt_bitfield ';' opt_semicolons
				{ func_warn("Variable as signal or slot."); }
			| type_and_name opt_bitfield ','member_declarator_list
			  ';' opt_semicolons
				{ func_warn("Variable as signal or slot."); }
			| enum_specifier opt_identifier ';' opt_semicolons
				{ func_warn("Enum declaration as signal or"
					    " slot."); }
                        | USING complete_class_name ';' opt_semicolons
                                { func_warn("Using declaration as signal or"
					    " slot."); }
			| USING NAMESPACE complete_class_name ';' opt_semicolons
                                { func_warn("Using declaration as signal or"
					    " slot."); }
			| NAMESPACE IDENTIFIER '{'
                                { classPLevel++;
				  moc_err("Namespace declaration as signal or"
					  " slot."); }
 			| nested_class_head ';' opt_semicolons
 				{ func_warn("Class declaration as signal or slot.");}
 			| nested_class_head
 			  '{'   { func_warn("Class declaration as signal or slot.");
				  BEGIN IN_FCT; fctLevel=1;
				}
                          '}'  { BEGIN QT_DEF; }
			  ';' opt_semicolons
			;


member_declarator_list:	  member_declarator
			| member_declarator_list ',' member_declarator
			;

member_declarator:	  declarator
			| IDENTIFIER ':'	 { expLevel = 0; }
			  const_expression
			| ':'			 { expLevel = 0; }
			  const_expression
			;

opt_bitfield:		  /* empty */
			| ':'			 { expLevel = 0; }
			  const_expression
			;


enum_specifier:		  ENUM enum_tail
			;

/* optional final comma at the end of an enum list. Not really C++ but
some people still use it */
opt_komma:		  /*empty*/
			| ','
			;

enum_tail:		  IDENTIFIER '{'   enum_list opt_komma
			  '}'   { BEGIN QT_DEF;	
				  if ( tmpAccessPerm == _PUBLIC) {
				      tmpEnum->name = $1;
				      addEnum();
				  }
				}
			| '{'   enum_list opt_komma
			  '}'   { tmpEnum->clear();}
			;

opt_identifier:		  /* empty */
			| IDENTIFIER
			;

enum_in_class_tail:	  IDENTIFIER IDENTIFIER
			| enum_tail opt_identifier
			;

enum_list:		  /* empty */
			| enumerator
			| enum_list ',' enumerator
			;

enumerator:		  IDENTIFIER { if ( tmpAccessPerm == _PUBLIC) tmpEnum->append( $1 ); }
			| IDENTIFIER '=' { expLevel=0; }
			  enumerator_expression {  if ( tmpAccessPerm == _PUBLIC) tmpEnum->append( $1 );  }


prop_access_function:	  IDENTIFIER 	{ $$ = $1; }
			| '0'		{ $$ = ""; }
			;

%%

#if defined(_OS_WIN32_)
#include <io.h>
#undef isatty
extern "C" int hack_isatty( int )
{
    return 0;
}
#define isatty hack_isatty
#else
#include <unistd.h>
#endif

#include "lex.yy.c"

void 	  init();				// initialize
void 	  initClass();				// prepare for new class
void 	  generateClass();			// generate C++ code for class
void 	  initExpression();			// prepare for new expression
QCString  combinePath( const char *, const char * );

QCString  fileName;				// file name
QCString  outputFile;				// output file name
QCString  includeFile;				// name of #include file
QCString  includePath;				// #include file path
QCString  qtPath;				// #include qt file path
bool	  noInclude     = FALSE;		// no #include <filename>
bool	  generatedCode = FALSE;		// no code generated
bool	  mocError = FALSE;			// moc parsing error occurred
QCString  className;				// name of parsed class
QCString  superclassName;			// name of super class
FuncList  signals;				// signal interface
FuncList  slots;				// slots interface
FuncList  propfuncs;				// all possible property access functions
FuncList  funcs( TRUE );			// all parsed functions, including signals
EnumList  enums;				// enums used in properties
PropList  props;				// list of all properties
ClassInfoList	infos;				// list of all class infos



FILE  *out;					// output file

int yyparse();

void replace( char *s, char c1, char c2 );

int main( int argc, char **argv )
{
    bool autoInclude = TRUE;
    char *error	     = 0;
    qtPath = "";
    for ( int n=1; n<argc && error==0; n++ ) {
	QCString arg = argv[n];
	if ( arg[0] == '-' ) {			// option
	    QCString opt = &arg[1];
	    if ( opt[0] == 'o' ) {		// output redirection
		if ( opt[1] == '\0' ) {
		    if ( !(n < argc-1) ) {
			error = "Missing output-file name";
			break;
		    }
		    outputFile = argv[++n];
		} else
		    outputFile = &opt[1];
	    } else if ( opt == "i" ) {		// no #include statement
		noInclude   = TRUE;
		autoInclude = FALSE;
	    } else if ( opt[0] == 'f' ) {	// produce #include statement
		noInclude   = FALSE;
		autoInclude = FALSE;
		if ( opt[1] ) {			// -fsomething.h
		    includeFile = &opt[1];
		}
	    } else if ( opt[0] == 'p' ) {	// include file path
		if ( opt[1] == '\0' ) {
		    if ( !(n < argc-1) ) {
			error = "Missing path name for the -p option.";
			break;
		    }
		    includePath = argv[++n];
		} else {
		    includePath = &opt[1];
		}
	    } else if ( opt[0] == 'q' ) {	// qt include file path
		if ( opt[1] == '\0' ) {
		    if ( !(n < argc-1) ) {
			error = "Missing path name for the -q option.";
			break;
		    }
		    qtPath = argv[++n];
		} else {
		    qtPath = &opt[1];
		}
		replace(qtPath.data(),'\\','/');
		if ( qtPath.right(1) != "/" )
		    qtPath += '/';
	    } else if ( opt == "k" ) {		// don't stop on errors
		errorControl = TRUE;
	    } else if ( opt == "nw" ) {		// don't display warnings
		displayWarnings = FALSE;
	    } else if ( opt == "ne" ) {		// don't do enums
		doEnums = FALSE;
	    } else if ( opt == "ldbg" ) {	// lex debug output
		lexDebug = TRUE;
	    } else if ( opt == "ydbg" ) {	// yacc debug output
		yydebug = TRUE;
	    } else {
		error = "Invalid argument";
	    }
	} else {
	    if ( !fileName.isNull() )		// can handle only one file
		error	 = "Too many input files specified";
	    else
		fileName = arg.copy();
	}
    }

    if ( autoInclude ) {
	int ppos = fileName.findRev('.');
	if ( ppos != -1 && tolower( fileName[ppos + 1] ) == 'h' )
	    noInclude = FALSE;
	else
	    noInclude = TRUE;
    }
    if ( !fileName.isEmpty() && !outputFile.isEmpty() &&
	 includeFile.isEmpty() && includePath.isEmpty() ) {
	includeFile = combinePath(fileName,outputFile);
    }
    if ( includeFile.isEmpty() )
	includeFile = fileName.copy();
    if ( !includePath.isEmpty() ) {
	if ( includePath.right(1) != "/" )
	    includePath += '/';
	includeFile = includePath + includeFile;
    }
    if ( fileName.isNull() && !error ) {
	fileName = "standard input";
	yyin	 = stdin;
    } else if ( argc < 2 || error ) {		// incomplete/wrong args
	fprintf( stderr, "Qt meta object compiler\n" );
	if ( error )
	    fprintf( stderr, "moc: %s\n", error );
	fprintf( stderr, "Usage:  moc [options] <header-file>\n"
		 "\t-o file  Write output to file rather than stdout\n"
		 "\t-i       Do not generate an #include statement\n"
		 "\t-f[file] Force #include, optional file name\n"
		 "\t-p path  Path prefix for included file\n"
		 "\t-k       Do not stop on errors\n"
		 "\t-nw      Do not display warnings\n"
		 "\t-ne      Do not scan for enumeration declarations\n"
		 );
	return 1;
    } else {
	yyin = fopen( (const char *)fileName, "r" );
	if ( !yyin ) {
	    fprintf( stderr, "moc: %s: No such file\n", (const char*)fileName);
	    return 1;
	}
    }
    if ( !outputFile.isEmpty() ) {		// output file specified
	out = fopen( (const char *)outputFile, "w" );	// create output file
	if ( !out ) {
	    fprintf( stderr, "moc: Cannot create %s\n",
		     (const char*)outputFile );
	    return 1;
	}
    } else {					// use stdout
	out = stdout;
    }
    init();
    yyparse();
    fclose( yyin );
    if ( !outputFile.isNull() )
	fclose( out );

    if ( !generatedCode && displayWarnings && !mocError ) {
        fprintf( stderr, "%s:%d: Warning: %s\n", fileName.data(), 0,
		 "No relevant classes found. No output generated." );
    }

    slots.clear();
    signals.clear();
    propfuncs.clear();
    funcs.clear();
    infos.clear();
    props.clear();
    infos.clear();

    return mocError ? 1 : 0;
}

void replace( char *s, char c1, char c2 )
{
    if ( !s )
	return;
    while ( *s ) {
	if ( *s == c1 )
	    *s = c2;
	s++;
    }
}

/*
  This function looks at two file names and returns the name of the
  infile, with a path relative to outfile. Examples:
    /tmp/abc	/tmp/bcd	->	abc
    xyz/a/bc	xyz/b/ac	->	../a/bc
    /tmp/abc	xyz/klm		-)	/tmp/abc
 */

QCString combinePath( const char *infile, const char *outfile )
{
    QCString a = infile;  replace(a.data(),'\\','/');
    QCString b = outfile; replace(b.data(),'\\','/');
    a = a.stripWhiteSpace();
    b = b.stripWhiteSpace();
    QCString r;
    int i = 0;
    int ncommondirs = 0;
    while ( a[i] && a[i] == b[i] ) {
	if ( a[i] == '/' && i > 0 )
	    ncommondirs++;
	i++;
    }
    if ( ncommondirs > 0 ) {			// common base directory
	while ( i>=0 ) {
	    if ( a[i] == '/' && b[i] == '/' )
		break;
	    --i;
	}
	++i;
	a = &a[i];
	b = &b[i];
    } else {
	if ( (a[0] == '/') || (isalpha(a[0]) && a[1] == ':') )
	    return a;
	b = &b[i];
    }
    i = b.contains('/');
    while ( i-- > 0 )
	r += "../";
    r += a;
    return r;
}


#define getenv hack_getenv			// workaround for byac

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic