summaryrefslogtreecommitdiffstats
path: root/buildtools/lib/parsers/qmake
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit114a878c64ce6f8223cfd22d76a20eb16d177e5e (patch)
treeacaf47eb0fa12142d3896416a69e74cbf5a72242 /buildtools/lib/parsers/qmake
downloadtdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.tar.gz
tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'buildtools/lib/parsers/qmake')
-rw-r--r--buildtools/lib/parsers/qmake/FlexLexer.h205
-rw-r--r--buildtools/lib/parsers/qmake/Mainpage.dox16
-rw-r--r--buildtools/lib/parsers/qmake/Makefile.am31
-rw-r--r--buildtools/lib/parsers/qmake/location.hh145
-rw-r--r--buildtools/lib/parsers/qmake/position.hh142
-rw-r--r--buildtools/lib/parsers/qmake/qmake.ll237
-rw-r--r--buildtools/lib/parsers/qmake/qmake.yy430
-rw-r--r--buildtools/lib/parsers/qmake/qmake_lex.cpp2239
-rw-r--r--buildtools/lib/parsers/qmake/qmake_lex.h49
-rw-r--r--buildtools/lib/parsers/qmake/qmake_yacc.cpp1243
-rw-r--r--buildtools/lib/parsers/qmake/qmake_yacc.hpp418
-rw-r--r--buildtools/lib/parsers/qmake/qmakeast.cpp170
-rw-r--r--buildtools/lib/parsers/qmake/qmakeast.h236
-rw-r--r--buildtools/lib/parsers/qmake/qmakeastvisitor.cpp68
-rw-r--r--buildtools/lib/parsers/qmake/qmakeastvisitor.h46
-rw-r--r--buildtools/lib/parsers/qmake/qmakedriver.cpp113
-rw-r--r--buildtools/lib/parsers/qmake/qmakedriver.h55
-rw-r--r--buildtools/lib/parsers/qmake/stack.hh129
-rw-r--r--buildtools/lib/parsers/qmake/tests/Makefile.am21
-rw-r--r--buildtools/lib/parsers/qmake/tests/runner.cpp169
-rw-r--r--buildtools/lib/parsers/qmake/tests/viewer.cpp182
-rw-r--r--buildtools/lib/parsers/qmake/tests/viewer.h48
-rw-r--r--buildtools/lib/parsers/qmake/tests/viewer_main.cpp33
-rw-r--r--buildtools/lib/parsers/qmake/tests/viewerbase.ui250
24 files changed, 6675 insertions, 0 deletions
diff --git a/buildtools/lib/parsers/qmake/FlexLexer.h b/buildtools/lib/parsers/qmake/FlexLexer.h
new file mode 100644
index 00000000..1db844da
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/FlexLexer.h
@@ -0,0 +1,205 @@
+
+// -*-C++-*-
+// FlexLexer.h -- define interfaces for lexical analyzer classes generated
+// by flex
+
+// Copyright (c) 1993 The Regents of the University of California.
+// All rights reserved.
+//
+// This code is derived from software contributed to Berkeley by
+// Kent Williams and Tom Epperly.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+
+// Neither the name of the University nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+
+// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE.
+
+// This file defines FlexLexer, an abstract class which specifies the
+// external interface provided to flex C++ lexer objects, and yyFlexLexer,
+// which defines a particular lexer class.
+//
+// If you want to create multiple lexer classes, you use the -P flag
+// to rename each yyFlexLexer to some other xxFlexLexer. You then
+// include <FlexLexer.h> in your other sources once per lexer class:
+//
+// #undef yyFlexLexer
+// #define yyFlexLexer xxFlexLexer
+// #include <FlexLexer.h>
+//
+// #undef yyFlexLexer
+// #define yyFlexLexer zzFlexLexer
+// #include <FlexLexer.h>
+// ...
+
+#ifndef __FLEX_LEXER_H
+// Never included before - need to define base class.
+#define __FLEX_LEXER_H
+
+#include <iostream>
+# ifndef FLEX_STD
+# define FLEX_STD std::
+# endif
+
+extern "C++" {
+
+struct yy_buffer_state;
+typedef int yy_state_type;
+
+class FlexLexer {
+public:
+ virtual ~FlexLexer() { }
+
+ const char* YYText() const { return yytext; }
+ int YYLeng() const { return yyleng; }
+
+ virtual void
+ yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0;
+ virtual struct yy_buffer_state*
+ yy_create_buffer( FLEX_STD istream* s, int size ) = 0;
+ virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0;
+ virtual void yyrestart( FLEX_STD istream* s ) = 0;
+
+ virtual int yylex() = 0;
+
+ // Call yylex with new input/output sources.
+ int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 )
+ {
+ switch_streams( new_in, new_out );
+ return yylex();
+ }
+
+ // Switch to new input/output streams. A nil stream pointer
+ // indicates "keep the current one".
+ virtual void switch_streams( FLEX_STD istream* new_in = 0,
+ FLEX_STD ostream* new_out = 0 ) = 0;
+
+ int lineno() const { return yylineno; }
+
+ int debug() const { return yy_flex_debug; }
+ void set_debug( int flag ) { yy_flex_debug = flag; }
+
+protected:
+ char* yytext;
+ int yyleng;
+ int yylineno; // only maintained if you use %option yylineno
+ int yy_flex_debug; // only has effect with -d or "%option debug"
+};
+
+}
+#endif
+
+#if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce)
+// Either this is the first time through (yyFlexLexerOnce not defined),
+// or this is a repeated include to define a different flavor of
+// yyFlexLexer, as discussed in the flex man page.
+#define yyFlexLexerOnce
+
+extern "C++" {
+
+class yyFlexLexer : public FlexLexer {
+public:
+ // arg_yyin and arg_yyout default to the cin and cout, but we
+ // only make that assignment when initializing in yylex().
+ yyFlexLexer( FLEX_STD istream* arg_yyin = 0, FLEX_STD ostream* arg_yyout = 0 );
+
+ virtual ~yyFlexLexer();
+
+ void yy_switch_to_buffer( struct yy_buffer_state* new_buffer );
+ struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size );
+ void yy_delete_buffer( struct yy_buffer_state* b );
+ void yyrestart( FLEX_STD istream* s );
+
+ void yypush_buffer_state( struct yy_buffer_state* new_buffer );
+ void yypop_buffer_state(void);
+
+ virtual int yylex();
+ virtual void switch_streams( FLEX_STD istream* new_in, FLEX_STD ostream* new_out );
+
+protected:
+ virtual int LexerInput( char* buf, int max_size );
+ virtual void LexerOutput( const char* buf, int size );
+ virtual void LexerError( const char* msg );
+
+ void yyunput( int c, char* buf_ptr );
+ int yyinput();
+
+ void yy_load_buffer_state();
+ void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream* s );
+ void yy_flush_buffer( struct yy_buffer_state* b );
+
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int* yy_start_stack;
+
+ void yy_push_state( int new_state );
+ void yy_pop_state();
+ int yy_top_state();
+
+ yy_state_type yy_get_previous_state();
+ yy_state_type yy_try_NUL_trans( yy_state_type current_state );
+ int yy_get_next_buffer();
+
+ FLEX_STD istream* yyin; // input source for default LexerInput
+ FLEX_STD ostream* yyout; // output sink for default LexerOutput
+
+ // yy_hold_char holds the character lost when yytext is formed.
+ char yy_hold_char;
+
+ // Number of characters read into yy_ch_buf.
+ int yy_n_chars;
+
+ // Points to current character in buffer.
+ char* yy_c_buf_p;
+
+ int yy_init; // whether we need to initialize
+ int yy_start; // start state number
+
+ // Flag which is used to allow yywrap()'s to do buffer switches
+ // instead of setting up a fresh yyin. A bit of a hack ...
+ int yy_did_buffer_switch_on_eof;
+
+
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ struct yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */
+ void yyensure_buffer_stack(void);
+
+ // The following are not always needed, but may be depending
+ // on use of certain flex features (like REJECT or yymore()).
+
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ yy_state_type* yy_state_buf;
+ yy_state_type* yy_state_ptr;
+
+ char* yy_full_match;
+ int* yy_full_state;
+ int yy_full_lp;
+
+ int yy_lp;
+ int yy_looking_for_trail_begin;
+
+ int yy_more_flag;
+ int yy_more_len;
+ int yy_more_offset;
+ int yy_prev_more_offset;
+};
+
+}
+
+#endif
diff --git a/buildtools/lib/parsers/qmake/Mainpage.dox b/buildtools/lib/parsers/qmake/Mainpage.dox
new file mode 100644
index 00000000..7b2e2682
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/Mainpage.dox
@@ -0,0 +1,16 @@
+/**
+@mainpage The KDevelop QMake Parser
+
+This library contains qmake parser.
+
+<b>Link with</b>: -lkdevqmakeparser
+
+<b>Include path</b>: -I\$(kde_includes)/kdevelop/buildtools/parsers/qmake
+
+\section qmakeparseroverview Overview
+Here resides a parser for qmake .pro (.pri) files. This parser
+reads project files, builds an AST which then can be written
+back to the project file.
+
+*/
+
diff --git a/buildtools/lib/parsers/qmake/Makefile.am b/buildtools/lib/parsers/qmake/Makefile.am
new file mode 100644
index 00000000..fd80170c
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/Makefile.am
@@ -0,0 +1,31 @@
+# This directory collects some classes related to
+# project management for the sole purpose that they
+# can be shared between parts.
+
+#SUBDIRS = tests
+
+INCLUDES = -I$(top_srcdir)/lib/interfaces \
+ -I$(top_srcdir)/lib/interfaces/extensions -I$(top_srcdir)/lib/util -I$(top_srcdir)/lib/widgets/propeditor \
+ $(all_includes)
+METASOURCES = AUTO
+lib_LTLIBRARIES = libkdevqmakeparser.la
+libkdevqmakeparser_la_LDFLAGS = -no-undefined $(all_libraries) $(LIB_KIO)
+libkdevqmakeparser_la_SOURCES = qmake_lex.cpp qmake_yacc.cpp qmakeast.cpp \
+ qmakeastvisitor.cpp qmakedriver.cpp
+
+kdevelopbuildtoolsincludedir = $(includedir)/kdevelop/buildtools/parsers/qmake
+kdevelopbuildtoolsinclude_HEADERS = qmakeast.h qmakedriver.h qmakeastvisitor.h
+
+parser:
+ cd $(srcdir) ; \
+ bison -d qmake.yy -r all -k -t -oqmake_yacc.cpp ; \
+ flex -d -oqmake_lex.cpp qmake.ll
+
+EXTRA_DIST = qmake.yy qmake.ll
+
+DOXYGEN_REFERENCES = dcop interfaces kdecore kdefx kdeui khtml kmdi kio kjs kparts kutils
+DOXYGEN_PROJECTNAME = KDevelop QMake parser
+DOXYGEN_DOCDIRPREFIX = kdevparser
+include ../../../../Doxyfile.am
+
+noinst_HEADERS = qmake.ll qmake.yy qmake_lex.h
diff --git a/buildtools/lib/parsers/qmake/location.hh b/buildtools/lib/parsers/qmake/location.hh
new file mode 100644
index 00000000..4da36b8a
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/location.hh
@@ -0,0 +1,145 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Locations for Bison parsers in C++
+
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/**
+ ** \file location.hh
+ ** Define the QMake::location class.
+ */
+
+#ifndef BISON_LOCATION_HH
+# define BISON_LOCATION_HH
+
+# include <iostream>
+# include <string>
+# include "position.hh"
+
+namespace QMake
+{
+
+ /// Abstract a location.
+ class location
+ {
+ public:
+
+ /// Construct a location.
+ location ()
+ : begin (), end ()
+ {
+ }
+
+
+ /// Initialization.
+ inline void initialize (std::string* fn)
+ {
+ begin.initialize (fn);
+ end = begin;
+ }
+
+ /** \name Line and Column related manipulators
+ ** \{ */
+ public:
+ /// Reset initial location to final location.
+ inline void step ()
+ {
+ begin = end;
+ }
+
+ /// Extend the current location to the COUNT next columns.
+ inline void columns (unsigned int count = 1)
+ {
+ end += count;
+ }
+
+ /// Extend the current location to the COUNT next lines.
+ inline void lines (unsigned int count = 1)
+ {
+ end.lines (count);
+ }
+ /** \} */
+
+
+ public:
+ /// Beginning of the located region.
+ position begin;
+ /// End of the located region.
+ position end;
+ };
+
+ /// Join two location objects to create a location.
+ inline const location operator+ (const location& begin, const location& end)
+ {
+ location res = begin;
+ res.end = end.end;
+ return res;
+ }
+
+ /// Add two location objects.
+ inline const location operator+ (const location& begin, unsigned int width)
+ {
+ location res = begin;
+ res.columns (width);
+ return res;
+ }
+
+ /// Add and assign a location.
+ inline location& operator+= (location& res, unsigned int width)
+ {
+ res.columns (width);
+ return res;
+ }
+
+ /** \brief Intercept output stream redirection.
+ ** \param ostr the destination output stream
+ ** \param loc a reference to the location to redirect
+ **
+ ** Avoid duplicate information.
+ */
+ inline std::ostream& operator<< (std::ostream& ostr, const location& loc)
+ {
+ position last = loc.end - 1;
+ ostr << loc.begin;
+ if (last.filename
+ && (!loc.begin.filename
+ || *loc.begin.filename != *last.filename))
+ ostr << '-' << last;
+ else if (loc.begin.line != last.line)
+ ostr << '-' << last.line << '.' << last.column;
+ else if (loc.begin.column != last.column)
+ ostr << '-' << last.column;
+ return ostr;
+ }
+
+}
+
+#endif // not BISON_LOCATION_HH
diff --git a/buildtools/lib/parsers/qmake/position.hh b/buildtools/lib/parsers/qmake/position.hh
new file mode 100644
index 00000000..704f0df4
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/position.hh
@@ -0,0 +1,142 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Positions for Bison parsers in C++
+
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/**
+ ** \file position.hh
+ ** Define the QMake::position class.
+ */
+
+#ifndef BISON_POSITION_HH
+# define BISON_POSITION_HH
+
+# include <iostream>
+# include <string>
+
+namespace QMake
+{
+ /// Abstract a position.
+ class position
+ {
+ public:
+
+ /// Construct a position.
+ position ()
+ : filename (0), line (1), column (0)
+ {
+ }
+
+
+ /// Initialization.
+ inline void initialize (std::string* fn)
+ {
+ filename = fn;
+ line = 1;
+ column = 0;
+ }
+
+ /** \name Line and Column related manipulators
+ ** \{ */
+ public:
+ /// (line related) Advance to the COUNT next lines.
+ inline void lines (int count = 1)
+ {
+ column = 0;
+ line += count;
+ }
+
+ /// (column related) Advance to the COUNT next columns.
+ inline void columns (int count = 1)
+ {
+ int leftmost = 0;
+ int current = column;
+ if (leftmost <= current + count)
+ column += count;
+ else
+ column = 0;
+ }
+ /** \} */
+
+ public:
+ /// File name to which this position refers.
+ std::string* filename;
+ /// Current line number.
+ unsigned int line;
+ /// Current column number.
+ unsigned int column;
+ };
+
+ /// Add and assign a position.
+ inline const position&
+ operator+= (position& res, const int width)
+ {
+ res.columns (width);
+ return res;
+ }
+
+ /// Add two position objects.
+ inline const position
+ operator+ (const position& begin, const int width)
+ {
+ position res = begin;
+ return res += width;
+ }
+
+ /// Add and assign a position.
+ inline const position&
+ operator-= (position& res, const int width)
+ {
+ return res += -width;
+ }
+
+ /// Add two position objects.
+ inline const position
+ operator- (const position& begin, const int width)
+ {
+ return begin + -width;
+ }
+
+ /** \brief Intercept output stream redirection.
+ ** \param ostr the destination output stream
+ ** \param pos a reference to the position to redirect
+ */
+ inline std::ostream&
+ operator<< (std::ostream& ostr, const position& pos)
+ {
+ if (pos.filename)
+ ostr << *pos.filename << ':';
+ return ostr << pos.line << '.' << pos.column;
+ }
+
+}
+#endif // not BISON_POSITION_HH
diff --git a/buildtools/lib/parsers/qmake/qmake.ll b/buildtools/lib/parsers/qmake/qmake.ll
new file mode 100644
index 00000000..715d60b3
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmake.ll
@@ -0,0 +1,237 @@
+%{
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <stdlib.h>
+
+#define DONT_INCLUDE_FLEXLEXER
+
+#include "qmake_lex.h"
+
+/**
+@file qmake.ll
+QMake Lexer
+
+There are 3 types of identifiers recognized by this lexer:
+-id_simple: examples of such identifiers are qmake variables and scoped variables
+at the left of the operator in assignments (like "SOURCES" in "SOURCES+=foo.cpp goo.cpp");
+-id_list: those are "value list identifiers" at the right side in assignments
+(like "foo.cpp goo.cpp" in "SOURCES+=foo.cpp goo.cpp");
+-id_args: function arguments recognized as one identifier
+(example: ""${QMAKE_FILE} is intended only for Windows!""
+in "!win32-*:!wince-*:error("${QMAKE_FILE} is intended only for Windows!")" statements).
+.
+
+To recognize those identifiers two additional start conditions are used: list and funcargs.
+
+@note "Not" operator (!) is recognized as a part of an identifier. Linefeeds passed to
+the parser as NEWLINE tokens to preserve file structure but whitespaces are stripped
+so no indentation is preserved by this lexer (and parser).
+
+To debug this lexer, put the line below into the next flex file section.
+%option debug
+*/
+%}
+
+%option noyywrap
+%option yylineno
+%option c++
+%option yyclass="QMake::Lexer"
+
+%x vallist
+%x funcargs
+
+delim [ \t]
+ws {delim}+
+newline (\n|\r|\r\n)
+quote "\""
+var_value [^#\r\n\t ]*[^\r\n\t \\]
+quoted_var_value {quote}({var_value}|[\t ])({var_value}|[\t ])*{quote}
+letter [A-Za-z]
+digit [0-9]
+id_simple ({digit}|{letter}|\!|-|_|\*|\$)({letter}|{digit}|\||\!|-|_|\*|\$|\.|\+)*
+id_args [^\r\n]*\)
+number {digit}+
+comment #[^\r\n]*{newline}
+comment_cont (\\{ws}*#[^\r\n]*{newline}|#[^\r\n]*\\{newline})
+cont \\{ws}*{newline}
+
+%%
+<vallist><<EOF>> {
+ BEGIN(INITIAL);
+ return Parser::token::token::ENDOFFILE;
+}
+<INITIAL>{ws} {}
+
+<vallist>{ws} {
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::LIST_WS;
+}
+
+<vallist,INITIAL>{cont} {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::CONT;
+}
+
+<vallist,INITIAL>{comment_cont} {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::COMMENT_CONT;
+}
+
+{id_simple} {
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return (Parser::token::token::ID_SIMPLE);
+}
+
+<funcargs>{id_args} {
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ mylval->value = mylval->value.mid(0, mylval->value.length()-1);
+ unput(')');
+ BEGIN(INITIAL);
+ return (Parser::token::token::ID_ARGS);
+ }
+
+<vallist>{var_value} {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::VARIABLE_VALUE;
+}
+
+<vallist>{quoted_var_value} {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::QUOTED_VARIABLE_VALUE;
+}
+
+"=" {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::EQ;
+}
+
+"+=" {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::PLUSEQ;
+}
+
+"-=" {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::MINUSEQ;
+}
+
+"*=" {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::STAREQ;
+}
+
+"~=" {
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::TILDEEQ;
+}
+
+"{" {
+ return Parser::token::token::LCURLY;
+}
+
+":"{delim}*"{" {
+ return Parser::token::token::LCURLY;
+}
+
+"}" {
+ return Parser::token::token::RCURLY;
+}
+
+"(" {
+ BEGIN(funcargs);
+ return Parser::token::token::LBRACE;
+}
+
+<funcargs,INITIAL>")" {
+ BEGIN(INITIAL);
+ return Parser::token::token::RBRACE;
+}
+
+":" {
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::COLON;
+}
+
+
+<vallist>{ws}{newline} {
+ BEGIN(INITIAL);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ setLineEndingFromString( mylval->value );
+ return Parser::token::token::NEWLINE;
+}
+
+<vallist,INITIAL>{newline} {
+ BEGIN(INITIAL);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ setLineEndingFromString( mylval->value );
+ return Parser::token::token::NEWLINE;
+}
+
+<vallist,INITIAL>{comment} {
+ BEGIN(INITIAL);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return (Parser::token::token::COMMENT);
+}
+
+%%
+namespace QMake
+{
+ Lexer::Lexer( std::istream* argin, std::ostream* argout )
+ : yyFlexLexer(argin, argout), mylval(0), m_lineEnding(None)
+ {
+ }
+
+ int Lexer::yylex( QMake::Parser::semantic_type* yylval )
+ {
+ mylval = yylval;
+ return yylex();
+ }
+
+ void Lexer::setLineEndingFromString( const QString& str )
+ {
+ if( str.endsWith("\r\n") && m_lineEnding == None )
+ m_lineEnding = Windows;
+ else if ( str.endsWith("\r") && m_lineEnding == None )
+ m_lineEnding = MacOS;
+ else if ( m_lineEnding == None )
+ m_lineEnding = Unix;
+ }
+
+ Lexer::LineEnding Lexer::lineending()
+ {
+ return m_lineEnding;
+ }
+}
+
+int QMakelex( QMake::Parser::semantic_type* yylval, QMake::Lexer* lexer)
+{
+ return lexer->yylex( yylval );
+}
+
diff --git a/buildtools/lib/parsers/qmake/qmake.yy b/buildtools/lib/parsers/qmake/qmake.yy
new file mode 100644
index 00000000..9e6d378a
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmake.yy
@@ -0,0 +1,430 @@
+%{
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * Copyright (C) 2006 by Andreas Pakulat *
+ * apaku@gmx.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+/**
+@file qmake.yy
+QMake Parser
+
+Simple LALR parser which builds the syntax tree (see @ref QMake::AST).
+
+@todo Recognize comments after statements like:
+SOURCES = foo #regognize me
+
+@fixme Parser fails on files that do not end with a newline
+@fixme 1 shift/reduce conflict in "line_body" rule
+*/
+
+#include <qvaluestack.h>
+#include "qmakeast.h"
+#include <qregexp.h>
+
+#define YYSTYPE_IS_DECLARED
+
+namespace QMake
+{
+ class Lexer;
+
+/**
+The yylval type.
+*/
+struct Result {
+ Result(): node(0) {}
+
+ /**Type of semantic value for simple grammar rules.*/
+ QString value;
+ /**Type of semantic value for grammar rules which are parts of AST.*/
+ AST *node;
+ /**Type of semantic value for "multiline_values" grammar rule.
+ Each line of multiline value is stored as a string in the list.
+
+ For example we have in .pro file:
+ @code
+ SOURCE = foo1.cpp \
+ foo2.cpp \
+ foo3.cpp foo4.cpp
+ @endcode
+ The string list will be populated with three strings:
+ <pre>
+ foo1.cpp
+ foo2.cpp
+ foo3.cpp foo4.cpp
+ </pre>
+ */
+ QStringList values;
+ QString indent;
+};
+
+#define YYSTYPE Result
+typedef Result YYSTYPE;
+}
+
+extern int QMakelex( QMake::Result* yylval, QMake::Lexer* lexer );
+
+/**
+The stack to store ProjectAST pointers when a new child
+ProjectAST is created and filled with statements.
+
+Parser creates root ProjectAST for a .pro file, pushes it onto the stack and starts
+adding statements. Each statement is added as a child StatementAST to the ProjectAST
+currently on the top in the stack.
+
+When a scope or function scope statement is parsed, the child ProjectAST is created
+and pushed onto the stack. Therefore all statements which belong to the scope
+or function scope are added as childs to their direct parent (scope or function scope).
+*/
+//QValueStack<ProjectAST*> projects;
+
+/**
+The current depth of AST node is stored here.
+AST depth is important to know because automatic indentation can
+be easily implemented (the parser itself looses all information
+about indentation).
+*/
+// int depth = 0;
+
+/*
+To debug this parser, put the line below into the next bison file section.
+Don't forget to uncomment "yydebug = 1" line in qmakedriver.cpp.
+%debug
+*/
+%}
+
+%skeleton "lalr1.cc"
+%define "parser_class_name" "Parser"
+%name-prefix="QMake"
+%parse-param { QMake::Lexer* lexer }
+%parse-param { QValueStack<ProjectAST*>& projects }
+%parse-param { int depth }
+%lex-param { QMake::Lexer* lexer }
+%start project
+
+%token ID_SIMPLE
+%token EQ
+%token PLUSEQ
+%token MINUSEQ
+%token STAREQ
+%token TILDEEQ
+%token LBRACE
+%token RBRACE
+%token COLON
+%token NEWLINE
+%token COMMENT
+%token CONT
+%token COMMENT_CONT
+%token RCURLY
+%token LCURLY
+%token ID_ARGS
+%token QUOTED_VARIABLE_VALUE
+%token VARIABLE_VALUE
+%token LIST_WS
+%token ENDOFFILE
+%%
+
+project :
+ {
+ ProjectAST *projectAST = new ProjectAST();
+ projects.push(projectAST);
+ }
+ statements
+ ;
+
+statements : statements statement
+ {
+ projects.top()->addChildAST($<node>2);
+ $<node>2->setDepth(depth);
+ }
+ |
+ ;
+
+statement : variable_assignment
+ {
+ $<node>$ = $<node>1;
+ }
+ | scope
+ {
+ $<node>$ = $<node>1;
+ }
+ | function_call
+ {
+ $<node>$ = $<node>1;
+ }
+ | comment
+ {
+ $<node>$ = $<node>1;
+ }
+ | emptyline
+ {
+ $<node>$ = new NewLineAST();
+ }
+ ;
+
+variable_assignment : ID_SIMPLE operator multiline_values listws NEWLINE
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = $<value>1;
+ node->op = $<value>2;
+ node->values = $<values>3 ;
+ node->values.append( $<value>4 );
+ node->values.append( $<value>5 );
+ node->indent = $<indent>3;
+ $<node>$ = node;
+ }
+ | ID_SIMPLE operator multiline_values listws ENDOFFILE
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = $<value>1;
+ node->op = $<value>2;
+ node->values = $<values>3 ;
+ node->values.append( $<value>4 );
+ node->indent = $<indent>3;
+ $<node>$ = node;
+ }
+ | ID_SIMPLE operator multiline_values listws CONT
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = $<value>1;
+ node->op = $<value>2;
+ node->values = $<values>3 ;
+ node->values.append( $<value>4 );
+ node->values.append( $<value>5 );
+ node->indent = $<indent>3;
+ $<node>$ = node;
+ }
+ | ID_SIMPLE operator multiline_values listws COMMENT_CONT
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = $<value>1;
+ node->op = $<value>2;
+ node->values = $<values>3 ;
+ node->values.append( $<value>4 );
+ node->values.append( $<value>5 );
+ node->indent = $<indent>3;
+ $<node>$ = node;
+ }
+ | ID_SIMPLE operator listws NEWLINE
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = $<value>1;
+ node->op = $<value>2;
+ node->values.append( $<value>3 );
+ node->values.append( $<value>4 );
+ $<node>$ = node;
+ }
+ | ID_SIMPLE operator listws ENDOFFILE
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = $<value>1;
+ node->op = $<value>2;
+ node->values.append( $<value>3 );
+ $<node>$ = node;
+ }
+ | ID_SIMPLE operator listws COMMENT
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = $<value>1;
+ node->op = $<value>2;
+ node->values.append( $<value>3 );
+ node->values.append( $<value>4 );
+ $<node>$ = node;
+ }
+ | ID_SIMPLE operator multiline_values listws COMMENT
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = $<value>1;
+ node->op = $<value>2;
+ node->values = $<values>3;
+ node->values.append( $<value>4 );
+ node->values.append( $<value>5 );
+ node->indent = $<indent>3;
+ $<node>$ = node;
+ }
+ ;
+
+possible_value : variable_value | COMMENT_CONT | CONT
+
+multiline_values : multiline_values LIST_WS possible_value
+ {
+ $<values>$.append( $<value>2 );
+ $<values>$.append( $<value>3 );
+ }
+ | multiline_values variable_value
+ {
+ $<values>$.append( $<value>2 );
+ }
+ | multiline_values listws CONT listws possible_value
+ {
+ $<values>$.append( $<value>2 );
+ $<values>$.append( $<value>3 );
+ $<values>$.append( $<value>4 );
+ $<values>$.append( $<value>5 );
+ if( $<indent>4 != "" && $<indent>$ == "" )
+ $<indent>$ = $<indent>4;
+ }
+ | multiline_values listws COMMENT_CONT listws possible_value
+ {
+ $<values>$.append( $<value>2 );
+ $<values>$.append( $<value>3 );
+ $<values>$.append( $<value>4 );
+ $<values>$.append( $<value>5 );
+ if( $<indent>4 != "" && $<indent>$ == "" )
+ $<indent>$ = $<indent>4;
+ }
+ | listws possible_value
+ {
+ $<values>$ = QStringList();
+ $<values>$.append( $<value>1 );
+ $<values>$.append( $<value>2 );
+ }
+ ;
+
+
+variable_value : VARIABLE_VALUE { $<value>$ = $<value>1; }
+ | QUOTED_VARIABLE_VALUE { $<value>$ = $<value>1; }
+ ;
+
+
+listws: LIST_WS
+ {
+ $<value>$ = $<value>1;
+ $<indent>$ = $<value>1;
+ }
+ |
+ {
+ $<value>$ = QString();
+ $<indent>$ = QString();
+ }
+ ;
+operator : EQ
+ {
+ $<value>$ = $<value>1;
+ }
+ | PLUSEQ
+ {
+ $<value>$ = $<value>1;
+ }
+ | MINUSEQ
+ {
+ $<value>$ = $<value>1;
+ }
+ | STAREQ
+ {
+ $<value>$ = $<value>1;
+ }
+ | TILDEEQ
+ {
+ $<value>$ = $<value>1;
+ }
+ ;
+
+scope : ID_SIMPLE
+ {
+ ProjectAST *projectAST = new ProjectAST(ProjectAST::Scope);
+ projects.push(projectAST);
+ projects.top()->scopedID = $<value>1;
+ depth++;
+ }
+ scope_body
+ {
+ $<node>$ = projects.pop();
+ depth--;
+ }
+ ;
+
+function_call : ID_SIMPLE LBRACE function_args RBRACE
+ {
+ ProjectAST *projectAST = new ProjectAST(ProjectAST::FunctionScope);
+ projects.push(projectAST);
+ projects.top()->scopedID = $<value>1;
+ projects.top()->args = $<value>3;
+ depth++;
+
+ //qWarning("%s", $<value>1.ascii());
+ if ($<value>1.contains("include"))
+ {
+ IncludeAST *includeAST = new IncludeAST();
+ includeAST->projectName = $<value>3;
+ projects.top()->addChildAST(includeAST);
+ includeAST->setDepth(depth);
+ }
+ }
+ scope_body
+ else_statement
+ {
+ $<node>$ = projects.pop();
+ depth--;
+ }
+ ;
+
+function_args : ID_ARGS { $<value>$ = $<value>1; }
+ | { $<value>$ = ""; }
+ ;
+
+scope_body : LCURLY statements RCURLY
+ | COLON statement
+ {
+ projects.top()->addChildAST($<node>2);
+ $<node>2->setDepth(depth);
+ }
+ |
+ ;
+
+else_statement : "else" LCURLY
+ {
+ ProjectAST *projectAST = new ProjectAST(ProjectAST::FunctionScope);
+ projects.push(projectAST);
+ projects.top()->scopedID = "else";
+ projects.top()->args = "";
+ depth++;
+ }
+ scope_body RCURLY
+ {
+ $<node>$ = projects.pop();
+ depth--;
+ }
+ |
+ {
+ $<node>$ = new ProjectAST();
+ }
+ ;
+
+comment : COMMENT
+ {
+ CommentAST *node = new CommentAST();
+ node->comment = $<value>1;
+ $<node>$ = node;
+ }
+ ;
+
+emptyline : NEWLINE
+ ;
+
+%%
+
+
+namespace QMake
+{
+ void Parser::error(const location_type& /*l*/, const std::string& m)
+ {
+ std::cerr << m << std::endl;
+ }
+}
diff --git a/buildtools/lib/parsers/qmake/qmake_lex.cpp b/buildtools/lib/parsers/qmake/qmake_lex.cpp
new file mode 100644
index 00000000..b49677fe
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmake_lex.cpp
@@ -0,0 +1,2239 @@
+#line 2 "qmake_lex.cpp"
+
+#line 4 "qmake_lex.cpp"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* %if-c++-only */
+ /* The c++ scanner is a mess. The FlexLexer.h header file relies on the
+ * following macro. This is required in order to pass the c++-multiple-scanners
+ * test in the regression suite. We get reports that it breaks inheritance.
+ * We will address this in a future release of flex, or omit the C++ scanner
+ * altogether.
+ */
+ #define yyFlexLexer yyFlexLexer
+/* %endif */
+
+/* %if-c-only */
+/* %endif */
+
+/* %if-c-only */
+/* %endif */
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+/* %if-c-only */
+/* %endif */
+
+/* %if-tables-serialization */
+/* %endif */
+/* end standard C headers. */
+
+/* %if-c-or-c++ */
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+/* %endif */
+
+/* %if-c++-only */
+/* begin standard C++ headers. */
+#include <iostream>
+#include <errno.h>
+#include <cstdlib>
+#include <cstring>
+/* end standard C++ headers. */
+/* %endif */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* %not-for-header */
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+/* %ok-for-header */
+
+/* %not-for-header */
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+/* %ok-for-header */
+
+/* %if-reentrant */
+/* %endif */
+
+/* %if-not-reentrant */
+
+/* %endif */
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+/* %if-not-reentrant */
+extern int yyleng;
+/* %endif */
+
+/* %if-c-only */
+/* %if-not-reentrant */
+/* %endif */
+/* %endif */
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE yylex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-yylineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < yyleng; ++yyl )\
+ if ( yytext[yyl] == '\n' )\
+ --yylineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+/* %if-c-only */
+/* %endif */
+
+/* %if-c++-only */
+ std::istream* yy_input_file;
+/* %endif */
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* %if-c-only Standard (non-C++) definition */
+/* %not-for-header */
+
+/* %if-not-reentrant */
+/* %endif */
+/* %ok-for-header */
+
+/* %endif */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* %if-c-only Standard (non-C++) definition */
+/* %if-not-reentrant */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %endif */
+/* %endif */
+
+void *yyalloc (yy_size_t );
+void *yyrealloc (void *,yy_size_t );
+void yyfree (void * );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */
+/* Begin user sect3 */
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+
+#define FLEX_DEBUG
+
+typedef unsigned char YY_CHAR;
+
+#define yytext_ptr yytext
+#define YY_INTERACTIVE
+
+#include <FlexLexer.h>
+int yyFlexLexer::yylex()
+ {
+ LexerError( "yyFlexLexer::yylex invoked but %option yyclass used" );
+ return 0;
+ }
+
+#define YY_DECL int QMake::Lexer::yylex()
+
+/* %if-c-only Standard (non-C++) definition */
+/* %endif */
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+/* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+/* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\
+ (yy_c_buf_p) = yy_cp;
+
+/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
+#define YY_NUM_RULES 23
+#define YY_END_OF_BUFFER 24
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[76] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 24, 23, 1, 21,
+ 21, 5, 23, 17, 18, 5, 23, 5, 19, 9,
+ 23, 14, 16, 23, 7, 2, 7, 7, 23, 23,
+ 6, 1, 21, 5, 0, 22, 22, 0, 12, 10,
+ 11, 0, 15, 0, 3, 3, 0, 13, 7, 7,
+ 0, 2, 20, 20, 7, 0, 7, 0, 7, 0,
+ 6, 4, 4, 0, 4, 4, 7, 0, 7, 7,
+ 0, 0, 8, 0, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 5, 6, 7, 8, 1, 1, 1, 9,
+ 10, 11, 12, 1, 13, 14, 1, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 16, 1, 1,
+ 17, 1, 1, 1, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 1, 19, 1, 1, 20, 1, 18, 18, 18, 18,
+
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 21, 22, 23, 24, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[25] =
+ { 0,
+ 1, 2, 3, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[85] =
+ { 0,
+ 0, 0, 23, 41, 28, 30, 132, 289, 126, 289,
+ 123, 56, 32, 289, 289, 106, 105, 104, 35, 289,
+ 77, 289, 289, 103, 34, 55, 47, 69, 87, 108,
+ 106, 111, 289, 0, 79, 289, 96, 82, 289, 289,
+ 289, 44, 289, 0, 289, 90, 59, 289, 68, 289,
+ 85, 93, 289, 74, 105, 123, 141, 98, 99, 45,
+ 42, 289, 47, 105, 289, 36, 159, 177, 195, 213,
+ 108, 231, 249, 112, 289, 268, 271, 274, 27, 277,
+ 279, 281, 284, 286
+ } ;
+
+static yyconst flex_int16_t yy_def[85] =
+ { 0,
+ 75, 1, 76, 76, 77, 77, 75, 75, 75, 75,
+ 75, 75, 78, 75, 75, 12, 75, 12, 75, 75,
+ 75, 75, 75, 75, 79, 75, 80, 78, 79, 81,
+ 81, 75, 75, 12, 78, 75, 75, 78, 75, 75,
+ 75, 75, 75, 21, 75, 75, 82, 75, 79, 75,
+ 79, 75, 75, 75, 83, 84, 84, 80, 82, 81,
+ 81, 75, 75, 82, 75, 75, 83, 84, 83, 84,
+ 83, 84, 84, 84, 0, 75, 75, 75, 75, 75,
+ 75, 75, 75, 75
+ } ;
+
+static yyconst flex_int16_t yy_nxt[314] =
+ { 0,
+ 8, 9, 10, 11, 12, 8, 13, 12, 14, 15,
+ 16, 17, 18, 8, 12, 19, 20, 12, 21, 12,
+ 22, 8, 23, 24, 26, 10, 11, 49, 27, 28,
+ 8, 8, 8, 8, 36, 37, 42, 31, 65, 31,
+ 50, 29, 26, 10, 11, 42, 27, 28, 56, 62,
+ 38, 61, 51, 57, 61, 43, 52, 53, 54, 29,
+ 34, 65, 66, 34, 43, 58, 34, 34, 34, 34,
+ 34, 36, 37, 34, 50, 34, 53, 34, 44, 45,
+ 46, 36, 37, 47, 62, 63, 51, 38, 44, 45,
+ 46, 50, 45, 59, 52, 53, 54, 38, 36, 75,
+
+ 38, 65, 66, 51, 57, 51, 68, 65, 66, 75,
+ 69, 70, 32, 75, 70, 61, 58, 61, 68, 48,
+ 41, 40, 39, 71, 68, 33, 71, 32, 73, 68,
+ 74, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 75, 74, 68, 75, 75, 75, 73, 68, 75, 75,
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 74,
+ 68, 75, 75, 75, 69, 70, 75, 75, 75, 75,
+ 75, 75, 75, 75, 75, 75, 75, 71, 68, 75,
+ 75, 75, 73, 68, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75, 75, 75, 74, 68, 75, 75, 75,
+
+ 69, 70, 75, 75, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75, 71, 68, 75, 75, 75, 73, 68,
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 75, 74, 68, 75, 75, 75, 73, 68, 75, 75,
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 74,
+ 68, 75, 75, 75, 73, 68, 75, 75, 75, 75,
+ 75, 75, 75, 75, 75, 75, 75, 74, 25, 25,
+ 25, 30, 30, 30, 35, 35, 35, 55, 55, 60,
+ 60, 64, 64, 64, 67, 67, 72, 72, 7, 75,
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75
+ } ;
+
+static yyconst flex_int16_t yy_chk[314] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 3, 3, 79, 3, 3,
+ 5, 5, 6, 6, 13, 13, 19, 5, 66, 6,
+ 25, 3, 4, 4, 4, 42, 4, 4, 27, 63,
+ 13, 61, 25, 27, 60, 19, 26, 26, 26, 4,
+ 12, 47, 47, 12, 42, 27, 12, 12, 12, 12,
+ 12, 28, 28, 12, 49, 12, 54, 12, 21, 21,
+ 21, 35, 35, 21, 38, 38, 49, 28, 29, 29,
+ 29, 51, 46, 29, 52, 52, 52, 35, 37, 58,
+
+ 38, 59, 59, 51, 58, 29, 55, 64, 64, 71,
+ 55, 55, 32, 74, 71, 31, 58, 30, 74, 24,
+ 18, 17, 16, 55, 56, 11, 71, 9, 56, 56,
+ 74, 7, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 56, 57, 0, 0, 0, 57, 57, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 57,
+ 67, 0, 0, 0, 67, 67, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 67, 68, 0,
+ 0, 0, 68, 68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 68, 69, 0, 0, 0,
+
+ 69, 69, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 69, 70, 0, 0, 0, 70, 70,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 70, 72, 0, 0, 0, 72, 72, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,
+ 73, 0, 0, 0, 73, 73, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 73, 76, 76,
+ 76, 77, 77, 77, 78, 78, 78, 80, 80, 81,
+ 81, 82, 82, 82, 83, 83, 84, 84, 75, 75,
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[24] =
+ { 0,
+0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, };
+
+static yyconst flex_int16_t yy_rule_linenum[23] =
+ { 0,
+ 81, 83, 88, 94, 100, 105, 113, 119, 125, 131,
+ 137, 143, 149, 155, 159, 163, 167, 172, 177, 183,
+ 190, 197
+ } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "qmake.ll"
+#line 2 "qmake.ll"
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <stdlib.h>
+
+#define DONT_INCLUDE_FLEXLEXER
+
+#include "qmake_lex.h"
+
+/**
+@file qmake.ll
+QMake Lexer
+
+There are 3 types of identifiers recognized by this lexer:
+-id_simple: examples of such identifiers are qmake variables and scoped variables
+at the left of the operator in assignments (like "SOURCES" in "SOURCES+=foo.cpp goo.cpp");
+-id_list: those are "value list identifiers" at the right side in assignments
+(like "foo.cpp goo.cpp" in "SOURCES+=foo.cpp goo.cpp");
+-id_args: function arguments recognized as one identifier
+(example: ""${QMAKE_FILE} is intended only for Windows!""
+in "!win32-*:!wince-*:error("${QMAKE_FILE} is intended only for Windows!")" statements).
+.
+
+To recognize those identifiers two additional start conditions are used: list and funcargs.
+
+@note "Not" operator (!) is recognized as a part of an identifier. Linefeeds passed to
+the parser as NEWLINE tokens to preserve file structure but whitespaces are stripped
+so no indentation is preserved by this lexer (and parser).
+
+To debug this lexer, put the line below into the next flex file section.
+%option debug
+*/
+
+
+#line 657 "qmake_lex.cpp"
+
+#define INITIAL 0
+#define vallist 1
+#define funcargs 2
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+#include <unistd.h>
+/* %endif */
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* %if-c-only Reentrant structure and macros (non-C++). */
+/* %if-reentrant */
+/* %if-c-only */
+/* %endif */
+/* %if-reentrant */
+/* %endif */
+/* %if-bison-bridge */
+/* %endif */
+/* %endif End reentrant structures and macros. */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %endif */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+/* %if-c-only Standard (non-C++) definition */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %endif */
+#endif
+
+/* %if-c-only */
+/* %endif */
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* %if-c-only Standard (non-C++) definition */
+/* %endif */
+/* %if-c++-only C++ definition */
+#define ECHO LexerOutput( yytext, yyleng )
+/* %endif */
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\
+\
+/* %if-c++-only C++ definition \ */\
+ if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+/* %endif */
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+#define YY_FATAL_ERROR(msg) LexerError( msg )
+/* %endif */
+#endif
+
+/* %if-tables-serialization structures and prototypes */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %not-for-header */
+
+/* %tables-yydmap generated elements */
+/* %endif */
+/* end tables serialization structures and prototypes */
+
+/* %ok-for-header */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+/* %if-c-only Standard (non-C++) definition */
+/* %endif */
+/* %if-c++-only C++ definition */
+#define YY_DECL int yyFlexLexer::yylex()
+/* %endif */
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+/* %% [6.0] YY_RULE_SETUP definition goes here */
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/* %not-for-header */
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+/* %% [7.0] user's declarations go here */
+#line 76 "qmake.ll"
+
+#line 818 "qmake_lex.cpp"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! yyin )
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ yyin = & std::cin;
+/* %endif */
+
+ if ( ! yyout )
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ yyout = & std::cout;
+/* %endif */
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+ }
+
+ yy_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+/* %% [8.0] yymore()-related code goes here */
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of yytext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+/* %% [9.0] code to set up and find next match goes here */
+ yy_current_state = (yy_start);
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 76 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 289 );
+
+yy_find_action:
+/* %% [10.0] code to find the action number goes here */
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+/* %% [11.0] code for yylineno update goes here */
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ if ( yytext[yyl] == '\n' )
+
+ yylineno++;
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+/* %% [12.0] debug code goes here */
+ if ( yy_flex_debug )
+ {
+ if ( yy_act == 0 )
+ std::cerr << "--scanner backing up\n";
+ else if ( yy_act < 23 )
+ std::cerr << "--accepting rule at line " << yy_rule_linenum[yy_act] <<
+ "(\"" << yytext << "\")\n";
+ else if ( yy_act == 23 )
+ std::cerr << "--accepting default rule (\"" << yytext << "\")\n";
+ else if ( yy_act == 24 )
+ std::cerr << "--(end of buffer or a NUL)\n";
+ else
+ std::cerr << "--EOF (start condition " << YY_START << ")\n";
+ }
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+/* %% [13.0] actions go here */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case YY_STATE_EOF(vallist):
+#line 77 "qmake.ll"
+{
+ BEGIN(INITIAL);
+ return Parser::token::token::ENDOFFILE;
+}
+ YY_BREAK
+case 1:
+YY_RULE_SETUP
+#line 81 "qmake.ll"
+{}
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 83 "qmake.ll"
+{
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::LIST_WS;
+}
+ YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+#line 88 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::CONT;
+}
+ YY_BREAK
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+#line 94 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::COMMENT_CONT;
+}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 100 "qmake.ll"
+{
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return (Parser::token::token::ID_SIMPLE);
+}
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 105 "qmake.ll"
+{
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ mylval->value = mylval->value.mid(0, mylval->value.length()-1);
+ unput(')');
+ BEGIN(INITIAL);
+ return (Parser::token::token::ID_ARGS);
+ }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 113 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::VARIABLE_VALUE;
+}
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 119 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::QUOTED_VARIABLE_VALUE;
+}
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 125 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::EQ;
+}
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 131 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::PLUSEQ;
+}
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 137 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::MINUSEQ;
+}
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 143 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::STAREQ;
+}
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 149 "qmake.ll"
+{
+ BEGIN(vallist);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::TILDEEQ;
+}
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 155 "qmake.ll"
+{
+ return Parser::token::token::LCURLY;
+}
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 159 "qmake.ll"
+{
+ return Parser::token::token::LCURLY;
+}
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 163 "qmake.ll"
+{
+ return Parser::token::token::RCURLY;
+}
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 167 "qmake.ll"
+{
+ BEGIN(funcargs);
+ return Parser::token::token::LBRACE;
+}
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 172 "qmake.ll"
+{
+ BEGIN(INITIAL);
+ return Parser::token::token::RBRACE;
+}
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 177 "qmake.ll"
+{
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return Parser::token::token::COLON;
+}
+ YY_BREAK
+case 20:
+/* rule 20 can match eol */
+YY_RULE_SETUP
+#line 183 "qmake.ll"
+{
+ BEGIN(INITIAL);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ setLineEndingFromString( mylval->value );
+ return Parser::token::token::NEWLINE;
+}
+ YY_BREAK
+case 21:
+/* rule 21 can match eol */
+YY_RULE_SETUP
+#line 190 "qmake.ll"
+{
+ BEGIN(INITIAL);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ setLineEndingFromString( mylval->value );
+ return Parser::token::token::NEWLINE;
+}
+ YY_BREAK
+case 22:
+/* rule 22 can match eol */
+YY_RULE_SETUP
+#line 197 "qmake.ll"
+{
+ BEGIN(INITIAL);
+ mylval->value = QString::fromLocal8Bit( YYText(), YYLeng() );
+ return (Parser::token::token::COMMENT);
+}
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 203 "qmake.ll"
+ECHO;
+ YY_BREAK
+#line 1145 "qmake_lex.cpp"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(funcargs):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( yywrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+/* %ok-for-header */
+
+/* %if-c++-only */
+/* %not-for-header */
+
+yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout )
+{
+ yyin = arg_yyin;
+ yyout = arg_yyout;
+ yy_c_buf_p = 0;
+ yy_init = 0;
+ yy_start = 0;
+ yy_flex_debug = 0;
+ yylineno = 1; // this will only get updated if %option yylineno
+
+ yy_did_buffer_switch_on_eof = 0;
+
+ yy_looking_for_trail_begin = 0;
+ yy_more_flag = 0;
+ yy_more_len = 0;
+ yy_more_offset = yy_prev_more_offset = 0;
+
+ yy_start_stack_ptr = yy_start_stack_depth = 0;
+ yy_start_stack = NULL;
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+
+ yy_state_buf = 0;
+
+}
+
+void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out )
+{
+ if ( new_in )
+ {
+ yy_delete_buffer( YY_CURRENT_BUFFER );
+ yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) );
+ }
+
+ if ( new_out )
+ yyout = new_out;
+}
+
+#ifdef YY_INTERACTIVE
+int yyFlexLexer::LexerInput( char* buf, int /* max_size */ )
+#else
+int yyFlexLexer::LexerInput( char* buf, int max_size )
+#endif
+{
+ if ( yyin->eof() || yyin->fail() )
+ return 0;
+
+#ifdef YY_INTERACTIVE
+ yyin->get( buf[0] );
+
+ if ( yyin->eof() )
+ return 0;
+
+ if ( yyin->bad() )
+ return -1;
+
+ return 1;
+
+#else
+ (void) yyin->read( buf, max_size );
+
+ if ( yyin->bad() )
+ return -1;
+ else
+ return yyin->gcount();
+#endif
+}
+
+void yyFlexLexer::LexerOutput( const char* buf, int size )
+{
+ (void) yyout->write( buf, size );
+}
+/* %ok-for-header */
+
+/* %endif */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+int yyFlexLexer::yy_get_next_buffer()
+/* %endif */
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+/* %if-c-only */
+/* %not-for-header */
+
+/* %endif */
+/* %if-c++-only */
+ yy_state_type yyFlexLexer::yy_get_previous_state()
+/* %endif */
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+/* %% [15.0] code to get the start state into yy_current_state goes here */
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+/* %% [16.0] code to find the next state goes here */
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 76 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state )
+/* %endif */
+{
+ register int yy_is_jam;
+ /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */
+ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 76 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 75);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yyunput( int c, register char* yy_bp)
+/* %endif */
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up yytext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+/* %% [18.0] update yylineno here */
+
+ if ( c == '\n' ){
+ --yylineno;
+ }
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+/* %if-c-only */
+/* %endif */
+
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ int yyFlexLexer::yyinput()
+/* %endif */
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+/* %% [19.0] update BOL and yylineno */
+ if ( c == '\n' )
+
+ yylineno++;
+;
+
+ return c;
+}
+/* %if-c-only */
+/* %endif */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yyrestart( std::istream* input_file )
+/* %endif */
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+ }
+
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file );
+ yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+/* %endif */
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yy_load_buffer_state()
+/* %endif */
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size )
+/* %endif */
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b )
+/* %endif */
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf );
+
+ yyfree((void *) b );
+}
+
+/* %if-c-only */
+/* %endif */
+
+/* %if-c++-only */
+
+extern "C" int isatty (int );
+
+/* %endif */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream* file )
+/* %endif */
+
+{
+ int oerrno = errno;
+
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ b->yy_is_interactive = 0;
+/* %endif */
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b )
+/* %endif */
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/* %if-c-or-c++ */
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer)
+/* %endif */
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+/* %endif */
+
+/* %if-c-or-c++ */
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+void yyFlexLexer::yypop_buffer_state (void)
+/* %endif */
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+/* %endif */
+
+/* %if-c-or-c++ */
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+void yyFlexLexer::yyensure_buffer_stack(void)
+/* %endif */
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+/* %endif */
+
+/* %if-c-only */
+/* %endif */
+
+/* %if-c-only */
+/* %endif */
+
+/* %if-c-only */
+/* %endif */
+
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yy_push_state( int new_state )
+/* %endif */
+{
+ if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) )
+ {
+ yy_size_t new_size;
+
+ (yy_start_stack_depth) += YY_START_STACK_INCR;
+ new_size = (yy_start_stack_depth) * sizeof( int );
+
+ if ( ! (yy_start_stack) )
+ (yy_start_stack) = (int *) yyalloc(new_size );
+
+ else
+ (yy_start_stack) = (int *) yyrealloc((void *) (yy_start_stack),new_size );
+
+ if ( ! (yy_start_stack) )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START;
+
+ BEGIN(new_state);
+}
+
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ void yyFlexLexer::yy_pop_state()
+/* %endif */
+{
+ if ( --(yy_start_stack_ptr) < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN((yy_start_stack)[(yy_start_stack_ptr)]);
+}
+
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+ int yyFlexLexer::yy_top_state()
+/* %endif */
+{
+ return (yy_start_stack)[(yy_start_stack_ptr) - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+void yyFlexLexer::LexerError( yyconst char msg[] )
+{
+ std::cerr << msg << std::endl;
+ exit( YY_EXIT_FAILURE );
+}
+/* %endif */
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/* %if-c-only */
+/* %if-reentrant */
+/* %endif */
+/* %if-reentrant */
+/* %endif */
+/* %endif */
+
+/* %if-reentrant */
+/* %if-bison-bridge */
+/* %endif */
+/* %endif */
+
+/* %if-c-only */
+/* %endif */
+
+/* %if-c-or-c++ */
+/* %if-c-only */
+/* %endif */
+/* %if-c++-only */
+yyFlexLexer::~yyFlexLexer()
+/* %endif */
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer( YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+/* %if-c++-only */
+ delete [] (yy_state_buf);
+ yyfree((yy_start_stack) );
+/* %endif */
+
+/* %if-c-only */
+/* %if-reentrant */
+/* %endif */
+/* %endif */
+}
+/* %endif */
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+/* %if-tables-serialization definitions */
+/* %define-yytables The name for this specific scanner's tables. */
+#define YYTABLES_NAME "yytables"
+/* %endif */
+
+/* %ok-for-header */
+
+#line 203 "qmake.ll"
+
+
+namespace QMake
+{
+ Lexer::Lexer( std::istream* argin, std::ostream* argout )
+ : yyFlexLexer(argin, argout), mylval(0), m_lineEnding(None)
+ {
+ }
+
+ int Lexer::yylex( QMake::Parser::semantic_type* yylval )
+ {
+ mylval = yylval;
+ return yylex();
+ }
+
+ void Lexer::setLineEndingFromString( const QString& str )
+ {
+ if( str.endsWith("\r\n") && m_lineEnding == None )
+ m_lineEnding = Windows;
+ else if ( str.endsWith("\r") && m_lineEnding == None )
+ m_lineEnding = MacOS;
+ else if ( m_lineEnding == None )
+ m_lineEnding = Unix;
+ }
+
+ Lexer::LineEnding Lexer::lineending()
+ {
+ return m_lineEnding;
+ }
+}
+
+int QMakelex( QMake::Parser::semantic_type* yylval, QMake::Lexer* lexer)
+{
+ return lexer->yylex( yylval );
+}
+
+
diff --git a/buildtools/lib/parsers/qmake/qmake_lex.h b/buildtools/lib/parsers/qmake/qmake_lex.h
new file mode 100644
index 00000000..1b91e747
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmake_lex.h
@@ -0,0 +1,49 @@
+/* KDevelop QMake Support
+ *
+ * Copyright 2007 Andreas Pakulat <apaku@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef QMAKE_LEX_H
+#define QMAKE_LEX_H
+
+#include "qmake_yacc.hpp"
+#include <iostream>
+
+#ifndef DONT_INCLUDE_FLEXLEXER
+#include "FlexLexer.h"
+#endif
+
+namespace QMake
+{
+ class Lexer : public yyFlexLexer
+ {
+ public:
+ enum LineEnding{ None, Unix, MacOS, Windows };
+ Lexer( std::istream* argin = 0, std::ostream* argout = 0 );
+ int yylex( QMake::Parser::semantic_type* yylval );
+ int yylex();
+ void setLineEndingFromString( const QString& );
+ LineEnding lineending();
+ private:
+ QMake::Parser::semantic_type* mylval;
+ LineEnding m_lineEnding;
+ };
+}
+
+#endif
+
+// kate: space-indent on; indent-width 4; tab-width: 4; replace-tabs on; auto-insert-doxygen on
diff --git a/buildtools/lib/parsers/qmake/qmake_yacc.cpp b/buildtools/lib/parsers/qmake/qmake_yacc.cpp
new file mode 100644
index 00000000..9cd09ebe
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmake_yacc.cpp
@@ -0,0 +1,1243 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison LALR(1) parsers in C++
+
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+// Take the name prefix into account.
+#define yylex QMakelex
+
+#include "qmake_yacc.hpp"
+
+/* User implementation prologue. */
+
+
+/* Line 317 of lalr1.cc. */
+#line 45 "qmake_yacc.cpp"
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* FIXME: INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#define YYUSE(e) ((void) (e))
+
+/* A pseudo ostream that takes yydebug_ into account. */
+# define YYCDEBUG \
+ for (bool yydebugcond_ = yydebug_; yydebugcond_; yydebugcond_ = false) \
+ (*yycdebug_)
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug_) \
+ { \
+ *yycdebug_ << Title << ' '; \
+ yy_symbol_print_ ((Type), (Value), (Location)); \
+ *yycdebug_ << std::endl; \
+ } \
+} while (false)
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug_) \
+ yy_reduce_print_ (Rule); \
+} while (false)
+
+# define YY_STACK_PRINT() \
+do { \
+ if (yydebug_) \
+ yystack_print_ (); \
+} while (false)
+
+#else /* !YYDEBUG */
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_REDUCE_PRINT(Rule)
+# define YY_STACK_PRINT()
+
+#endif /* !YYDEBUG */
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+namespace QMake
+{
+#if YYERROR_VERBOSE
+
+ /* Return YYSTR after stripping away unnecessary quotes and
+ backslashes, so that it's suitable for yyerror. The heuristic is
+ that double-quoting is unnecessary unless the string contains an
+ apostrophe, a comma, or backslash (other than backslash-backslash).
+ YYSTR is taken from yytname. */
+ std::string
+ Parser::yytnamerr_ (const char *yystr)
+ {
+ if (*yystr == '"')
+ {
+ std::string yyr = "";
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ yyr += *yyp;
+ break;
+
+ case '"':
+ return yyr;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ return yystr;
+ }
+
+#endif
+
+ /// Build a parser object.
+ Parser::Parser (QMake::Lexer* lexer_yyarg, QValueStack<ProjectAST*>& projects_yyarg, int depth_yyarg)
+ : yydebug_ (false),
+ yycdebug_ (&std::cerr),
+ lexer (lexer_yyarg),
+ projects (projects_yyarg),
+ depth (depth_yyarg)
+ {
+ }
+
+ Parser::~Parser ()
+ {
+ }
+
+#if YYDEBUG
+ /*--------------------------------.
+ | Print this symbol on YYOUTPUT. |
+ `--------------------------------*/
+
+ inline void
+ Parser::yy_symbol_value_print_ (int yytype,
+ const semantic_type* yyvaluep, const location_type* yylocationp)
+ {
+ YYUSE (yylocationp);
+ YYUSE (yyvaluep);
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ }
+
+
+ void
+ Parser::yy_symbol_print_ (int yytype,
+ const semantic_type* yyvaluep, const location_type* yylocationp)
+ {
+ *yycdebug_ << (yytype < yyntokens_ ? "token" : "nterm")
+ << ' ' << yytname_[yytype] << " ("
+ << *yylocationp << ": ";
+ yy_symbol_value_print_ (yytype, yyvaluep, yylocationp);
+ *yycdebug_ << ')';
+ }
+#endif /* ! YYDEBUG */
+
+ void
+ Parser::yydestruct_ (const char* yymsg,
+ int yytype, semantic_type* yyvaluep, location_type* yylocationp)
+ {
+ YYUSE (yylocationp);
+ YYUSE (yymsg);
+ YYUSE (yyvaluep);
+
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+ }
+
+ void
+ Parser::yypop_ (unsigned int n)
+ {
+ yystate_stack_.pop (n);
+ yysemantic_stack_.pop (n);
+ yylocation_stack_.pop (n);
+ }
+
+ std::ostream&
+ Parser::debug_stream () const
+ {
+ return *yycdebug_;
+ }
+
+ void
+ Parser::set_debug_stream (std::ostream& o)
+ {
+ yycdebug_ = &o;
+ }
+
+
+ Parser::debug_level_type
+ Parser::debug_level () const
+ {
+ return yydebug_;
+ }
+
+ void
+ Parser::set_debug_level (debug_level_type l)
+ {
+ yydebug_ = l;
+ }
+
+
+ int
+ Parser::parse ()
+ {
+ /// Look-ahead and look-ahead in internal form.
+ int yychar = yyempty_;
+ int yytoken = 0;
+
+ /* State. */
+ int yyn;
+ int yylen = 0;
+ int yystate = 0;
+
+ /* Error handling. */
+ int yynerrs_ = 0;
+ int yyerrstatus_ = 0;
+
+ /// Semantic value of the look-ahead.
+ semantic_type yylval;
+ /// Location of the look-ahead.
+ location_type yylloc;
+ /// The locations where the error started and ended.
+ location yyerror_range[2];
+
+ /// $$.
+ semantic_type yyval;
+ /// @$.
+ location_type yyloc;
+
+ int yyresult;
+
+ YYCDEBUG << "Starting parse" << std::endl;
+
+
+ /* Initialize the stacks. The initial state will be pushed in
+ yynewstate, since the latter expects the semantical and the
+ location values to have been already stored, initialize these
+ stacks with a primary value. */
+ yystate_stack_ = state_stack_type (0);
+ yysemantic_stack_ = semantic_stack_type (0);
+ yylocation_stack_ = location_stack_type (0);
+ yysemantic_stack_.push (yylval);
+ yylocation_stack_.push (yylloc);
+
+ /* New state. */
+ yynewstate:
+ yystate_stack_.push (yystate);
+ YYCDEBUG << "Entering state " << yystate << std::endl;
+ goto yybackup;
+
+ /* Backup. */
+ yybackup:
+
+ /* Try to take a decision without look-ahead. */
+ yyn = yypact_[yystate];
+ if (yyn == yypact_ninf_)
+ goto yydefault;
+
+ /* Read a look-ahead token. */
+ if (yychar == yyempty_)
+ {
+ YYCDEBUG << "Reading a token: ";
+ yychar = yylex (&yylval, lexer);
+ }
+
+
+ /* Convert token to internal form. */
+ if (yychar <= yyeof_)
+ {
+ yychar = yytoken = yyeof_;
+ YYCDEBUG << "Now at end of input." << std::endl;
+ }
+ else
+ {
+ yytoken = yytranslate_ (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken)
+ goto yydefault;
+
+ /* Reduce or error. */
+ yyn = yytable_[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == yytable_ninf_)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Accept? */
+ if (yyn == yyfinal_)
+ goto yyacceptlab;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != yyeof_)
+ yychar = yyempty_;
+
+ yysemantic_stack_.push (yylval);
+ yylocation_stack_.push (yylloc);
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus_)
+ --yyerrstatus_;
+
+ yystate = yyn;
+ goto yynewstate;
+
+ /*-----------------------------------------------------------.
+ | yydefault -- do the default action for the current state. |
+ `-----------------------------------------------------------*/
+ yydefault:
+ yyn = yydefact_[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+ /*-----------------------------.
+ | yyreduce -- Do a reduction. |
+ `-----------------------------*/
+ yyreduce:
+ yylen = yyr2_[yyn];
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'. Otherwise, use the top of the stack.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. */
+ if (yylen)
+ yyval = yysemantic_stack_[yylen - 1];
+ else
+ yyval = yysemantic_stack_[0];
+
+ {
+ slice<location_type, location_stack_type> slice (yylocation_stack_, yylen);
+ YYLLOC_DEFAULT (yyloc, slice, yylen);
+ }
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 144 "qmake.yy"
+ {
+ ProjectAST *projectAST = new ProjectAST();
+ projects.push(projectAST);
+ ;}
+ break;
+
+ case 4:
+#line 152 "qmake.yy"
+ {
+ projects.top()->addChildAST((yysemantic_stack_[(2) - (2)].node));
+ (yysemantic_stack_[(2) - (2)].node)->setDepth(depth);
+ ;}
+ break;
+
+ case 6:
+#line 160 "qmake.yy"
+ {
+ (yyval.node) = (yysemantic_stack_[(1) - (1)].node);
+ ;}
+ break;
+
+ case 7:
+#line 164 "qmake.yy"
+ {
+ (yyval.node) = (yysemantic_stack_[(1) - (1)].node);
+ ;}
+ break;
+
+ case 8:
+#line 168 "qmake.yy"
+ {
+ (yyval.node) = (yysemantic_stack_[(1) - (1)].node);
+ ;}
+ break;
+
+ case 9:
+#line 172 "qmake.yy"
+ {
+ (yyval.node) = (yysemantic_stack_[(1) - (1)].node);
+ ;}
+ break;
+
+ case 10:
+#line 176 "qmake.yy"
+ {
+ (yyval.node) = new NewLineAST();
+ ;}
+ break;
+
+ case 11:
+#line 182 "qmake.yy"
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = (yysemantic_stack_[(5) - (1)].value);
+ node->op = (yysemantic_stack_[(5) - (2)].value);
+ node->values = (yysemantic_stack_[(5) - (3)].values) ;
+ node->values.append( (yysemantic_stack_[(5) - (4)].value) );
+ node->values.append( (yysemantic_stack_[(5) - (5)].value) );
+ node->indent = (yysemantic_stack_[(5) - (3)].indent);
+ (yyval.node) = node;
+ ;}
+ break;
+
+ case 12:
+#line 193 "qmake.yy"
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = (yysemantic_stack_[(5) - (1)].value);
+ node->op = (yysemantic_stack_[(5) - (2)].value);
+ node->values = (yysemantic_stack_[(5) - (3)].values) ;
+ node->values.append( (yysemantic_stack_[(5) - (4)].value) );
+ node->indent = (yysemantic_stack_[(5) - (3)].indent);
+ (yyval.node) = node;
+ ;}
+ break;
+
+ case 13:
+#line 203 "qmake.yy"
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = (yysemantic_stack_[(5) - (1)].value);
+ node->op = (yysemantic_stack_[(5) - (2)].value);
+ node->values = (yysemantic_stack_[(5) - (3)].values) ;
+ node->values.append( (yysemantic_stack_[(5) - (4)].value) );
+ node->values.append( (yysemantic_stack_[(5) - (5)].value) );
+ node->indent = (yysemantic_stack_[(5) - (3)].indent);
+ (yyval.node) = node;
+ ;}
+ break;
+
+ case 14:
+#line 214 "qmake.yy"
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = (yysemantic_stack_[(5) - (1)].value);
+ node->op = (yysemantic_stack_[(5) - (2)].value);
+ node->values = (yysemantic_stack_[(5) - (3)].values) ;
+ node->values.append( (yysemantic_stack_[(5) - (4)].value) );
+ node->values.append( (yysemantic_stack_[(5) - (5)].value) );
+ node->indent = (yysemantic_stack_[(5) - (3)].indent);
+ (yyval.node) = node;
+ ;}
+ break;
+
+ case 15:
+#line 225 "qmake.yy"
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = (yysemantic_stack_[(4) - (1)].value);
+ node->op = (yysemantic_stack_[(4) - (2)].value);
+ node->values.append( (yysemantic_stack_[(4) - (3)].value) );
+ node->values.append( (yysemantic_stack_[(4) - (4)].value) );
+ (yyval.node) = node;
+ ;}
+ break;
+
+ case 16:
+#line 234 "qmake.yy"
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = (yysemantic_stack_[(4) - (1)].value);
+ node->op = (yysemantic_stack_[(4) - (2)].value);
+ node->values.append( (yysemantic_stack_[(4) - (3)].value) );
+ (yyval.node) = node;
+ ;}
+ break;
+
+ case 17:
+#line 242 "qmake.yy"
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = (yysemantic_stack_[(4) - (1)].value);
+ node->op = (yysemantic_stack_[(4) - (2)].value);
+ node->values.append( (yysemantic_stack_[(4) - (3)].value) );
+ node->values.append( (yysemantic_stack_[(4) - (4)].value) );
+ (yyval.node) = node;
+ ;}
+ break;
+
+ case 18:
+#line 251 "qmake.yy"
+ {
+ AssignmentAST *node = new AssignmentAST();
+ node->scopedID = (yysemantic_stack_[(5) - (1)].value);
+ node->op = (yysemantic_stack_[(5) - (2)].value);
+ node->values = (yysemantic_stack_[(5) - (3)].values);
+ node->values.append( (yysemantic_stack_[(5) - (4)].value) );
+ node->values.append( (yysemantic_stack_[(5) - (5)].value) );
+ node->indent = (yysemantic_stack_[(5) - (3)].indent);
+ (yyval.node) = node;
+ ;}
+ break;
+
+ case 22:
+#line 266 "qmake.yy"
+ {
+ (yyval.values).append( (yysemantic_stack_[(3) - (2)].value) );
+ (yyval.values).append( (yysemantic_stack_[(3) - (3)].value) );
+ ;}
+ break;
+
+ case 23:
+#line 271 "qmake.yy"
+ {
+ (yyval.values).append( (yysemantic_stack_[(2) - (2)].value) );
+ ;}
+ break;
+
+ case 24:
+#line 275 "qmake.yy"
+ {
+ (yyval.values).append( (yysemantic_stack_[(5) - (2)].value) );
+ (yyval.values).append( (yysemantic_stack_[(5) - (3)].value) );
+ (yyval.values).append( (yysemantic_stack_[(5) - (4)].value) );
+ (yyval.values).append( (yysemantic_stack_[(5) - (5)].value) );
+ if( (yysemantic_stack_[(5) - (4)].indent) != "" && (yyval.indent) == "" )
+ (yyval.indent) = (yysemantic_stack_[(5) - (4)].indent);
+ ;}
+ break;
+
+ case 25:
+#line 284 "qmake.yy"
+ {
+ (yyval.values).append( (yysemantic_stack_[(5) - (2)].value) );
+ (yyval.values).append( (yysemantic_stack_[(5) - (3)].value) );
+ (yyval.values).append( (yysemantic_stack_[(5) - (4)].value) );
+ (yyval.values).append( (yysemantic_stack_[(5) - (5)].value) );
+ if( (yysemantic_stack_[(5) - (4)].indent) != "" && (yyval.indent) == "" )
+ (yyval.indent) = (yysemantic_stack_[(5) - (4)].indent);
+ ;}
+ break;
+
+ case 26:
+#line 293 "qmake.yy"
+ {
+ (yyval.values) = QStringList();
+ (yyval.values).append( (yysemantic_stack_[(2) - (1)].value) );
+ (yyval.values).append( (yysemantic_stack_[(2) - (2)].value) );
+ ;}
+ break;
+
+ case 27:
+#line 301 "qmake.yy"
+ { (yyval.value) = (yysemantic_stack_[(1) - (1)].value); ;}
+ break;
+
+ case 28:
+#line 302 "qmake.yy"
+ { (yyval.value) = (yysemantic_stack_[(1) - (1)].value); ;}
+ break;
+
+ case 29:
+#line 307 "qmake.yy"
+ {
+ (yyval.value) = (yysemantic_stack_[(1) - (1)].value);
+ (yyval.indent) = (yysemantic_stack_[(1) - (1)].value);
+ ;}
+ break;
+
+ case 30:
+#line 312 "qmake.yy"
+ {
+ (yyval.value) = QString();
+ (yyval.indent) = QString();
+ ;}
+ break;
+
+ case 31:
+#line 318 "qmake.yy"
+ {
+ (yyval.value) = (yysemantic_stack_[(1) - (1)].value);
+ ;}
+ break;
+
+ case 32:
+#line 322 "qmake.yy"
+ {
+ (yyval.value) = (yysemantic_stack_[(1) - (1)].value);
+ ;}
+ break;
+
+ case 33:
+#line 326 "qmake.yy"
+ {
+ (yyval.value) = (yysemantic_stack_[(1) - (1)].value);
+ ;}
+ break;
+
+ case 34:
+#line 330 "qmake.yy"
+ {
+ (yyval.value) = (yysemantic_stack_[(1) - (1)].value);
+ ;}
+ break;
+
+ case 35:
+#line 334 "qmake.yy"
+ {
+ (yyval.value) = (yysemantic_stack_[(1) - (1)].value);
+ ;}
+ break;
+
+ case 36:
+#line 340 "qmake.yy"
+ {
+ ProjectAST *projectAST = new ProjectAST(ProjectAST::Scope);
+ projects.push(projectAST);
+ projects.top()->scopedID = (yysemantic_stack_[(1) - (1)].value);
+ depth++;
+ ;}
+ break;
+
+ case 37:
+#line 347 "qmake.yy"
+ {
+ (yyval.node) = projects.pop();
+ depth--;
+ ;}
+ break;
+
+ case 38:
+#line 354 "qmake.yy"
+ {
+ ProjectAST *projectAST = new ProjectAST(ProjectAST::FunctionScope);
+ projects.push(projectAST);
+ projects.top()->scopedID = (yysemantic_stack_[(4) - (1)].value);
+ projects.top()->args = (yysemantic_stack_[(4) - (3)].value);
+ depth++;
+
+ //qWarning("%s", $<value>1.ascii());
+ if ((yysemantic_stack_[(4) - (1)].value).contains("include"))
+ {
+ IncludeAST *includeAST = new IncludeAST();
+ includeAST->projectName = (yysemantic_stack_[(4) - (3)].value);
+ projects.top()->addChildAST(includeAST);
+ includeAST->setDepth(depth);
+ }
+ ;}
+ break;
+
+ case 39:
+#line 372 "qmake.yy"
+ {
+ (yyval.node) = projects.pop();
+ depth--;
+ ;}
+ break;
+
+ case 40:
+#line 378 "qmake.yy"
+ { (yyval.value) = (yysemantic_stack_[(1) - (1)].value); ;}
+ break;
+
+ case 41:
+#line 379 "qmake.yy"
+ { (yyval.value) = ""; ;}
+ break;
+
+ case 43:
+#line 384 "qmake.yy"
+ {
+ projects.top()->addChildAST((yysemantic_stack_[(2) - (2)].node));
+ (yysemantic_stack_[(2) - (2)].node)->setDepth(depth);
+ ;}
+ break;
+
+ case 45:
+#line 392 "qmake.yy"
+ {
+ ProjectAST *projectAST = new ProjectAST(ProjectAST::FunctionScope);
+ projects.push(projectAST);
+ projects.top()->scopedID = "else";
+ projects.top()->args = "";
+ depth++;
+ ;}
+ break;
+
+ case 46:
+#line 400 "qmake.yy"
+ {
+ (yyval.node) = projects.pop();
+ depth--;
+ ;}
+ break;
+
+ case 47:
+#line 405 "qmake.yy"
+ {
+ (yyval.node) = new ProjectAST();
+ ;}
+ break;
+
+ case 48:
+#line 411 "qmake.yy"
+ {
+ CommentAST *node = new CommentAST();
+ node->comment = (yysemantic_stack_[(1) - (1)].value);
+ (yyval.node) = node;
+ ;}
+ break;
+
+
+ /* Line 675 of lalr1.cc. */
+#line 756 "qmake_yacc.cpp"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc);
+
+ yypop_ (yylen);
+ yylen = 0;
+ YY_STACK_PRINT ();
+
+ yysemantic_stack_.push (yyval);
+ yylocation_stack_.push (yyloc);
+
+ /* Shift the result of the reduction. */
+ yyn = yyr1_[yyn];
+ yystate = yypgoto_[yyn - yyntokens_] + yystate_stack_[0];
+ if (0 <= yystate && yystate <= yylast_
+ && yycheck_[yystate] == yystate_stack_[0])
+ yystate = yytable_[yystate];
+ else
+ yystate = yydefgoto_[yyn - yyntokens_];
+ goto yynewstate;
+
+ /*------------------------------------.
+ | yyerrlab -- here on detecting error |
+ `------------------------------------*/
+ yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus_)
+ {
+ ++yynerrs_;
+ error (yylloc, yysyntax_error_ (yystate));
+ }
+
+ yyerror_range[0] = yylloc;
+ if (yyerrstatus_ == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= yyeof_)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == yyeof_)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc);
+ yychar = yyempty_;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+ /*---------------------------------------------------.
+ | yyerrorlab -- error raised explicitly by YYERROR. |
+ `---------------------------------------------------*/
+ yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (false)
+ goto yyerrorlab;
+
+ yyerror_range[0] = yylocation_stack_[yylen - 1];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ yypop_ (yylen);
+ yylen = 0;
+ yystate = yystate_stack_[0];
+ goto yyerrlab1;
+
+ /*-------------------------------------------------------------.
+ | yyerrlab1 -- common code for both syntax error and YYERROR. |
+ `-------------------------------------------------------------*/
+ yyerrlab1:
+ yyerrstatus_ = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact_[yystate];
+ if (yyn != yypact_ninf_)
+ {
+ yyn += yyterror_;
+ if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
+ {
+ yyn = yytable_[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yystate_stack_.height () == 1)
+ YYABORT;
+
+ yyerror_range[0] = yylocation_stack_[0];
+ yydestruct_ ("Error: popping",
+ yystos_[yystate],
+ &yysemantic_stack_[0], &yylocation_stack_[0]);
+ yypop_ ();
+ yystate = yystate_stack_[0];
+ YY_STACK_PRINT ();
+ }
+
+ if (yyn == yyfinal_)
+ goto yyacceptlab;
+
+ yyerror_range[1] = yylloc;
+ // Using YYLLOC is tempting, but would change the location of
+ // the look-ahead. YYLOC is available though.
+ YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+ yysemantic_stack_.push (yylval);
+ yylocation_stack_.push (yyloc);
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos_[yyn],
+ &yysemantic_stack_[0], &yylocation_stack_[0]);
+
+ yystate = yyn;
+ goto yynewstate;
+
+ /* Accept. */
+ yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+ /* Abort. */
+ yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+ yyreturn:
+ if (yychar != yyeof_ && yychar != yyempty_)
+ yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc);
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ yypop_ (yylen);
+ while (yystate_stack_.height () != 1)
+ {
+ yydestruct_ ("Cleanup: popping",
+ yystos_[yystate_stack_[0]],
+ &yysemantic_stack_[0],
+ &yylocation_stack_[0]);
+ yypop_ ();
+ }
+
+ return yyresult;
+ }
+
+ // Generate an error message.
+ std::string
+ Parser::yysyntax_error_ (int yystate)
+ {
+ std::string res;
+ YYUSE (yystate);
+#if YYERROR_VERBOSE
+ int yyn = yypact_[yystate];
+ if (yypact_ninf_ < yyn && yyn <= yylast_)
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = yylast_ - yyn + 1;
+ int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
+ int count = 0;
+ for (int x = yyxbegin; x < yyxend; ++x)
+ if (yycheck_[x + yyn] == x && x != yyterror_)
+ ++count;
+
+ // FIXME: This method of building the message is not compatible
+ // with internationalization. It should work like yacc.c does it.
+ // That is, first build a string that looks like this:
+ // "syntax error, unexpected %s or %s or %s"
+ // Then, invoke YY_ on this string.
+ // Finally, use the string as a format to output
+ // yytname_[tok], etc.
+ // Until this gets fixed, this message appears in English only.
+ res = "syntax error, unexpected ";
+ res += yytnamerr_ (yytname_[tok]);
+ if (count < 5)
+ {
+ count = 0;
+ for (int x = yyxbegin; x < yyxend; ++x)
+ if (yycheck_[x + yyn] == x && x != yyterror_)
+ {
+ res += (!count++) ? ", expecting " : " or ";
+ res += yytnamerr_ (yytname_[x]);
+ }
+ }
+ }
+ else
+#endif
+ res = YY_("syntax error");
+ return res;
+ }
+
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+ const signed char Parser::yypact_ninf_ = -44;
+ const signed char
+ Parser::yypact_[] =
+ {
+ -44, 19, -44, -44, 8, 45, -44, -44, -44, -44,
+ -44, -44, -44, -44, -44, -44, -44, -44, -44, 12,
+ 10, 31, -44, 24, -44, -15, -5, 8, -44, -44,
+ -44, -44, -44, 26, -44, 14, -44, -44, -44, -44,
+ -44, -44, -44, -44, 0, 31, -44, -44, -44, 18,
+ 18, -44, -44, 20, 26, 26, 27, -44, -44, -44,
+ -44, 31, 39, -44
+ };
+
+ /* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
+ doesn't specify something else to do. Zero means the default is an
+ error. */
+ const unsigned char
+ Parser::yydefact_[] =
+ {
+ 2, 0, 5, 1, 3, 36, 49, 48, 4, 6,
+ 7, 8, 9, 10, 31, 32, 33, 34, 35, 41,
+ 30, 44, 40, 0, 29, 30, 0, 0, 5, 37,
+ 38, 28, 27, 29, 23, 0, 15, 17, 21, 20,
+ 16, 26, 19, 43, 0, 44, 22, 11, 18, 13,
+ 14, 12, 42, 47, 0, 0, 0, 39, 24, 25,
+ 45, 44, 0, 46
+ };
+
+ /* YYPGOTO[NTERM-NUM]. */
+ const signed char
+ Parser::yypgoto_[] =
+ {
+ -44, -44, -44, 7, 29, -44, -32, -44, 22, -25,
+ -44, -44, -44, -44, -44, -44, -43, -44, -44, -44,
+ -44
+ };
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+ const signed char
+ Parser::yydefgoto_[] =
+ {
+ -1, 1, 2, 4, 8, 9, 41, 25, 42, 26,
+ 20, 10, 21, 11, 45, 23, 29, 57, 61, 12,
+ 13
+ };
+
+ /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says. */
+ const signed char Parser::yytable_ninf_ = -31;
+ const signed char
+ Parser::yytable_[] =
+ {
+ 35, 46, 53, 5, 31, 32, 33, 36, 37, 38,
+ 39, 5, 6, 7, 31, 32, 52, 40, 62, 3,
+ 6, 7, 58, 59, 54, 55, 47, 48, 49, 50,
+ 22, 24, -30, -30, 30, 44, 51, -30, -30, 24,
+ 38, 39, 27, 56, 60, 31, 32, 34, 28, 14,
+ 15, 16, 17, 18, 19, 63, 43
+ };
+
+ /* YYCHECK. */
+ const unsigned char
+ Parser::yycheck_[] =
+ {
+ 25, 33, 45, 3, 19, 20, 21, 12, 13, 14,
+ 15, 3, 12, 13, 19, 20, 16, 22, 61, 0,
+ 12, 13, 54, 55, 49, 50, 12, 13, 14, 15,
+ 18, 21, 14, 15, 10, 28, 22, 19, 20, 21,
+ 14, 15, 11, 23, 17, 19, 20, 25, 17, 4,
+ 5, 6, 7, 8, 9, 16, 27
+ };
+
+ /* STOS_[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+ const unsigned char
+ Parser::yystos_[] =
+ {
+ 0, 25, 26, 0, 27, 3, 12, 13, 28, 29,
+ 35, 37, 43, 44, 4, 5, 6, 7, 8, 9,
+ 34, 36, 18, 39, 21, 31, 33, 11, 17, 40,
+ 10, 19, 20, 21, 32, 33, 12, 13, 14, 15,
+ 22, 30, 32, 28, 27, 38, 30, 12, 13, 14,
+ 15, 22, 16, 40, 33, 33, 23, 41, 30, 30,
+ 17, 42, 40, 16
+ };
+
+#if YYDEBUG
+ /* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding
+ to YYLEX-NUM. */
+ const unsigned short int
+ Parser::yytoken_number_[] =
+ {
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278
+ };
+#endif
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+ const unsigned char
+ Parser::yyr1_[] =
+ {
+ 0, 24, 26, 25, 27, 27, 28, 28, 28, 28,
+ 28, 29, 29, 29, 29, 29, 29, 29, 29, 30,
+ 30, 30, 31, 31, 31, 31, 31, 32, 32, 33,
+ 33, 34, 34, 34, 34, 34, 36, 35, 38, 37,
+ 39, 39, 40, 40, 40, 42, 41, 41, 43, 44
+ };
+
+ /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+ const unsigned char
+ Parser::yyr2_[] =
+ {
+ 0, 2, 0, 2, 2, 0, 1, 1, 1, 1,
+ 1, 5, 5, 5, 5, 4, 4, 4, 5, 1,
+ 1, 1, 3, 2, 5, 5, 2, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 0, 3, 0, 7,
+ 1, 0, 3, 2, 0, 0, 5, 0, 1, 1
+ };
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+ /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at \a yyntokens_, nonterminals. */
+ const char*
+ const Parser::yytname_[] =
+ {
+ "$end", "error", "$undefined", "ID_SIMPLE", "EQ", "PLUSEQ", "MINUSEQ",
+ "STAREQ", "TILDEEQ", "LBRACE", "RBRACE", "COLON", "NEWLINE", "COMMENT",
+ "CONT", "COMMENT_CONT", "RCURLY", "LCURLY", "ID_ARGS",
+ "QUOTED_VARIABLE_VALUE", "VARIABLE_VALUE", "LIST_WS", "ENDOFFILE",
+ "\"else\"", "$accept", "project", "@1", "statements", "statement",
+ "variable_assignment", "possible_value", "multiline_values",
+ "variable_value", "listws", "operator", "scope", "@2", "function_call",
+ "@3", "function_args", "scope_body", "else_statement", "@4", "comment",
+ "emptyline", 0
+ };
+#endif
+
+#if YYDEBUG
+ /* YYRHS -- A `-1'-separated list of the rules' RHS. */
+ const Parser::rhs_number_type
+ Parser::yyrhs_[] =
+ {
+ 25, 0, -1, -1, 26, 27, -1, 27, 28, -1,
+ -1, 29, -1, 35, -1, 37, -1, 43, -1, 44,
+ -1, 3, 34, 31, 33, 12, -1, 3, 34, 31,
+ 33, 22, -1, 3, 34, 31, 33, 14, -1, 3,
+ 34, 31, 33, 15, -1, 3, 34, 33, 12, -1,
+ 3, 34, 33, 22, -1, 3, 34, 33, 13, -1,
+ 3, 34, 31, 33, 13, -1, 32, -1, 15, -1,
+ 14, -1, 31, 21, 30, -1, 31, 32, -1, 31,
+ 33, 14, 33, 30, -1, 31, 33, 15, 33, 30,
+ -1, 33, 30, -1, 20, -1, 19, -1, 21, -1,
+ -1, 4, -1, 5, -1, 6, -1, 7, -1, 8,
+ -1, -1, 3, 36, 40, -1, -1, 3, 9, 39,
+ 10, 38, 40, 41, -1, 18, -1, -1, 17, 27,
+ 16, -1, 11, 28, -1, -1, -1, 23, 17, 42,
+ 40, 16, -1, -1, 13, -1, 12, -1
+ };
+
+ /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+ const unsigned char
+ Parser::yyprhs_[] =
+ {
+ 0, 0, 3, 4, 7, 10, 11, 13, 15, 17,
+ 19, 21, 27, 33, 39, 45, 50, 55, 60, 66,
+ 68, 70, 72, 76, 79, 85, 91, 94, 96, 98,
+ 100, 101, 103, 105, 107, 109, 111, 112, 116, 117,
+ 125, 127, 128, 132, 135, 136, 137, 143, 144, 146
+ };
+
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+ const unsigned short int
+ Parser::yyrline_[] =
+ {
+ 0, 144, 144, 144, 151, 156, 159, 163, 167, 171,
+ 175, 181, 192, 202, 213, 224, 233, 241, 250, 263,
+ 263, 263, 265, 270, 274, 283, 292, 301, 302, 306,
+ 312, 317, 321, 325, 329, 333, 340, 339, 354, 353,
+ 378, 379, 382, 383, 388, 392, 391, 405, 410, 418
+ };
+
+ // Print the state stack on the debug stream.
+ void
+ Parser::yystack_print_ ()
+ {
+ *yycdebug_ << "Stack now";
+ for (state_stack_type::const_iterator i = yystate_stack_.begin ();
+ i != yystate_stack_.end (); ++i)
+ *yycdebug_ << ' ' << *i;
+ *yycdebug_ << std::endl;
+ }
+
+ // Report on the debug stream that the rule \a yyrule is going to be reduced.
+ void
+ Parser::yy_reduce_print_ (int yyrule)
+ {
+ unsigned int yylno = yyrline_[yyrule];
+ int yynrhs = yyr2_[yyrule];
+ /* Print the symbols being reduced, and their result. */
+ *yycdebug_ << "Reducing stack by rule " << yyrule - 1
+ << " (line " << yylno << "), ";
+ /* The symbols being reduced. */
+ for (int yyi = 0; yyi < yynrhs; yyi++)
+ YY_SYMBOL_PRINT (" $" << yyi + 1 << " =",
+ yyrhs_[yyprhs_[yyrule] + yyi],
+ &(yysemantic_stack_[(yynrhs) - (yyi + 1)]),
+ &(yylocation_stack_[(yynrhs) - (yyi + 1)]));
+ }
+#endif // YYDEBUG
+
+ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+ Parser::token_number_type
+ Parser::yytranslate_ (int t)
+ {
+ static
+ const token_number_type
+ translate_table[] =
+ {
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23
+ };
+ if ((unsigned int) t <= yyuser_token_number_max_)
+ return translate_table[t];
+ else
+ return yyundef_token_;
+ }
+
+ const int Parser::yyeof_ = 0;
+ const int Parser::yylast_ = 56;
+ const int Parser::yynnts_ = 21;
+ const int Parser::yyempty_ = -2;
+ const int Parser::yyfinal_ = 3;
+ const int Parser::yyterror_ = 1;
+ const int Parser::yyerrcode_ = 256;
+ const int Parser::yyntokens_ = 24;
+
+ const unsigned int Parser::yyuser_token_number_max_ = 278;
+ const Parser::token_number_type Parser::yyundef_token_ = 2;
+
+} // namespace QMake
+
+#line 421 "qmake.yy"
+
+
+
+namespace QMake
+{
+ void Parser::error(const location_type& /*l*/, const std::string& m)
+ {
+ std::cerr << m << std::endl;
+ }
+}
+
diff --git a/buildtools/lib/parsers/qmake/qmake_yacc.hpp b/buildtools/lib/parsers/qmake/qmake_yacc.hpp
new file mode 100644
index 00000000..69b8a035
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmake_yacc.hpp
@@ -0,0 +1,418 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison LALR(1) parsers in C++
+
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C++ LALR(1) parser skeleton written by Akim Demaille. */
+
+#ifndef PARSER_HEADER_H
+# define PARSER_HEADER_H
+
+#include <string>
+#include <iostream>
+#include "stack.hh"
+
+namespace QMake
+{
+ class position;
+ class location;
+}
+
+/* First part of user declarations. */
+#line 1 "qmake.yy"
+
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * Copyright (C) 2006 by Andreas Pakulat *
+ * apaku@gmx.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+/**
+@file qmake.yy
+QMake Parser
+
+Simple LALR parser which builds the syntax tree (see @ref QMake::AST).
+
+@todo Recognize comments after statements like:
+SOURCES = foo #regognize me
+
+@fixme Parser fails on files that do not end with a newline
+@fixme 1 shift/reduce conflict in "line_body" rule
+*/
+
+#include <qvaluestack.h>
+#include "qmakeast.h"
+#include <qregexp.h>
+
+#define YYSTYPE_IS_DECLARED
+
+namespace QMake
+{
+ class Lexer;
+
+/**
+The yylval type.
+*/
+struct Result {
+ Result(): node(0) {}
+
+ /**Type of semantic value for simple grammar rules.*/
+ QString value;
+ /**Type of semantic value for grammar rules which are parts of AST.*/
+ AST *node;
+ /**Type of semantic value for "multiline_values" grammar rule.
+ Each line of multiline value is stored as a string in the list.
+
+ For example we have in .pro file:
+ @code
+ SOURCE = foo1.cpp \
+ foo2.cpp \
+ foo3.cpp foo4.cpp
+ @endcode
+ The string list will be populated with three strings:
+ <pre>
+ foo1.cpp
+ foo2.cpp
+ foo3.cpp foo4.cpp
+ </pre>
+ */
+ QStringList values;
+ QString indent;
+};
+
+#define YYSTYPE Result
+typedef Result YYSTYPE;
+}
+
+extern int QMakelex( QMake::Result* yylval, QMake::Lexer* lexer );
+
+/**
+The stack to store ProjectAST pointers when a new child
+ProjectAST is created and filled with statements.
+
+Parser creates root ProjectAST for a .pro file, pushes it onto the stack and starts
+adding statements. Each statement is added as a child StatementAST to the ProjectAST
+currently on the top in the stack.
+
+When a scope or function scope statement is parsed, the child ProjectAST is created
+and pushed onto the stack. Therefore all statements which belong to the scope
+or function scope are added as childs to their direct parent (scope or function scope).
+*/
+//QValueStack<ProjectAST*> projects;
+
+/**
+The current depth of AST node is stored here.
+AST depth is important to know because automatic indentation can
+be easily implemented (the parser itself looses all information
+about indentation).
+*/
+// int depth = 0;
+
+/*
+To debug this parser, put the line below into the next bison file section.
+Don't forget to uncomment "yydebug = 1" line in qmakedriver.cpp.
+%debug
+*/
+
+
+/* Line 35 of lalr1.cc. */
+#line 165 "qmake_yacc.hpp"
+
+#include "location.hh"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 1
+#endif
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+do { \
+ if (N) \
+ { \
+ (Current).begin = (Rhs)[1].begin; \
+ (Current).end = (Rhs)[N].end; \
+ } \
+ else \
+ { \
+ (Current).begin = (Current).end = (Rhs)[0].end; \
+ } \
+} while (false)
+#endif
+
+namespace QMake
+{
+
+ /// A Bison parser.
+ class Parser
+ {
+ public:
+ /// Symbol semantic values.
+#ifndef YYSTYPE
+ typedef int semantic_type;
+#else
+ typedef YYSTYPE semantic_type;
+#endif
+ /// Symbol locations.
+ typedef location location_type;
+ /// Tokens.
+ struct token
+ {
+ /* Tokens. */
+ enum yytokentype {
+ ID_SIMPLE = 258,
+ EQ = 259,
+ PLUSEQ = 260,
+ MINUSEQ = 261,
+ STAREQ = 262,
+ TILDEEQ = 263,
+ LBRACE = 264,
+ RBRACE = 265,
+ COLON = 266,
+ NEWLINE = 267,
+ COMMENT = 268,
+ CONT = 269,
+ COMMENT_CONT = 270,
+ RCURLY = 271,
+ LCURLY = 272,
+ ID_ARGS = 273,
+ QUOTED_VARIABLE_VALUE = 274,
+ VARIABLE_VALUE = 275,
+ LIST_WS = 276,
+ ENDOFFILE = 277
+ };
+
+ };
+ /// Token type.
+ typedef token::yytokentype token_type;
+
+ /// Build a parser object.
+ Parser (QMake::Lexer* lexer_yyarg, QValueStack<ProjectAST*>& projects_yyarg, int depth_yyarg);
+ virtual ~Parser ();
+
+ /// Parse.
+ /// \returns 0 iff parsing succeeded.
+ virtual int parse ();
+
+ /// The current debugging stream.
+ std::ostream& debug_stream () const;
+ /// Set the current debugging stream.
+ void set_debug_stream (std::ostream &);
+
+ /// Type for debugging levels.
+ typedef int debug_level_type;
+ /// The current debugging level.
+ debug_level_type debug_level () const;
+ /// Set the current debugging level.
+ void set_debug_level (debug_level_type l);
+
+ private:
+ /// Report a syntax error.
+ /// \param loc where the syntax error is found.
+ /// \param msg a description of the syntax error.
+ virtual void error (const location_type& loc, const std::string& msg);
+
+ /// Generate an error message.
+ /// \param state the state where the error occurred.
+ /// \param tok the look-ahead token.
+ virtual std::string yysyntax_error_ (int yystate);
+
+#if YYDEBUG
+ /// \brief Report a symbol value on the debug stream.
+ /// \param yytype The token type.
+ /// \param yyvaluep Its semantic value.
+ /// \param yylocationp Its location.
+ virtual void yy_symbol_value_print_ (int yytype,
+ const semantic_type* yyvaluep,
+ const location_type* yylocationp);
+ /// \brief Report a symbol on the debug stream.
+ /// \param yytype The token type.
+ /// \param yyvaluep Its semantic value.
+ /// \param yylocationp Its location.
+ virtual void yy_symbol_print_ (int yytype,
+ const semantic_type* yyvaluep,
+ const location_type* yylocationp);
+#endif /* ! YYDEBUG */
+
+
+ /// State numbers.
+ typedef int state_type;
+ /// State stack type.
+ typedef stack<state_type> state_stack_type;
+ /// Semantic value stack type.
+ typedef stack<semantic_type> semantic_stack_type;
+ /// location stack type.
+ typedef stack<location_type> location_stack_type;
+
+ /// The state stack.
+ state_stack_type yystate_stack_;
+ /// The semantic value stack.
+ semantic_stack_type yysemantic_stack_;
+ /// The location stack.
+ location_stack_type yylocation_stack_;
+
+ /// Internal symbol numbers.
+ typedef unsigned char token_number_type;
+ /* Tables. */
+ /// For a state, the index in \a yytable_ of its portion.
+ static const signed char yypact_[];
+ static const signed char yypact_ninf_;
+
+ /// For a state, default rule to reduce.
+ /// Unless\a yytable_ specifies something else to do.
+ /// Zero means the default is an error.
+ static const unsigned char yydefact_[];
+
+ static const signed char yypgoto_[];
+ static const signed char yydefgoto_[];
+
+ /// What to do in a state.
+ /// \a yytable_[yypact_[s]]: what to do in state \a s.
+ /// - if positive, shift that token.
+ /// - if negative, reduce the rule which number is the opposite.
+ /// - if zero, do what YYDEFACT says.
+ static const signed char yytable_[];
+ static const signed char yytable_ninf_;
+
+ static const unsigned char yycheck_[];
+
+ /// For a state, its accessing symbol.
+ static const unsigned char yystos_[];
+
+ /// For a rule, its LHS.
+ static const unsigned char yyr1_[];
+ /// For a rule, its RHS length.
+ static const unsigned char yyr2_[];
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+ /// For a symbol, its name in clear.
+ static const char* const yytname_[];
+#endif
+
+#if YYERROR_VERBOSE
+ /// Convert the symbol name \a n to a form suitable for a diagnostic.
+ virtual std::string yytnamerr_ (const char *n);
+#endif
+
+#if YYDEBUG
+ /// A type to store symbol numbers and -1.
+ typedef signed char rhs_number_type;
+ /// A `-1'-separated list of the rules' RHS.
+ static const rhs_number_type yyrhs_[];
+ /// For each rule, the index of the first RHS symbol in \a yyrhs_.
+ static const unsigned char yyprhs_[];
+ /// For each rule, its source line number.
+ static const unsigned short int yyrline_[];
+ /// For each scanner token number, its symbol number.
+ static const unsigned short int yytoken_number_[];
+ /// Report on the debug stream that the rule \a r is going to be reduced.
+ virtual void yy_reduce_print_ (int r);
+ /// Print the state stack on the debug stream.
+ virtual void yystack_print_ ();
+#endif
+
+ /// Convert a scanner token number \a t to a symbol number.
+ token_number_type yytranslate_ (int t);
+
+ /// \brief Reclaim the memory associated to a symbol.
+ /// \param yymsg Why this token is reclaimed.
+ /// \param yytype The symbol type.
+ /// \param yyvaluep Its semantic value.
+ /// \param yylocationp Its location.
+ inline void yydestruct_ (const char* yymsg,
+ int yytype,
+ semantic_type* yyvaluep,
+ location_type* yylocationp);
+
+ /// Pop \a n symbols the three stacks.
+ inline void yypop_ (unsigned int n = 1);
+
+ /* Constants. */
+ static const int yyeof_;
+ /* LAST_ -- Last index in TABLE_. */
+ static const int yylast_;
+ static const int yynnts_;
+ static const int yyempty_;
+ static const int yyfinal_;
+ static const int yyterror_;
+ static const int yyerrcode_;
+ static const int yyntokens_;
+ static const unsigned int yyuser_token_number_max_;
+ static const token_number_type yyundef_token_;
+
+ /* Debugging. */
+ int yydebug_;
+ std::ostream* yycdebug_;
+
+
+ /* User arguments. */
+ QMake::Lexer* lexer;
+ QValueStack<ProjectAST*>& projects;
+ int depth;
+ };
+}
+
+
+#endif /* ! defined PARSER_HEADER_H */
diff --git a/buildtools/lib/parsers/qmake/qmakeast.cpp b/buildtools/lib/parsers/qmake/qmakeast.cpp
new file mode 100644
index 00000000..e6283e28
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmakeast.cpp
@@ -0,0 +1,170 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "qmakeast.h"
+
+#include <kdebug.h>
+
+namespace QMake {
+
+//AST
+
+AST::~AST()
+{
+ for (QValueList<AST*>::iterator it = m_children.begin(); it != m_children.end(); ++it)
+ {
+ AST *node = *it;
+ delete node;
+ }
+ m_children.clear();
+}
+
+void AST::addChildAST(AST *node)
+{
+ m_children.append(node);
+}
+
+void AST::removeChildAST(AST *node)
+{
+ m_children.remove(node);
+}
+
+void AST::writeBack(QString &buffer)
+{
+ for (QValueList<AST*>::const_iterator it = m_children.constBegin();
+ it != m_children.constEnd(); ++it)
+ {
+ if (*it)
+ {
+ (*it)->writeBack(buffer);
+ }
+ }
+}
+
+QString AST::indentation()
+{
+ QString result;
+ for (int i = 0; i < depth(); i++)
+ result += " ";
+ return result;
+}
+
+//ProjectAST
+
+void ProjectAST::writeBack(QString &buffer)
+{
+ bool hasActualStatements = false;
+ for (QValueList<QMake::AST*>::const_iterator it = m_children.begin(); it != m_children.end(); ++it)
+ {
+ if ((*it)->nodeType() != AST::IncludeAST)
+ {
+ hasActualStatements = true;
+ break;
+ }
+ }
+
+ if (isScope())
+ {
+ if( !buffer.endsWith(": ") )
+ buffer += indentation();
+ buffer += scopedID;
+ if( m_children.count() == 1 )
+ buffer += " : ";
+ else
+ buffer += " {";
+ }
+ else if (isFunctionScope())
+ {
+ if( !buffer.endsWith(": ") )
+ buffer += indentation();
+ buffer += scopedID + "(" + args + ")";
+ if( m_children.count() == 1 && hasActualStatements )
+ buffer += ": ";
+ else if( (m_children.count() > 0 && hasActualStatements) )
+ buffer += "{";
+ else
+ buffer += "";
+ }
+ else if( !buffer.endsWith(": ") )
+ buffer += indentation();
+ AST::writeBack(buffer);
+ if (isScope() && m_children.count() > 1 )
+ buffer += indentation() + "}";
+
+ if (isFunctionScope() && (hasActualStatements) && m_children.count() > 1)
+ buffer += indentation() + "}";
+}
+
+
+void ProjectAST::setLineEnding( ProjectAST::LineEnding l )
+{
+ m_lineEnding = l;
+}
+
+ProjectAST::LineEnding ProjectAST::lineEnding()
+{
+ return m_lineEnding;
+}
+
+//AssignmentAST
+
+AssignmentAST::~AssignmentAST()
+{
+}
+
+void AssignmentAST::writeBack(QString &buffer)
+{
+ if( !buffer.endsWith(": ") )
+ buffer += indentation();
+ buffer += scopedID + " " + op;
+ if( values.first().stripWhiteSpace() != "" )
+ buffer += " ";
+ buffer += values.join("");
+}
+
+
+//NewLineAST
+
+void NewLineAST::writeBack(QString &buffer)
+{
+ buffer += "\n";
+}
+
+
+//CommentAST
+
+void CommentAST::writeBack(QString &buffer)
+{
+ if( !buffer.endsWith(": ") )
+ buffer += indentation();
+ buffer += comment;
+}
+
+
+//IncludeAST
+
+void IncludeAST::writeBack(QString &/*buffer*/)
+{
+}
+
+}
+
+// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on
+
+
diff --git a/buildtools/lib/parsers/qmake/qmakeast.h b/buildtools/lib/parsers/qmake/qmakeast.h
new file mode 100644
index 00000000..b8486433
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmakeast.h
@@ -0,0 +1,236 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef QMAKEQMAKEAST_H
+#define QMAKEQMAKEAST_H
+
+#include <qstringlist.h>
+
+/**
+@file qmakeast.h
+Abstract Syntax Tree (AST) class declarations.
+*/
+
+namespace QMake {
+
+/**
+AST node.
+This is the base class. Objects of this type are not created by the parser.
+
+Each AST node holds the list of its children which are always deleted in the
+destructor. This way, it's possible call delete for only root AST node and
+others will be deleted automatically.
+
+Each AST node also knows how to write the information back into .pro file.
+*/
+class AST {
+public:
+ /**Type of AST node.*/
+ enum NodeType {
+ ProjectAST /**<Project, scope or function scope.*/,
+ AssignmentAST /**<Variable assignment.*/,
+ NewLineAST /**<Line feed.*/,
+ CommentAST /**<Comment.*/,
+ IncludeAST /**<.pri include.*/,
+ OrOperatorAST /* | */
+ };
+
+ /**Constructs AST with given node type.*/
+ AST(NodeType nodeType): m_nodeType(nodeType), m_depth(0) {}
+ virtual ~AST();
+
+ /**Adds child AST node to this node. Despite this function is virtual,
+ reimplementations should call it to make automatic destruction of
+ AST tree possible.*/
+ virtual void addChildAST(AST *node);
+ /**Removes child AST node from this node. Despite this function is virtual,
+ reimplementations should call it to make automatic destruction of
+ AST tree possible.*/
+ virtual void removeChildAST(AST *node);
+ /**Writes information stored in the AST into the @p buffer.
+ This is a default implementation which iterates over child nodes
+ and calls writeBack for each child node.*/
+ virtual void writeBack(QString &buffer);
+
+ /**@return The type of the node.*/
+ virtual NodeType nodeType() const { return m_nodeType; }
+
+ /**Sets the depth of the node in AST.*/
+ void setDepth(int depth) { m_depth = depth; }
+ /**@return The depth of the node in AST.*/
+ int depth() const { return m_depth; }
+ /**@return The indentation string based on node depth.*/
+ virtual QString indentation();
+
+ /**The list of child AST nodes.*/
+ QValueList<AST*> m_children;
+
+protected:
+ NodeType m_nodeType;
+
+private:
+ int m_depth;
+
+};
+
+
+/**
+Project AST node.
+Represents complete projects, scopes and function scopes.
+Examples:
+@code
+scopename{
+var=value
+}
+function(args){
+var=value
+}
+@endcode
+*/
+class ProjectAST: public AST {
+public:
+ /**The kind of a project node.*/
+ enum Kind {
+ Project /**<Project*/,
+ Scope /**<Scope*/,
+ FunctionScope /**<FunctionScope*/,
+ Empty /**<Project does not exist, the AST is empty*/
+ };
+
+ enum LineEnding {
+ Unix,
+ MacOS,
+ Windows
+ };
+
+ /**Constructs a project node of given @p kind.*/
+ ProjectAST(Kind kind = Project): AST(AST::ProjectAST), m_kind(kind) {}
+
+ virtual void writeBack(QString &buffer);
+
+ /**@return true if this node is a project.*/
+ bool isProject() const { return m_kind == Project; }
+ /**@return true if this node is a scope.*/
+ bool isScope() const { return m_kind == Scope; }
+ /**@return true if this node is a function scope.*/
+ bool isFunctionScope() const { return m_kind == FunctionScope; }
+ /**@return true if this node is empty.*/
+ bool isEmpty() const { return m_kind == Empty; }
+
+ void setFileName(const QString& fileName) { m_fileName = fileName; }
+ QString fileName() const { return m_fileName; }
+
+ void setLineEnding( LineEnding );
+ LineEnding lineEnding();
+
+ /**Scoped identifier (scope name or function name).*/
+ QString scopedID;
+ /**Function arguments. Empty for other kinds of projects.*/
+ QString args;
+
+private:
+ Kind m_kind;
+ QString m_fileName;
+ LineEnding m_lineEnding;
+};
+
+
+/**
+Assignment AST node.
+Represents assignments, for example:
+<pre>
+var=value
+</pre>
+
+Values can be specified on several lines and
+each line is stored as a string in the list of values.@n
+For example, if we have in .pro:
+<pre>
+SOURCES=a.cpp \
+ b.cpp c.cpp
+</pre>
+then values will be stored as a two elements list:
+<pre>
+a.cpp
+ b.cpp c.cpp
+</pre>
+*/
+class AssignmentAST: public AST {
+public:
+ AssignmentAST(): AST(AST::AssignmentAST){}
+ ~AssignmentAST();
+
+ virtual void writeBack(QString &buffer);
+
+ /**Scoped name of the variable.*/
+ QString scopedID;
+ /**Operator.*/
+ QString op;
+ /**List of values.*/
+ QStringList values;
+ /**Indentation of multiline values*/
+ QString indent;
+};
+
+
+/**
+New line AST node.
+Represents line feeds in files.
+*/
+class NewLineAST: public AST {
+public:
+ NewLineAST(): AST(AST::NewLineAST) {}
+
+ virtual void writeBack(QString &buffer);
+
+};
+
+
+/**
+Comment AST node.
+Represents comments.
+*/
+class CommentAST: public AST {
+public:
+ CommentAST(): AST(AST::CommentAST) {}
+
+ virtual void writeBack(QString &buffer);
+
+ /**Comment text.*/
+ QString comment;
+
+};
+
+
+/**
+Include AST node.
+Represents pri include.
+ */
+class IncludeAST: public AST {
+public:
+ IncludeAST(): AST(AST::IncludeAST) {}
+
+ virtual void writeBack(QString &buffer);
+
+ QString projectName;
+};
+
+}
+
+#endif
diff --git a/buildtools/lib/parsers/qmake/qmakeastvisitor.cpp b/buildtools/lib/parsers/qmake/qmakeastvisitor.cpp
new file mode 100644
index 00000000..d8dd7751
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmakeastvisitor.cpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "qmakeastvisitor.h"
+
+namespace QMake {
+
+void ASTVisitor::processProject(ProjectAST *project)
+{
+ if (project->isProject())
+ enterRealProject(project);
+ else if (project->isScope())
+ enterScope(project);
+ else if (project->isFunctionScope())
+ enterFunctionScope(project);
+ for (QValueList<QMake::AST*>::const_iterator it = project->m_children.constBegin();
+ it != project->m_children.constEnd(); ++it)
+ {
+ AST *ast = *it;
+ if (ast == 0)
+ continue;
+ switch (ast->nodeType()) {
+ case AST::AssignmentAST:
+ processAssignment(static_cast<QMake::AssignmentAST*>(ast));
+ break;
+
+ case AST::NewLineAST:
+ processNewLine(static_cast<QMake::NewLineAST*>(ast));
+ break;
+
+ case AST::CommentAST:
+ processComment(static_cast<QMake::CommentAST*>(ast));
+ break;
+
+ case AST::ProjectAST:
+ processProject(static_cast<QMake::ProjectAST*>(ast));
+ break;
+
+ case AST::IncludeAST:
+ processInclude(static_cast<QMake::IncludeAST*>(ast));
+ break;
+ }
+ }
+ if (project->isProject())
+ leaveRealProject(project);
+ else if (project->isScope())
+ leaveScope(project);
+ else if (project->isFunctionScope())
+ leaveFunctionScope(project);
+}
+
+}
diff --git a/buildtools/lib/parsers/qmake/qmakeastvisitor.h b/buildtools/lib/parsers/qmake/qmakeastvisitor.h
new file mode 100644
index 00000000..006d1de3
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmakeastvisitor.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef QMAKEQMAKEASTVISITOR_H
+#define QMAKEQMAKEASTVISITOR_H
+
+#include "qmakeast.h"
+
+namespace QMake {
+
+class ASTVisitor{
+public:
+ ASTVisitor() {}
+
+ virtual void processProject(ProjectAST *);
+ virtual void enterRealProject(ProjectAST *) {}
+ virtual void leaveRealProject(ProjectAST *) {}
+ virtual void enterScope(ProjectAST *) {}
+ virtual void leaveScope(ProjectAST *) {}
+ virtual void enterFunctionScope(ProjectAST *) {}
+ virtual void leaveFunctionScope(ProjectAST *) {}
+ virtual void processAssignment(AssignmentAST *) {}
+ virtual void processNewLine(NewLineAST *) {}
+ virtual void processComment(CommentAST *) {}
+ virtual void processInclude(IncludeAST *) {}
+};
+
+}
+
+#endif
diff --git a/buildtools/lib/parsers/qmake/qmakedriver.cpp b/buildtools/lib/parsers/qmake/qmakedriver.cpp
new file mode 100644
index 00000000..3e385c7a
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmakedriver.cpp
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "qmakedriver.h"
+#include "qmakeast.h"
+
+#include <qvaluestack.h>
+#include <kio/netaccess.h>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include "qmake_lex.h"
+#include "qmake_yacc.hpp"
+
+namespace QMake {
+
+int Driver::parseFile(const char *fileName, ProjectAST **ast, int debug)
+{
+ std::ifstream inf( fileName, std::ios::in );
+ if ( !inf.is_open() )
+ {
+ *ast = 0;
+ return 1;
+ }
+// yydebug = 1;
+ Lexer l(&inf);
+ l.set_debug(debug);
+ int depth = 0;
+ QValueStack<ProjectAST*> stack;
+ Parser p(&l, stack, depth);
+ p.set_debug_level(debug);
+ int ret = p.parse();
+ *ast = stack.top();
+ (*ast)->setFileName(fileName);
+ switch( l.lineending() )
+ {
+ case QMake::Lexer::Windows:
+ (*ast)->setLineEnding(QMake::ProjectAST::Windows);
+ break;
+ case QMake::Lexer::MacOS:
+ (*ast)->setLineEnding(QMake::ProjectAST::MacOS);
+ break;
+ case QMake::Lexer::Unix:
+ default:
+ (*ast)->setLineEnding(QMake::ProjectAST::Unix);
+ break;
+ }
+ return ret;
+}
+
+int Driver::parseFile(QString fileName, ProjectAST **ast, int debug)
+{
+ return parseFile(fileName.ascii(), ast, debug);
+}
+
+int Driver::parseFile(KURL fileName, ProjectAST **ast, int debug)
+{
+ QString tmpFile;
+ int ret = 0;
+ if (KIO::NetAccess::download(fileName, tmpFile, 0))
+ ret = parseFile(tmpFile, ast, debug);
+ KIO::NetAccess::removeTempFile(tmpFile);
+ return ret;
+}
+
+int Driver::parseString( const char* string, ProjectAST **ast, int debug )
+{
+ std::istringstream ins;
+ ins.str(string);
+ Lexer l(&ins);
+ l.set_debug(debug);
+ int depth = 0;
+ QValueStack<ProjectAST*> stack;
+ Parser p(&l, stack, depth);
+ p.set_debug_level(debug);
+ int ret = p.parse();
+ *ast = stack.top();
+ (*ast)->setFileName("");
+ switch( l.lineending() )
+ {
+ case QMake::Lexer::Windows:
+ (*ast)->setLineEnding(QMake::ProjectAST::Windows);
+ break;
+ case QMake::Lexer::MacOS:
+ (*ast)->setLineEnding(QMake::ProjectAST::MacOS);
+ break;
+ case QMake::Lexer::Unix:
+ default:
+ (*ast)->setLineEnding(QMake::ProjectAST::Unix);
+ break;
+ }
+ return ret;
+}
+
+}
diff --git a/buildtools/lib/parsers/qmake/qmakedriver.h b/buildtools/lib/parsers/qmake/qmakedriver.h
new file mode 100644
index 00000000..a1cdc9d9
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/qmakedriver.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef QMAKEQMAKEDRIVER_H
+#define QMAKEQMAKEDRIVER_H
+
+class QString;
+class KURL;
+
+namespace QMake {
+
+/**
+@file qmakedriver.h
+Driver for a qmake parser.
+*/
+
+class ProjectAST;
+
+/**
+Driver.
+Use methods of this class to lauch parsing and build the AST.
+*/
+class Driver{
+public:
+ /**Parses the file @p fileName and stores the resulting ProjectAST root
+ into @p ast. @p ast should not be initialized before. Driver will
+ initialize it on its own.
+ @return The result of parsing. Result is 0 on success and <> 0 on failure.
+ */
+ static int parseFile(const char *fileName, ProjectAST **ast, int debug);
+ static int parseFile(QString fileName, ProjectAST **ast, int debug);
+ static int parseFile(KURL fileName, ProjectAST **ast, int debug);
+ static int parseString(const char* string, ProjectAST **ast, int debug);
+
+};
+
+}
+
+#endif
diff --git a/buildtools/lib/parsers/qmake/stack.hh b/buildtools/lib/parsers/qmake/stack.hh
new file mode 100644
index 00000000..b81e4a28
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/stack.hh
@@ -0,0 +1,129 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Stack handling for Bison parsers in C++
+
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef BISON_STACK_HH
+# define BISON_STACK_HH
+
+#include <deque>
+
+namespace QMake
+{
+ template <class T, class S = std::deque<T> >
+ class stack
+ {
+ public:
+
+ // Hide our reversed order.
+ typedef typename S::reverse_iterator iterator;
+ typedef typename S::const_reverse_iterator const_iterator;
+
+ stack () : seq_ ()
+ {
+ }
+
+ stack (unsigned int n) : seq_ (n)
+ {
+ }
+
+ inline
+ T&
+ operator [] (unsigned int i)
+ {
+ return seq_[i];
+ }
+
+ inline
+ const T&
+ operator [] (unsigned int i) const
+ {
+ return seq_[i];
+ }
+
+ inline
+ void
+ push (const T& t)
+ {
+ seq_.push_front (t);
+ }
+
+ inline
+ void
+ pop (unsigned int n = 1)
+ {
+ for (; n; --n)
+ seq_.pop_front ();
+ }
+
+ inline
+ unsigned int
+ height () const
+ {
+ return seq_.size ();
+ }
+
+ inline const_iterator begin () const { return seq_.rbegin (); }
+ inline const_iterator end () const { return seq_.rend (); }
+
+ private:
+
+ S seq_;
+ };
+
+ /// Present a slice of the top of a stack.
+ template <class T, class S = stack<T> >
+ class slice
+ {
+ public:
+
+ slice (const S& stack,
+ unsigned int range) : stack_ (stack),
+ range_ (range)
+ {
+ }
+
+ inline
+ const T&
+ operator [] (unsigned int i) const
+ {
+ return stack_[range_ - i];
+ }
+
+ private:
+
+ const S& stack_;
+ unsigned int range_;
+ };
+}
+
+#endif // not BISON_STACK_HH
diff --git a/buildtools/lib/parsers/qmake/tests/Makefile.am b/buildtools/lib/parsers/qmake/tests/Makefile.am
new file mode 100644
index 00000000..a73f8f4e
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/tests/Makefile.am
@@ -0,0 +1,21 @@
+# This directory collects some classes related to
+# project management for the sole purpose that they
+# can be shared between parts.
+
+INCLUDES = -I$(top_srcdir)/lib/interfaces \
+ -I$(top_srcdir)/lib/interfaces/extensions -I$(top_srcdir)/lib/util -I$(top_srcdir)/lib/widgets/propeditor \
+ -I$(top_srcdir)/buildtools/lib/parsers/qmake \
+ -I$(top_builddir)/buildtools/lib/parsers/qmake/tests \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+noinst_PROGRAMS = runner viewer
+
+runner_LDFLAGS = $(all_libraries) $(LIB_KDECORE) $(KDE_RPATH)
+runner_LDADD = $(top_builddir)/buildtools/lib/parsers/qmake/libkdevqmakeparser.la
+runner_SOURCES = runner.cpp
+
+viewer_LDFLAGS = --no-undefined $(all_libraries) $(LIB_KDECORE) $(KDE_RPATH)
+viewer_LDADD = $(top_builddir)/buildtools/lib/parsers/qmake/libkdevqmakeparser.la
+viewer_SOURCES = viewer.cpp viewer_main.cpp viewerbase.ui
diff --git a/buildtools/lib/parsers/qmake/tests/runner.cpp b/buildtools/lib/parsers/qmake/tests/runner.cpp
new file mode 100644
index 00000000..b01284f1
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/tests/runner.cpp
@@ -0,0 +1,169 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <cstdlib>
+#include <iostream>
+#include <stdio.h>
+#include "qmakedriver.h"
+#include "qmakeastvisitor.h"
+
+#include <qstring.h>
+
+#include <kdebug.h>
+#include <kcmdlineargs.h>
+#include <kurl.h>
+
+static const KCmdLineOptions options[] =
+{
+ {"silent", "Enable Parser debug output", 0},
+ {"!debug", "Disable output of the generated AST", 0},
+ {"!+files", "QMake project files", 0}
+};
+
+
+class PrintAST : QMake::ASTVisitor
+{
+public:
+ PrintAST() : QMake::ASTVisitor()
+ {
+ indent = 0;
+ }
+
+ virtual void processProject( QMake::ProjectAST* p )
+ {
+ QMake::ASTVisitor::processProject(p);
+ }
+private:
+ virtual void enterRealProject( QMake::ProjectAST* p )
+ {
+ kdDebug(9024) << getIndent() << "--------- Entering Project: " << replaceWs(p->fileName()) << "| LineEnding:" << p->lineEnding() << " --------------" << endl;
+ indent += 4;
+ QMake::ASTVisitor::enterRealProject(p);
+ }
+
+ virtual void leaveRealProject( QMake::ProjectAST* p )
+ {
+ indent -= 4;
+ kdDebug(9024) << getIndent() << "--------- Leaving Project: " << replaceWs(p->fileName()) << " --------------" << endl;
+ QMake::ASTVisitor::leaveRealProject(p);
+ }
+
+ virtual void enterScope( QMake::ProjectAST* p )
+ {
+ kdDebug(9024) << getIndent() << "--------- Entering Scope: " << replaceWs(p->scopedID) << " --------------" << endl;
+ indent += 4;
+ QMake::ASTVisitor::enterScope(p);
+ }
+
+ virtual void leaveScope( QMake::ProjectAST* p )
+ {
+ indent -= 4;
+ kdDebug(9024) << getIndent() << "--------- Leaving Scope: " << replaceWs(p->scopedID) << " --------------" << endl;
+ QMake::ASTVisitor::leaveScope(p);
+ }
+
+ virtual void enterFunctionScope( QMake::ProjectAST* p )
+ {
+ kdDebug(9024) << getIndent() << "--------- Entering FunctionScope: " << replaceWs(p->scopedID) << "(" << replaceWs(p->args) << ")"<< " --------------" << endl;
+ indent += 4;
+ QMake::ASTVisitor::enterFunctionScope(p);
+ }
+
+ virtual void leaveFunctionScope( QMake::ProjectAST* p )
+ {
+ indent -= 4;
+ kdDebug(9024) << getIndent() << "--------- Leaving FunctionScope: " << replaceWs(p->scopedID) << "(" << replaceWs(p->args) << ")"<< " --------------" << endl;
+ QMake::ASTVisitor::leaveFunctionScope(p);
+ }
+
+ QString replaceWs(QString s)
+ {
+ return s.replace("\n", "%nl").replace("\t", "%tab").replace(" ", "%spc");
+ }
+
+ virtual void processAssignment( QMake::AssignmentAST* a)
+ {
+ kdDebug(9024) << getIndent() << "Assignment(" << replaceWs(a->indent) << "):" << replaceWs(a->scopedID) << " " << replaceWs(a->op) << " " << replaceWs(a->values.join("|")) << endl;
+ QMake::ASTVisitor::processAssignment(a);
+ }
+
+ virtual void processNewLine( QMake::NewLineAST* n)
+ {
+ kdDebug(9024) << getIndent() << "Newline " << endl;
+ QMake::ASTVisitor::processNewLine(n);
+ }
+
+ virtual void processComment( QMake::CommentAST* a)
+ {
+ kdDebug(9024) << getIndent() << "Comment: " << replaceWs(a->comment) << endl;
+ QMake::ASTVisitor::processComment(a);
+ }
+
+ virtual void processInclude( QMake::IncludeAST* a)
+ {
+ kdDebug(9024) << getIndent() << "Include: " << replaceWs(a->projectName) << endl;
+ QMake::ASTVisitor::processInclude(a);
+ }
+
+ QString getIndent()
+ {
+ QString ind;
+ for( int i = 0 ; i < indent ; i++)
+ ind += " ";
+ return ind;
+ }
+ int indent;
+};
+int main(int argc, char *argv[])
+{
+ KCmdLineArgs::init( argc, argv, "QMake Parser", "qmake-parser", "Parse QMake project files", "1.0.0");
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if( args->count() < 1 )
+ {
+ KCmdLineArgs::usage(0);
+ }
+
+ int debug = 0;
+ bool silent = false;
+
+ if( args->isSet("silent") )
+ silent = true;
+ if( args->isSet("debug") )
+ debug = 1;
+ for( int i = 0 ; i < args->count() ; i++ )
+ {
+ QMake::ProjectAST *projectAST;
+ int ret = QMake::Driver::parseFile(args->url(i).path(), &projectAST, debug);
+ PrintAST pa;
+ if ( ret == 0 )
+ if ( !silent )
+ {
+ pa.processProject(projectAST);
+ QString profile;
+ projectAST->writeBack(profile);
+ kdDebug(9024) << "QMake file written back:\n" << profile << endl;
+ }
+ return ret;
+ }
+ return 0;
+}
diff --git a/buildtools/lib/parsers/qmake/tests/viewer.cpp b/buildtools/lib/parsers/qmake/tests/viewer.cpp
new file mode 100644
index 00000000..dba2b7fb
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/tests/viewer.cpp
@@ -0,0 +1,182 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "viewer.h"
+
+#include <qdir.h>
+#include <qlineedit.h>
+#include <qlistbox.h>
+#include <qfiledialog.h>
+#include <qtextedit.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qlistview.h>
+#include <qtabwidget.h>
+
+#include <qmakeast.h>
+#include <qmakedriver.h>
+#include <qmakeastvisitor.h>
+
+using namespace QMake;
+
+Viewer::Viewer(QWidget *parent, const char *name)
+ :ViewerBase(parent, name), projectAST(0)
+{
+ if (QFile::exists(QDir::currentDirPath() + "/" + "qtlist"))
+ {
+ QFile f(QDir::currentDirPath() + "/" + "qtlist");
+ f.open(IO_ReadOnly);
+ QTextStream str(&f);
+ while (!str.eof())
+ files->insertItem(str.readLine());
+ }
+ ast->setSorting(-1);
+// parentProject.push((QListViewItem*)0);
+}
+
+void Viewer::addAll_clicked()
+{
+ if (allLocation->text().isEmpty())
+ return;
+ QDir d(allLocation->text());
+ QStringList l = d.entryList("*.pro *.pri");
+ for (QStringList::iterator it = l.begin(); it != l.end(); ++it)
+ (*it) = QDir::cleanDirPath(allLocation->text() + "/" + (*it));
+ files->insertStringList(l);
+}
+
+void Viewer::choose_clicked()
+{
+ QString fileName = QFileDialog::getOpenFileName(QDir::currentDirPath(), "*.pro *.pri", this);
+ if (!fileName.isEmpty())
+ files->insertItem(fileName);
+}
+
+void Viewer::files_currentChanged(QListBoxItem* item)
+{
+ ast->clear();
+
+ QFile f(item->text());
+ f.open(IO_ReadOnly);
+ QTextStream str(&f);
+ source->setText(str.read());
+ f.close();
+
+ int result = QMake::Driver::parseFile(item->text().ascii(), &projectAST, 0);
+ if (projectAST && (result == 0))
+ {
+ processAST(projectAST);
+ }
+ if (tabWidget2->currentPageIndex() == 1)
+ tabWidget2_selected("Source to be written back");
+}
+
+void Viewer::tabWidget2_selected(const QString& text)
+{
+ if ((text == "Source to Be Written Back") && projectAST)
+ {
+ QString buffer;
+ projectAST->writeBack(buffer);
+ writeBack->setText(buffer);
+ }
+}
+
+class ViewerVisitor: public ASTVisitor {
+public:
+ ViewerVisitor(Viewer *v): ASTVisitor()
+ {
+ this->v = v;
+ parentProject.push((QListViewItem*)0);
+ }
+
+ virtual void processProject(ProjectAST *project)
+ {
+ ASTVisitor::processProject(project);
+ }
+
+ virtual void enterRealProject(ProjectAST *project)
+ {
+ QListViewItem *projectIt;
+ if (!parentProject.top())
+ {
+ projectIt = new QListViewItem(v->ast, "Project");
+ projectIt->setOpen(true);
+ parentProject.push(projectIt);
+ }
+
+ ASTVisitor::enterRealProject(project);
+ }
+ virtual void enterScope(ProjectAST *scope)
+ {
+ QListViewItem *projectIt = new QListViewItem(parentProject.top(), scope->scopedID, "scope");
+ parentProject.push(projectIt);
+ ASTVisitor::enterScope(scope);
+ }
+ virtual void leaveScope(ProjectAST *scope)
+ {
+ parentProject.pop();
+ }
+ virtual void enterFunctionScope(ProjectAST *fscope)
+ {
+ QListViewItem *projectIt = new QListViewItem(parentProject.top(),
+ fscope->scopedID + "(" + fscope->args + ")", "function scope");
+ parentProject.push(projectIt);
+ ASTVisitor::enterFunctionScope(fscope);
+ }
+ virtual void leaveFunctionScope(ProjectAST *fscope)
+ {
+ parentProject.pop();
+ }
+ virtual void processAssignment(AssignmentAST *assignment)
+ {
+ QListViewItem *item = new QListViewItem(parentProject.top(),
+ assignment->scopedID, assignment->op, assignment->values.join("|"),
+ "assignment");
+ item->setMultiLinesEnabled(true);
+
+ ASTVisitor::processAssignment(assignment);
+ }
+ virtual void processNewLine(NewLineAST *newline)
+ {
+ new QListViewItem(parentProject.top(), "<newline>");
+ ASTVisitor::processNewLine(newline);
+ }
+ virtual void processComment(CommentAST *comment)
+ {
+ new QListViewItem(parentProject.top(), "<comment>");
+ ASTVisitor::processComment(comment);
+ }
+ virtual void processInclude(IncludeAST *include)
+ {
+ new QListViewItem(parentProject.top(), "<include>", include->projectName);
+ QMake::ASTVisitor::processInclude(include);
+ }
+
+ Viewer *v;
+ QValueStack<QListViewItem *> parentProject;
+};
+
+
+void Viewer::processAST(QMake::ProjectAST *projectAST, QListViewItem *globAfter)
+{
+ ViewerVisitor visitor(this);
+ visitor.processProject(projectAST);
+}
+
+#include "viewer.moc"
diff --git a/buildtools/lib/parsers/qmake/tests/viewer.h b/buildtools/lib/parsers/qmake/tests/viewer.h
new file mode 100644
index 00000000..8d0da49f
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/tests/viewer.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef VIEWER_H
+#define VIEWER_H
+
+#include <qvaluestack.h>
+
+#include "viewerbase.h"
+
+namespace QMake {
+class ProjectAST;
+}
+
+class QListViewItem;
+
+class Viewer: public ViewerBase {
+Q_OBJECT
+public:
+ Viewer(QWidget *parent = 0, const char *name = 0);
+ void processAST(QMake::ProjectAST *projectAST, QListViewItem *globAfter = 0);
+public slots:
+ virtual void tabWidget2_selected(const QString&);
+ virtual void files_currentChanged(QListBoxItem*);
+ virtual void choose_clicked();
+ virtual void addAll_clicked();
+private:
+ QMake::ProjectAST *projectAST;
+ friend class ViewerVisitor;
+};
+
+#endif
diff --git a/buildtools/lib/parsers/qmake/tests/viewer_main.cpp b/buildtools/lib/parsers/qmake/tests/viewer_main.cpp
new file mode 100644
index 00000000..8fdbc910
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/tests/viewer_main.cpp
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Alexander Dymo *
+ * adymo@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Library General Public License as *
+ * published by the Free Software Foundation; either version 2 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include <qapplication.h>
+#include "viewer.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ Viewer viewer;
+ app.setMainWidget(&viewer);
+ viewer.show();
+ viewer.setWindowState(viewer.windowState() | Qt::WindowMaximized);
+
+ return app.exec();
+}
diff --git a/buildtools/lib/parsers/qmake/tests/viewerbase.ui b/buildtools/lib/parsers/qmake/tests/viewerbase.ui
new file mode 100644
index 00000000..976d4d0f
--- /dev/null
+++ b/buildtools/lib/parsers/qmake/tests/viewerbase.ui
@@ -0,0 +1,250 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ViewerBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ViewerBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Viewer</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSplitter" row="0" column="0">
+ <property name="name">
+ <cstring>splitter5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>allLocation</cstring>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>addAll</cstring>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Add All From Directory</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>choose</cstring>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Choose File to Add...</string>
+ </property>
+ </widget>
+ <widget class="QListBox">
+ <property name="name">
+ <cstring>files</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="hScrollBarMode">
+ <enum>Auto</enum>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QSplitter">
+ <property name="name">
+ <cstring>splitter2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <widget class="QTextEdit">
+ <property name="name">
+ <cstring>source</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>2</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Parse Tree</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value 1</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value 2</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value 3</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>ast</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Source to Be Written Back</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTextEdit" row="0" column="0">
+ <property name="name">
+ <cstring>writeBack</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>addAll</sender>
+ <signal>clicked()</signal>
+ <receiver>ViewerBase</receiver>
+ <slot>addAll_clicked()</slot>
+ </connection>
+ <connection>
+ <sender>choose</sender>
+ <signal>clicked()</signal>
+ <receiver>ViewerBase</receiver>
+ <slot>choose_clicked()</slot>
+ </connection>
+ <connection>
+ <sender>files</sender>
+ <signal>currentChanged(QListBoxItem*)</signal>
+ <receiver>ViewerBase</receiver>
+ <slot>files_currentChanged(QListBoxItem*)</slot>
+ </connection>
+ <connection>
+ <sender>tabWidget2</sender>
+ <signal>selected(const QString&amp;)</signal>
+ <receiver>ViewerBase</receiver>
+ <slot>tabWidget2_selected(const QString&amp;)</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>addAll_clicked()</slot>
+ <slot>choose_clicked()</slot>
+ <slot>files_currentChanged( QListBoxItem * )</slot>
+ <slot>tabWidget2_selected( const QString &amp; )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>