aboutsummaryrefslogtreecommitdiffstats
path: root/parser/rpp
diff options
context:
space:
mode:
Diffstat (limited to 'parser/rpp')
-rw-r--r--parser/rpp/builtin-macros.cpp23
-rw-r--r--parser/rpp/pp-cctype.h57
-rw-r--r--parser/rpp/pp-configuration86
-rw-r--r--parser/rpp/pp-engine-bits.h1252
-rw-r--r--parser/rpp/pp-engine.h274
-rw-r--r--parser/rpp/pp-environment.h137
-rw-r--r--parser/rpp/pp-fwd.h39
-rw-r--r--parser/rpp/pp-internal.h117
-rw-r--r--parser/rpp/pp-iterator.h88
-rw-r--r--parser/rpp/pp-macro-expander.h351
-rw-r--r--parser/rpp/pp-macro.h72
-rw-r--r--parser/rpp/pp-main.cpp295
-rw-r--r--parser/rpp/pp-qt-configuration24
-rw-r--r--parser/rpp/pp-scanner.h313
-rw-r--r--parser/rpp/pp-string.h107
-rw-r--r--parser/rpp/pp-symbol.h87
-rw-r--r--parser/rpp/pp.h91
-rw-r--r--parser/rpp/preprocessor.cpp158
-rw-r--r--parser/rpp/preprocessor.h66
19 files changed, 3637 insertions, 0 deletions
diff --git a/parser/rpp/builtin-macros.cpp b/parser/rpp/builtin-macros.cpp
new file mode 100644
index 000000000..1b0fc06af
--- /dev/null
+++ b/parser/rpp/builtin-macros.cpp
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
diff --git a/parser/rpp/pp-cctype.h b/parser/rpp/pp-cctype.h
new file mode 100644
index 000000000..5b0bf477c
--- /dev/null
+++ b/parser/rpp/pp-cctype.h
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_CCTYPE_H
+#define PP_CCTYPE_H
+
+#include <cctype>
+
+namespace rpp
+{
+
+inline bool pp_isalpha(int __ch)
+{
+ return std::isalpha((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isalnum(int __ch)
+{
+ return std::isalnum((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isdigit(int __ch)
+{
+ return std::isdigit((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isspace(int __ch)
+{
+ return std::isspace((unsigned char) __ch) != 0;
+}
+
+} // namespace rpp
+
+#endif // PP_CCTYPE_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-configuration b/parser/rpp/pp-configuration
new file mode 100644
index 000000000..15586dd88
--- /dev/null
+++ b/parser/rpp/pp-configuration
@@ -0,0 +1,86 @@
+#define __DBL_MIN_EXP__ (-1021)
+#define __FLT_MIN__ 1.17549435e-38F
+#define __CHAR_BIT__ 8
+#define __WCHAR_MAX__ 2147483647
+#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+#define __FLT_EVAL_METHOD__ 2
+#define __DBL_MIN_10_EXP__ (-307)
+#define __FINITE_MATH_ONLY__ 0
+#define __GNUC_PATCHLEVEL__ 2
+#define __SHRT_MAX__ 32767
+#define __LDBL_MAX__ 1.18973149535723176502e+4932L
+#define __UINTMAX_TYPE__ long long unsigned int
+#define __linux 1
+#define __unix 1
+#define __LDBL_MAX_EXP__ 16384
+#define __linux__ 1
+#define __SCHAR_MAX__ 127
+#define __USER_LABEL_PREFIX__
+#define __STDC_HOSTED__ 1
+#define __LDBL_HAS_INFINITY__ 1
+#define __DBL_DIG__ 15
+#define __FLT_EPSILON__ 1.19209290e-7F
+#define __GXX_WEAK__ 1
+#define __LDBL_MIN__ 3.36210314311209350626e-4932L
+#define __unix__ 1
+#define __DECIMAL_DIG__ 21
+#define __gnu_linux__ 1
+#define __LDBL_HAS_QUIET_NAN__ 1
+#define __GNUC__ 4
+#define __DBL_MAX__ 1.7976931348623157e+308
+#define __DBL_HAS_INFINITY__ 1
+#define __cplusplus 1
+#define __DEPRECATED 1
+#define __DBL_MAX_EXP__ 1024
+#define __GNUG__ 4
+#define __LONG_LONG_MAX__ 9223372036854775807LL
+#define __GXX_ABI_VERSION 1002
+#define __FLT_MIN_EXP__ (-125)
+#define __DBL_MIN__ 2.2250738585072014e-308
+#define __FLT_MIN_10_EXP__ (-37)
+#define __DBL_HAS_QUIET_NAN__ 1
+#define __REGISTER_PREFIX__
+#define __NO_INLINE__ 1
+#define __i386 1
+#define __FLT_MANT_DIG__ 24
+#define __VERSION__ "4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)"
+#define i386 1
+#define __i486__ 1
+#define unix 1
+#define __i386__ 1
+#define __SIZE_TYPE__ unsigned int
+#define __ELF__ 1
+#define __FLT_RADIX__ 2
+#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
+#define __FLT_HAS_QUIET_NAN__ 1
+#define __FLT_MAX_10_EXP__ 38
+#define __LONG_MAX__ 2147483647L
+#define __FLT_HAS_INFINITY__ 1
+#define linux 1
+#define __EXCEPTIONS 1
+#define __LDBL_MANT_DIG__ 64
+#define __WCHAR_TYPE__ int
+#define __FLT_DIG__ 6
+#define __INT_MAX__ 2147483647
+#define __i486 1
+#define __FLT_MAX_EXP__ 128
+#define __DBL_MANT_DIG__ 53
+#define __WINT_TYPE__ unsigned int
+#define __LDBL_MIN_EXP__ (-16381)
+#define __LDBL_MAX_10_EXP__ 4932
+#define __DBL_EPSILON__ 2.2204460492503131e-16
+#define __tune_i486__ 1
+#define __INTMAX_MAX__ 9223372036854775807LL
+#define __FLT_DENORM_MIN__ 1.40129846e-45F
+#define __FLT_MAX__ 3.40282347e+38F
+#define __INTMAX_TYPE__ long long int
+#define __GNUC_MINOR__ 0
+#define __DBL_MAX_10_EXP__ 308
+#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+#define __PTRDIFF_TYPE__ int
+#define __LDBL_MIN_10_EXP__ (-4931)
+#define __LDBL_DIG__ 18
+#define _GNU_SOURCE 1
+
+
+#define __STDC__
diff --git a/parser/rpp/pp-engine-bits.h b/parser/rpp/pp-engine-bits.h
new file mode 100644
index 000000000..7594ab796
--- /dev/null
+++ b/parser/rpp/pp-engine-bits.h
@@ -0,0 +1,1252 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_ENGINE_BITS_H
+#define PP_ENGINE_BITS_H
+
+#include "pp.h"
+#include <sys/stat.h>
+#include <cstdio>
+#include <iostream>
+
+namespace rpp
+{
+
+inline std::string pp::fix_file_path(std::string const &filename) const
+{
+#if defined (PP_OS_WIN)
+ std::string s = filename;
+ for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
+ if (*it == '/')
+ *it = '\\';
+ }
+ return s;
+#else
+ return filename;
+#endif
+}
+
+inline bool pp::is_absolute(std::string const &filename) const
+{
+#if defined(PP_OS_WIN)
+ return filename.length() >= 3
+ && filename.at(1) == ':'
+ && (filename.at(2) == '\\' || filename.at(2) == '/');
+#else
+ return filename.length() >= 1
+ && filename.at(0) == '/';
+#endif
+}
+
+template <typename _OutputIterator>
+void pp::file(std::string const &filename, _OutputIterator __result)
+{
+ FILE *fp = std::fopen(filename.c_str(), "rb");
+ if (fp != 0) {
+ std::string was = env.current_file;
+ env.current_file = filename;
+ file(fp, __result);
+ env.current_file = was;
+ }
+ //else
+ //std::cerr << "** WARNING file ``" << filename << " not found!" << std::endl;
+}
+
+template <typename _OutputIterator>
+void pp::file(FILE *fp, _OutputIterator __result)
+{
+ assert(fp != 0);
+
+#if defined (HAVE_MMAP)
+ struct stat st;
+ fstat(FILENO(fp), &st);
+ std::size_t size = st.st_size;
+ char *buffer = 0;
+ buffer = (char *) ::mmap(0, size, PROT_READ, MAP_SHARED, FILENO(fp), 0);
+ fclose(fp);
+ if (!buffer || buffer == (char*) - 1)
+ return;
+ this->operator()(buffer, buffer + size, __result);
+ ::munmap(buffer, size);
+#else
+ std::string buffer;
+ while (!feof(fp)) {
+ char tmp[1024];
+ int read = (int) fread(tmp, sizeof(char), 1023, fp);
+ tmp[read] = '\0';
+ buffer += tmp;
+ }
+ fclose(fp);
+ this->operator()(buffer.c_str(), buffer.c_str() + buffer.size(), __result);
+#endif
+}
+
+template <typename _InputIterator>
+bool pp::find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot)
+{
+ int was = env.current_line;
+
+ while (__first != __last) {
+ if (pp_isspace(*__first)) {
+ if (*__first == '\n')
+ ++env.current_line;
+
+ ++__first;
+ } else if (_PP_internal::comment_p(__first, __last)) {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ } else if (*__first == '#') {
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first != __last && *__first == 'i') {
+ _InputIterator __begin = __first;
+ __first = skip_identifier(__begin, __last);
+ env.current_line += skip_identifier.lines;
+
+ std::string __directive(__begin, __first);
+
+ if (__directive == "ifndef") {
+ __first = skip_blanks(__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ __begin = __first;
+ __first = skip_identifier(__first, __last);
+ env.current_line += skip_identifier.lines;
+
+ if (__begin != __first && __first != __last) {
+ __prot->assign(__begin, __first);
+ return true;
+ }
+ }
+ }
+ break;
+ } else
+ break;
+ }
+
+ env.current_line = was;
+ return false;
+}
+
+inline pp::PP_DIRECTIVE_TYPE pp::find_directive(char const *__directive, std::size_t __size) const
+{
+ switch (__size) {
+ case 2:
+ if (__directive[0] == 'i'
+ && __directive[1] == 'f')
+ return PP_IF;
+ break;
+
+ case 4:
+ if (__directive[0] == 'e' && !strcmp(__directive, "elif"))
+ return PP_ELIF;
+ else if (__directive[0] == 'e' && !strcmp(__directive, "else"))
+ return PP_ELSE;
+ break;
+
+ case 5:
+ if (__directive[0] == 'i' && !strcmp(__directive, "ifdef"))
+ return PP_IFDEF;
+ else if (__directive[0] == 'u' && !strcmp(__directive, "undef"))
+ return PP_UNDEF;
+ else if (__directive[0] == 'e') {
+ if (!strcmp(__directive, "endif"))
+ return PP_ENDIF;
+ else if (!strcmp(__directive, "error"))
+ return PP_ERROR;
+ }
+ break;
+
+ case 6:
+ if (__directive[0] == 'i' && !strcmp(__directive, "ifndef"))
+ return PP_IFNDEF;
+ else if (__directive[0] == 'd' && !strcmp(__directive, "define"))
+ return PP_DEFINE;
+ else if (__directive[0] == 'p' && !strcmp(__directive, "pragma"))
+ return PP_PRAGMA;
+ break;
+
+ case 7:
+ if (__directive[0] == 'i' && !strcmp(__directive, "include"))
+ return PP_INCLUDE;
+ else if (!strcmp(__directive, "warning"))
+ return PP_WARNING;
+ break;
+
+ case 12:
+ if (__directive[0] == 'i' && !strcmp(__directive, "include_next"))
+ return PP_INCLUDE_NEXT;
+ break;
+
+ default:
+ break;
+ }
+ std::cerr << "** WARNING unknown directive '#" << __directive << "' at " << env.current_file << ":" << env.current_line << std::endl;
+ return PP_UNKNOWN_DIRECTIVE;
+}
+
+inline bool pp::file_isdir(std::string const &__filename) const
+{
+ struct stat __st;
+#if defined(PP_OS_WIN)
+ if (stat(__filename.c_str(), &__st) == 0)
+ return (__st.st_mode & _S_IFDIR) == _S_IFDIR;
+ else
+ return false;
+#else
+ if (lstat(__filename.c_str(), &__st) == 0)
+ return (__st.st_mode & S_IFDIR) == S_IFDIR;
+ else
+ return false;
+#endif
+}
+
+inline bool pp::file_exists(std::string const &__filename) const
+{
+ struct stat __st;
+#if defined(PP_OS_WIN)
+ return stat(__filename.c_str(), &__st) == 0;
+#else
+ return lstat(__filename.c_str(), &__st) == 0;
+#endif
+}
+
+inline FILE *pp::find_include_file(std::string const &__input_filename, std::string *__filepath,
+ INCLUDE_POLICY __include_policy, bool __skip_current_path) const
+{
+ assert(__filepath != 0);
+ assert(! __input_filename.empty());
+
+ __filepath->assign(__input_filename);
+
+ if (is_absolute(*__filepath))
+ return std::fopen(__filepath->c_str(), "r");
+
+ if (! env.current_file.empty())
+ _PP_internal::extract_file_path(env.current_file, __filepath);
+
+ if (__include_policy == INCLUDE_LOCAL && ! __skip_current_path) {
+ std::string __tmp(*__filepath);
+ __tmp += __input_filename;
+
+ if (file_exists(__tmp) && !file_isdir(__tmp)) {
+ __filepath->append(__input_filename);
+ return std::fopen(__filepath->c_str(), "r");
+ }
+ }
+
+ std::vector<std::string>::const_iterator it = include_paths.begin();
+
+ if (__skip_current_path) {
+ it = std::find(include_paths.begin(), include_paths.end(), *__filepath);
+
+ if (it != include_paths.end())
+ ++it;
+
+ else
+ it = include_paths.begin();
+ }
+
+ for (; it != include_paths.end(); ++it) {
+ if (__skip_current_path && it == include_paths.begin())
+ continue;
+
+ __filepath->assign(*it);
+ __filepath->append(__input_filename);
+
+ if (file_exists(*__filepath) && !file_isdir(*__filepath))
+ return std::fopen(__filepath->c_str(), "r");
+
+#ifdef Q_OS_MAC
+ // try in Framework path on Mac, if there is a path in front
+ // ### what about escaped slashes?
+ size_t slashPos = __input_filename.find('/');
+ if (slashPos != std::string::npos) {
+ __filepath->assign(*it);
+ __filepath->append(__input_filename.substr(0, slashPos));
+ __filepath->append(".framework/Headers/");
+ __filepath->append(__input_filename.substr(slashPos + 1, std::string::npos));
+ std::cerr << *__filepath << "\n";
+
+ if (file_exists(*__filepath) && !file_isdir(*__filepath))
+ return fopen(__filepath->c_str(), "r");
+ }
+#endif // Q_OS_MAC
+ }
+
+ return 0;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+_InputIterator pp::handle_directive(char const *__directive, std::size_t __size,
+ _InputIterator __first, _InputIterator __last, _OutputIterator __result)
+{
+ __first = skip_blanks(__first, __last);
+
+ PP_DIRECTIVE_TYPE d = find_directive(__directive, __size);
+ switch (d) {
+ case PP_DEFINE:
+ if (! skipping())
+ return handle_define(__first, __last);
+ break;
+
+ case PP_INCLUDE:
+ case PP_INCLUDE_NEXT:
+ if (! skipping())
+ return handle_include(d == PP_INCLUDE_NEXT, __first, __last, __result);
+ break;
+
+ case PP_UNDEF:
+ if (! skipping())
+ return handle_undef(__first, __last);
+ break;
+
+ case PP_ELIF:
+ return handle_elif(__first, __last);
+
+ case PP_ELSE:
+ return handle_else(__first, __last);
+
+ case PP_ENDIF:
+ return handle_endif(__first, __last);
+
+ case PP_IF:
+ return handle_if(__first, __last);
+
+ case PP_IFDEF:
+ return handle_ifdef(false, __first, __last);
+
+ case PP_IFNDEF:
+ return handle_ifdef(true, __first, __last);
+
+ default:
+ break;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+_InputIterator pp::handle_include(bool __skip_current_path, _InputIterator __first, _InputIterator __last,
+ _OutputIterator __result)
+{
+ if (pp_isalpha(*__first) || *__first == '_') {
+ pp_macro_expander expand_include(env);
+ std::string name;
+ name.reserve(255);
+ expand_include(__first, __last, std::back_inserter(name));
+ std::string::iterator it = skip_blanks(name.begin(), name.end());
+ assert(it != name.end() && (*it == '<' || *it == '"'));
+ handle_include(__skip_current_path, it, name.end(), __result);
+ return __first;
+ }
+
+ assert(*__first == '<' || *__first == '"');
+ int quote = (*__first == '"') ? '"' : '>';
+ ++__first;
+
+ _InputIterator end_name = __first;
+ for (; end_name != __last; ++end_name) {
+ assert(*end_name != '\n');
+
+ if (*end_name == quote)
+ break;
+ }
+
+ std::string filename(__first, end_name);
+
+#ifdef PP_OS_WIN
+ std::replace(filename.begin(), filename.end(), '/', '\\');
+#endif
+
+ std::string filepath;
+ FILE *fp = find_include_file(filename, &filepath, quote == '>' ? INCLUDE_GLOBAL : INCLUDE_LOCAL, __skip_current_path);
+
+#if defined (PP_HOOK_ON_FILE_INCLUDED)
+ PP_HOOK_ON_FILE_INCLUDED(env.current_file, fp ? filepath : filename, fp);
+#endif
+
+ if (fp != 0) {
+ std::string old_file = env.current_file;
+ env.current_file = filepath;
+ int __saved_lines = env.current_line;
+
+ env.current_line = 1;
+ //output_line (env.current_file, 1, __result);
+
+ file(fp, __result);
+
+ // restore the file name and the line position
+ env.current_file = old_file;
+ env.current_line = __saved_lines;
+
+ // sync the buffer
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+#ifndef RPP_JAMBI
+// else
+// std::cerr << "*** WARNING " << filename << ": No such file or directory" << std::endl;
+#endif
+
+ return __first;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+void pp::operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
+{
+#ifndef PP_NO_SMART_HEADER_PROTECTION
+ std::string __prot;
+ __prot.reserve(255);
+ pp_fast_string __tmp(__prot.c_str(), __prot.size());
+
+ if (find_header_protection(__first, __last, &__prot)
+ && env.resolve(&__tmp) != 0) {
+ // std::cerr << "** DEBUG found header protection:" << __prot << std::endl;
+ return;
+ }
+#endif
+
+ env.current_line = 1;
+ char __buffer[512];
+
+ while (true) {
+ __first = skip_blanks(__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first == __last)
+ break;
+ else if (*__first == '#') {
+ assert(*__first == '#');
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ _InputIterator end_id = skip_identifier(__first, __last);
+ env.current_line += skip_identifier.lines;
+ std::size_t __size = end_id - __first;
+
+ assert(__size < 512);
+ char *__cp = __buffer;
+ std::copy(__first, end_id, __cp);
+ __cp[__size] = '\0';
+
+ end_id = skip_blanks(end_id, __last);
+ __first = skip(end_id, __last);
+
+ int was = env.current_line;
+ (void) handle_directive(__buffer, __size, end_id, __first, __result);
+
+ if (env.current_line != was) {
+ env.current_line = was;
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+ } else if (*__first == '\n') {
+ // ### compress the line
+ *__result++ = *__first++;
+ ++env.current_line;
+ } else if (skipping())
+ __first = skip(__first, __last);
+ else {
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ __first = expand(__first, __last, __result);
+ env.current_line += expand.lines;
+
+ if (expand.generated_lines)
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+ }
+}
+
+inline pp::pp(pp_environment &__env):
+ env(__env), expand(env)
+{
+ iflevel = 0;
+ _M_skipping[iflevel] = 0;
+ _M_true_test[iflevel] = 0;
+}
+
+inline std::back_insert_iterator<std::vector<std::string> > pp::include_paths_inserter()
+{
+ return std::back_inserter(include_paths);
+}
+
+inline std::vector<std::string>::iterator pp::include_paths_begin()
+{
+ return include_paths.begin();
+}
+
+inline std::vector<std::string>::iterator pp::include_paths_end()
+{
+ return include_paths.end();
+}
+
+inline std::vector<std::string>::const_iterator pp::include_paths_begin() const
+{
+ return include_paths.begin();
+}
+
+inline std::vector<std::string>::const_iterator pp::include_paths_end() const
+{
+ return include_paths.end();
+}
+
+inline void pp::push_include_path(std::string const &__path)
+{
+ if (__path.empty() || __path [__path.size() - 1] != PATH_SEPARATOR) {
+ std::string __tmp(__path);
+ __tmp += PATH_SEPARATOR;
+ include_paths.push_back(__tmp);
+ }
+
+ else
+ include_paths.push_back(__path);
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_define(_InputIterator __first, _InputIterator __last)
+{
+ pp_macro macro;
+#if defined (PP_WITH_MACRO_POSITION)
+ macro.file = pp_symbol::get(env.current_file);
+#endif
+ std::string definition;
+
+ __first = skip_blanks(__first, __last);
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+ pp_fast_string const *macro_name = pp_symbol::get(__first, end_macro_name);
+ __first = end_macro_name;
+
+ if (__first != __last && *__first == '(') {
+ macro.function_like = true;
+ macro.formals.reserve(5);
+
+ __first = skip_blanks(++__first, __last); // skip '('
+ _InputIterator arg_end = skip_identifier(__first, __last);
+ if (__first != arg_end)
+ macro.formals.push_back(pp_symbol::get(__first, arg_end));
+
+ __first = skip_blanks(arg_end, __last);
+
+ if (*__first == '.') {
+ macro.variadics = true;
+ while (*__first == '.')
+ ++__first;
+ }
+
+ while (__first != __last && *__first == ',') {
+ __first = skip_blanks(++__first, __last);
+
+ arg_end = skip_identifier(__first, __last);
+ if (__first != arg_end)
+ macro.formals.push_back(pp_symbol::get(__first, arg_end));
+
+ __first = skip_blanks(arg_end, __last);
+
+ if (*__first == '.') {
+ macro.variadics = true;
+ while (*__first == '.')
+ ++__first;
+ }
+ }
+
+ assert(*__first == ')');
+ ++__first;
+ }
+
+ __first = skip_blanks(__first, __last);
+
+ while (__first != __last && *__first != '\n') {
+ if (*__first == '/') {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ }
+
+ if (*__first == '\\') {
+ _InputIterator __begin = __first;
+ __begin = skip_blanks(++__begin, __last);
+
+ if (__begin != __last && *__begin == '\n') {
+ ++macro.lines;
+ __first = skip_blanks(++__begin, __last);
+ definition += ' ';
+ continue;
+ }
+ }
+
+ definition += *__first++;
+ }
+
+ macro.definition = pp_symbol::get(definition);
+ env.bind(macro_name, macro);
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::skip(_InputIterator __first, _InputIterator __last)
+{
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+
+ while (__first != __last && *__first != '\n') {
+ if (*__first == '/') {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ } else if (*__first == '"') {
+ __first = skip_string_literal(__first, __last);
+ env.current_line += skip_string_literal.lines;
+ } else if (*__first == '\'') {
+ __first = skip_char_literal(__first, __last);
+ env.current_line += skip_char_literal.lines;
+ } else if (*__first == '\\') {
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first != __last && *__first == '\n') {
+ ++__first;
+ ++env.current_line;
+ }
+ } else
+ ++__first;
+ }
+
+ return __first;
+}
+
+inline bool pp::test_if_level()
+{
+ bool result = !_M_skipping[iflevel++];
+ _M_skipping[iflevel] = _M_skipping[iflevel - 1];
+ _M_true_test[iflevel] = false;
+ return result;
+}
+
+inline int pp::skipping() const
+{
+ return _M_skipping[iflevel];
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_primary(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ bool expect_paren = false;
+ int token;
+ __first = next_token(__first, __last, &token);
+
+ switch (token) {
+ case TOKEN_NUMBER:
+ result->set_long(token_value);
+ break;
+
+ case TOKEN_UNUMBER:
+ result->set_ulong(token_uvalue);
+ break;
+
+ case TOKEN_DEFINED:
+ __first = next_token(__first, __last, &token);
+
+ if (token == '(') {
+ expect_paren = true;
+ __first = next_token(__first, __last, &token);
+ }
+
+ if (token != TOKEN_IDENTIFIER) {
+ std::cerr << "** WARNING expected ``identifier'' found:" << char(token) << std::endl;
+ result->set_long(0);
+ break;
+ }
+
+ result->set_long(env.resolve(token_text->c_str(), token_text->size()) != 0);
+
+ next_token(__first, __last, &token); // skip '('
+
+ if (expect_paren) {
+ _InputIterator next = next_token(__first, __last, &token);
+ if (token != ')')
+ std::cerr << "** WARNING expected ``)''" << std::endl;
+ else
+ __first = next;
+ }
+ break;
+
+ case TOKEN_IDENTIFIER:
+ result->set_long(0);
+ break;
+
+ case '-':
+ __first = eval_primary(__first, __last, result);
+ result->set_long(- result->l);
+ return __first;
+
+ case '+':
+ __first = eval_primary(__first, __last, result);
+ return __first;
+
+ case '!':
+ __first = eval_primary(__first, __last, result);
+ result->set_long(result->is_zero());
+ return __first;
+
+ case '(':
+ __first = eval_constant_expression(__first, __last, result);
+ next_token(__first, __last, &token);
+
+ if (token != ')')
+ std::cerr << "** WARNING expected ``)'' = " << token << std::endl;
+ else
+ __first = next_token(__first, __last, &token);
+ break;
+
+ default:
+ result->set_long(0);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_primary(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '*' || token == '/' || token == '%') {
+ Value value;
+ __first = eval_primary(next, __last, &value);
+
+ if (token == '*')
+ result->op_mult(value);
+ else if (token == '/') {
+ if (value.is_zero()) {
+ std::cerr << "** WARNING division by zero" << std::endl;
+ result->set_long(0);
+ } else
+ result->op_div(value);
+ } else {
+ if (value.is_zero()) {
+ std::cerr << "** WARNING division by zero" << std::endl;
+ result->set_long(0);
+ } else
+ result->op_mod(value);
+ }
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_additive(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_multiplicative(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '+' || token == '-') {
+ Value value;
+ __first = eval_multiplicative(next, __last, &value);
+
+ if (token == '+')
+ result->op_add(value);
+ else
+ result->op_sub(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_shift(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_additive(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_LT_LT || token == TOKEN_GT_GT) {
+ Value value;
+ __first = eval_additive(next, __last, &value);
+
+ if (token == TOKEN_LT_LT)
+ result->op_lhs(value);
+ else
+ result->op_rhs(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_relational(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_shift(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '<'
+ || token == '>'
+ || token == TOKEN_LT_EQ
+ || token == TOKEN_GT_EQ) {
+ Value value;
+ __first = eval_shift(next, __last, &value);
+
+ switch (token) {
+ default:
+ assert(0);
+ break;
+
+ case '<':
+ result->op_lt(value);
+ break;
+
+ case '>':
+ result->op_gt(value);
+ break;
+
+ case TOKEN_LT_EQ:
+ result->op_le(value);
+ break;
+
+ case TOKEN_GT_EQ:
+ result->op_ge(value);
+ break;
+ }
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_equality(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_relational(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_EQ_EQ || token == TOKEN_NOT_EQ) {
+ Value value;
+ __first = eval_relational(next, __last, &value);
+
+ if (token == TOKEN_EQ_EQ)
+ result->op_eq(value);
+ else
+ result->op_ne(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_and(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_equality(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '&') {
+ Value value;
+ __first = eval_equality(next, __last, &value);
+ result->op_bit_and(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_xor(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_and(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '^') {
+ Value value;
+ __first = eval_and(next, __last, &value);
+ result->op_bit_xor(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_or(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_xor(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '|') {
+ Value value;
+ __first = eval_xor(next, __last, &value);
+ result->op_bit_or(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_or(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_AND_AND) {
+ Value value;
+ __first = eval_or(next, __last, &value);
+ result->op_and(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_logical_and(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_OR_OR) {
+ Value value;
+ __first = eval_logical_and(next, __last, &value);
+ result->op_or(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_logical_or(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ if (token == '?') {
+ Value left_value;
+ __first = eval_constant_expression(next, __last, &left_value);
+ __first = skip_blanks(__first, __last);
+
+ __first = next_token(__first, __last, &token);
+ if (token == ':') {
+ Value right_value;
+ __first = eval_constant_expression(__first, __last, &right_value);
+
+ *result = !result->is_zero() ? left_value : right_value;
+ } else {
+ std::cerr << "** WARNING expected ``:'' = " << int (token) << std::endl;
+ *result = left_value;
+ }
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_expression(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ return __first = eval_constant_expression(skip_blanks(__first, __last), __last, result);
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_if(_InputIterator __first, _InputIterator __last)
+{
+ if (test_if_level()) {
+ pp_macro_expander expand_condition(env);
+ std::string condition;
+ condition.reserve(255);
+ expand_condition(skip_blanks(__first, __last), __last, std::back_inserter(condition));
+
+ Value result;
+ result.set_long(0);
+ eval_expression(condition.c_str(), condition.c_str() + condition.size(), &result);
+
+ _M_true_test[iflevel] = !result.is_zero();
+ _M_skipping[iflevel] = result.is_zero();
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_else(_InputIterator __first, _InputIterator /*__last*/)
+{
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #else without #if" << std::endl;
+ } else if (iflevel > 0 && _M_skipping[iflevel - 1]) {
+ _M_skipping[iflevel] = true;
+ } else {
+ _M_skipping[iflevel] = _M_true_test[iflevel];
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_elif(_InputIterator __first, _InputIterator __last)
+{
+ assert(iflevel > 0);
+
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #else without #if" << std::endl;
+ } else if (!_M_true_test[iflevel] && !_M_skipping[iflevel - 1]) {
+ Value result;
+ __first = eval_expression(__first, __last, &result);
+ _M_true_test[iflevel] = !result.is_zero();
+ _M_skipping[iflevel] = result.is_zero();
+ } else {
+ _M_skipping[iflevel] = true;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_endif(_InputIterator __first, _InputIterator /*__last*/)
+{
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #endif without #if" << std::endl;
+ } else {
+ _M_skipping[iflevel] = 0;
+ _M_true_test[iflevel] = 0;
+
+ --iflevel;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last)
+{
+ if (test_if_level()) {
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+
+ std::size_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, end_macro_name, __size);
+#else
+ __size = std::distance(__first, end_macro_name);
+#endif
+ assert(__size < 256);
+
+ char __buffer [256];
+ std::copy(__first, end_macro_name, __buffer);
+
+ bool value = env.resolve(__buffer, __size) != 0;
+
+ __first = end_macro_name;
+
+ if (check_undefined)
+ value = !value;
+
+ _M_true_test[iflevel] = value;
+ _M_skipping[iflevel] = !value;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_undef(_InputIterator __first, _InputIterator __last)
+{
+ __first = skip_blanks(__first, __last);
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+ assert(end_macro_name != __first);
+
+ std::size_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, end_macro_name, __size);
+#else
+ __size = std::distance(__first, end_macro_name);
+#endif
+
+ assert(__size < 256);
+
+ char __buffer [256];
+ std::copy(__first, end_macro_name, __buffer);
+
+ pp_fast_string const __tmp(__buffer, __size);
+ env.unbind(&__tmp);
+
+ __first = end_macro_name;
+
+ return __first;
+}
+
+template <typename _InputIterator>
+char pp::peek_char(_InputIterator __first, _InputIterator __last)
+{
+ if (__first == __last)
+ return 0;
+
+ return *++__first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::next_token(_InputIterator __first, _InputIterator __last, int *kind)
+{
+ __first = skip_blanks(__first, __last);
+
+ if (__first == __last) {
+ *kind = 0;
+ return __first;
+ }
+
+ char ch = *__first;
+ char ch2 = peek_char(__first, __last);
+
+ switch (ch) {
+ case '/':
+ if (ch2 == '/' || ch2 == '*') {
+ __first = skip_comment_or_divop(__first, __last);
+ return next_token(__first, __last, kind);
+ }
+ ++__first;
+ *kind = '/';
+ break;
+
+ case '<':
+ ++__first;
+ if (ch2 == '<') {
+ ++__first;
+ *kind = TOKEN_LT_LT;
+ } else if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_LT_EQ;
+ } else
+ *kind = '<';
+
+ return __first;
+
+ case '>':
+ ++__first;
+ if (ch2 == '>') {
+ ++__first;
+ *kind = TOKEN_GT_GT;
+ } else if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_GT_EQ;
+ } else
+ *kind = '>';
+
+ return __first;
+
+ case '!':
+ ++__first;
+ if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_NOT_EQ;
+ } else
+ *kind = '!';
+
+ return __first;
+
+ case '=':
+ ++__first;
+ if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_EQ_EQ;
+ } else
+ *kind = '=';
+
+ return __first;
+
+ case '|':
+ ++__first;
+ if (ch2 == '|') {
+ ++__first;
+ *kind = TOKEN_OR_OR;
+ } else
+ *kind = '|';
+
+ return __first;
+
+ case '&':
+ ++__first;
+ if (ch2 == '&') {
+ ++__first;
+ *kind = TOKEN_AND_AND;
+ } else
+ *kind = '&';
+
+ return __first;
+
+ default:
+ if (pp_isalpha(ch) || ch == '_') {
+ _InputIterator end = skip_identifier(__first, __last);
+ _M_current_text.assign(__first, end);
+
+ token_text = &_M_current_text;
+ __first = end;
+
+ if (*token_text == "defined")
+ *kind = TOKEN_DEFINED;
+ else
+ *kind = TOKEN_IDENTIFIER;
+ } else if (pp_isdigit(ch)) {
+ _InputIterator end = skip_number(__first, __last);
+ std::string __str(__first, __last);
+ char ch = __str [__str.size() - 1];
+ if (ch == 'u' || ch == 'U') {
+ token_uvalue = strtoul(__str.c_str(), 0, 0);
+ *kind = TOKEN_UNUMBER;
+ } else {
+ token_value = strtol(__str.c_str(), 0, 0);
+ *kind = TOKEN_NUMBER;
+ }
+ __first = end;
+ } else
+ *kind = *__first++;
+ }
+
+ return __first;
+}
+
+} // namespace rpp
+
+#endif // PP_ENGINE_BITS_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-engine.h b/parser/rpp/pp-engine.h
new file mode 100644
index 000000000..79e74c1aa
--- /dev/null
+++ b/parser/rpp/pp-engine.h
@@ -0,0 +1,274 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_ENGINE_H
+#define PP_ENGINE_H
+
+namespace rpp
+{
+
+struct Value {
+ enum Kind {
+ Kind_Long,
+ Kind_ULong,
+ };
+
+ Kind kind;
+
+ union {
+ long l;
+ unsigned long ul;
+ };
+
+ inline bool is_ulong() const {
+ return kind == Kind_ULong;
+ }
+
+ inline void set_ulong(unsigned long v) {
+ ul = v;
+ kind = Kind_ULong;
+ }
+
+ inline void set_long(long v) {
+ l = v;
+ kind = Kind_Long;
+ }
+
+ inline bool is_zero() const {
+ return l == 0;
+ }
+
+#define PP_DEFINE_BIN_OP(name, op) \
+ inline Value &name (const Value &other) \
+ { \
+ if (is_ulong () || other.is_ulong ()) \
+ set_ulong (ul op other.ul); \
+ else \
+ set_long (l op other.l); \
+ return *this; \
+ }
+
+ PP_DEFINE_BIN_OP(op_add, +)
+ PP_DEFINE_BIN_OP(op_sub, -)
+ PP_DEFINE_BIN_OP(op_mult, *)
+ PP_DEFINE_BIN_OP(op_div, /)
+ PP_DEFINE_BIN_OP(op_mod, %)
+ PP_DEFINE_BIN_OP(op_lhs, <<)
+ PP_DEFINE_BIN_OP(op_rhs, >>)
+ PP_DEFINE_BIN_OP(op_lt, <)
+ PP_DEFINE_BIN_OP(op_gt, >)
+ PP_DEFINE_BIN_OP(op_le, <=)
+ PP_DEFINE_BIN_OP(op_ge, >=)
+ PP_DEFINE_BIN_OP(op_eq, ==)
+ PP_DEFINE_BIN_OP(op_ne, !=)
+ PP_DEFINE_BIN_OP(op_bit_and, &)
+ PP_DEFINE_BIN_OP(op_bit_or, |)
+ PP_DEFINE_BIN_OP(op_bit_xor, ^)
+ PP_DEFINE_BIN_OP(op_and, &&)
+ PP_DEFINE_BIN_OP(op_or, ||)
+
+#undef PP_DEFINE_BIN_OP
+};
+
+class pp
+{
+ pp_environment &env;
+ pp_macro_expander expand;
+ pp_skip_identifier skip_identifier;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ pp_skip_blanks skip_blanks;
+ pp_skip_number skip_number;
+ std::vector<std::string> include_paths;
+ std::string _M_current_text;
+
+ enum { MAX_LEVEL = 512 };
+ int _M_skipping[MAX_LEVEL];
+ int _M_true_test[MAX_LEVEL];
+ int iflevel;
+
+ union {
+ long token_value;
+ unsigned long token_uvalue;
+ std::string *token_text;
+ };
+
+ enum INCLUDE_POLICY {
+ INCLUDE_GLOBAL,
+ INCLUDE_LOCAL
+ };
+
+ enum TOKEN_TYPE {
+ TOKEN_NUMBER = 1000,
+ TOKEN_UNUMBER,
+ TOKEN_IDENTIFIER,
+ TOKEN_DEFINED,
+ TOKEN_LT_LT,
+ TOKEN_LT_EQ,
+ TOKEN_GT_GT,
+ TOKEN_GT_EQ,
+ TOKEN_EQ_EQ,
+ TOKEN_NOT_EQ,
+ TOKEN_OR_OR,
+ TOKEN_AND_AND,
+ };
+
+ enum PP_DIRECTIVE_TYPE {
+ PP_UNKNOWN_DIRECTIVE,
+ PP_DEFINE,
+ PP_INCLUDE,
+ PP_INCLUDE_NEXT,
+ PP_ELIF,
+ PP_ELSE,
+ PP_ENDIF,
+ PP_IF,
+ PP_IFDEF,
+ PP_IFNDEF,
+ PP_UNDEF,
+ PP_PRAGMA,
+ PP_ERROR,
+ PP_WARNING
+ };
+
+public:
+ pp(pp_environment &__env);
+
+ inline std::back_insert_iterator<std::vector<std::string> > include_paths_inserter();
+
+ inline void push_include_path(std::string const &__path);
+
+ inline std::vector<std::string>::iterator include_paths_begin();
+ inline std::vector<std::string>::iterator include_paths_end();
+
+ inline std::vector<std::string>::const_iterator include_paths_begin() const;
+ inline std::vector<std::string>::const_iterator include_paths_end() const;
+
+ template <typename _InputIterator>
+ inline _InputIterator eval_expression(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _OutputIterator>
+ void file(std::string const &filename, _OutputIterator __result);
+
+ template <typename _OutputIterator>
+ void file(FILE *fp, _OutputIterator __result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ void operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result);
+
+private:
+ inline bool file_isdir(std::string const &__filename) const;
+ inline bool file_exists(std::string const &__filename) const;
+ FILE *find_include_file(std::string const &__filename, std::string *__filepath,
+ INCLUDE_POLICY __include_policy, bool __skip_current_path = false) const;
+
+ inline int skipping() const;
+ bool test_if_level();
+
+ inline std::string fix_file_path(std::string const &filename) const;
+ inline bool is_absolute(std::string const &filename) const;
+
+ PP_DIRECTIVE_TYPE find_directive(char const *__directive, std::size_t __size) const;
+
+ template <typename _InputIterator>
+ bool find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot);
+
+ template <typename _InputIterator>
+ _InputIterator skip(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator eval_primary(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_additive(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_shift(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_relational(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_equality(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_and(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_xor(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_or(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator handle_directive(char const *__directive, std::size_t __size,
+ _InputIterator __first, _InputIterator __last, _OutputIterator __result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator handle_include(bool skip_current_path, _InputIterator __first, _InputIterator __last,
+ _OutputIterator __result);
+
+ template <typename _InputIterator>
+ _InputIterator handle_define(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_if(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_else(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_elif(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_endif(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_undef(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ inline char peek_char(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator next_token(_InputIterator __first, _InputIterator __last, int *kind);
+};
+
+} // namespace rpp
+
+#endif // PP_ENGINE_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-environment.h b/parser/rpp/pp-environment.h
new file mode 100644
index 000000000..6003c0820
--- /dev/null
+++ b/parser/rpp/pp-environment.h
@@ -0,0 +1,137 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_ENVIRONMENT_H
+#define PP_ENVIRONMENT_H
+
+#include <vector>
+#include <cstring>
+
+namespace rpp
+{
+
+class pp_environment
+{
+public:
+ typedef std::vector<pp_macro*>::const_iterator const_iterator;
+
+public:
+ pp_environment():
+ current_line(0),
+ _M_hash_size(4093) {
+ _M_base = (pp_macro **) memset(new pp_macro* [_M_hash_size], 0, _M_hash_size * sizeof(pp_macro*));
+ }
+
+ ~pp_environment() {
+ for (std::size_t i = 0; i < _M_macros.size(); ++i)
+ delete _M_macros [i];
+
+ delete [] _M_base;
+ }
+
+ const_iterator first_macro() const {
+ return _M_macros.begin();
+ }
+ const_iterator last_macro() const {
+ return _M_macros.end();
+ }
+
+ inline void bind(pp_fast_string const *__name, pp_macro const &__macro) {
+ std::size_t h = hash_code(*__name) % _M_hash_size;
+ pp_macro *m = new pp_macro(__macro);
+ m->name = __name;
+ m->next = _M_base [h];
+ m->hash_code = h;
+ _M_base [h] = m;
+
+ _M_macros.push_back(m);
+
+ if (_M_macros.size() == _M_hash_size)
+ rehash();
+ }
+
+ inline void unbind(pp_fast_string const *__name) {
+ if (pp_macro *m = resolve(__name))
+ m->hidden = true;
+ }
+
+ inline void unbind(char const *__s, std::size_t __size) {
+ pp_fast_string __tmp(__s, __size);
+ unbind(&__tmp);
+ }
+
+ inline pp_macro *resolve(pp_fast_string const *__name) const {
+ std::size_t h = hash_code(*__name) % _M_hash_size;
+ pp_macro *it = _M_base [h];
+
+ while (it && it->name && it->hash_code == h && (*it->name != *__name || it->hidden))
+ it = it->next;
+
+ return it;
+ }
+
+ inline pp_macro *resolve(char const *__data, std::size_t __size) const {
+ pp_fast_string const __tmp(__data, __size);
+ return resolve(&__tmp);
+ }
+
+ std::string current_file;
+ int current_line;
+
+private:
+ inline std::size_t hash_code(pp_fast_string const &s) const {
+ std::size_t hash_value = 0;
+
+ for (std::size_t i = 0; i < s.size(); ++i)
+ hash_value = (hash_value << 5) - hash_value + s.at(i);
+
+ return hash_value;
+ }
+
+ void rehash() {
+ delete[] _M_base;
+
+ _M_hash_size <<= 1;
+
+ _M_base = (pp_macro **) memset(new pp_macro* [_M_hash_size], 0, _M_hash_size * sizeof(pp_macro*));
+ for (std::size_t index = 0; index < _M_macros.size(); ++index) {
+ pp_macro *elt = _M_macros [index];
+ std::size_t h = hash_code(*elt->name) % _M_hash_size;
+ elt->next = _M_base [h];
+ elt->hash_code = h;
+ _M_base [h] = elt;
+ }
+ }
+
+private:
+ std::vector<pp_macro*> _M_macros;
+ pp_macro **_M_base;
+ std::size_t _M_hash_size;
+};
+
+} // namespace rpp
+
+#endif // PP_ENVIRONMENT_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-fwd.h b/parser/rpp/pp-fwd.h
new file mode 100644
index 000000000..5b1c792f8
--- /dev/null
+++ b/parser/rpp/pp-fwd.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_FWD_H
+#define PP_FWD_H
+
+namespace rpp
+{
+
+template <typename _CharT> class pp_string;
+
+typedef pp_string<char> pp_fast_string;
+
+} // namespace rpp
+
+#endif // PP_FWD_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-internal.h b/parser/rpp/pp-internal.h
new file mode 100644
index 000000000..7e708101d
--- /dev/null
+++ b/parser/rpp/pp-internal.h
@@ -0,0 +1,117 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_INTERNAL_H
+#define PP_INTERNAL_H
+
+#include <algorithm>
+#include <string>
+#include "pp.h"
+
+namespace rpp
+{
+
+namespace _PP_internal
+{
+
+inline void extract_file_path(const std::string &__filename, std::string *__filepath)
+{
+ std::size_t __index = __filename.rfind(PATH_SEPARATOR);
+
+ if (__index == std::string::npos)
+ *__filepath = "/";
+
+ else
+ __filepath->assign(__filename, 0, __index + 1);
+}
+
+template <typename _OutputIterator>
+void output_line(const std::string &__filename, int __line, _OutputIterator __result)
+{
+ std::string __msg;
+
+ __msg += "# ";
+
+ char __line_descr[16];
+ pp_snprintf(__line_descr, 16, "%d", __line);
+ __msg += __line_descr;
+
+ __msg += " \"";
+
+ if (__filename.empty())
+ __msg += "<internal>";
+ else
+ __msg += __filename;
+
+ __msg += "\"\n";
+ std::copy(__msg.begin(), __msg.end(), __result);
+}
+
+template <typename _InputIterator>
+inline bool comment_p(_InputIterator __first, _InputIterator __last) /*const*/
+{
+ if (__first == __last)
+ return false;
+
+ if (*__first != '/')
+ return false;
+
+ if (++__first == __last)
+ return false;
+
+ return (*__first == '/' || *__first == '*');
+}
+
+struct _Compare_string: public std::binary_function<bool, pp_fast_string const *, pp_fast_string const *> {
+ inline bool operator()(pp_fast_string const *__lhs, pp_fast_string const *__rhs) const {
+ return *__lhs < *__rhs;
+ }
+};
+
+struct _Equal_to_string: public std::binary_function<bool, pp_fast_string const *, pp_fast_string const *> {
+ inline bool operator()(pp_fast_string const *__lhs, pp_fast_string const *__rhs) const {
+ return *__lhs == *__rhs;
+ }
+};
+
+struct _Hash_string: public std::unary_function<std::size_t, pp_fast_string const *> {
+ inline std::size_t operator()(pp_fast_string const *__s) const {
+ char const *__ptr = __s->begin();
+ std::size_t __size = __s->size();
+ std::size_t __h = 0;
+
+ for (std::size_t i = 0; i < __size; ++i)
+ __h = (__h << 5) - __h + __ptr [i];
+
+ return __h;
+ }
+};
+
+} // _PP_internal
+
+} // namespace rpp
+
+#endif // PP_INTERNAL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-iterator.h b/parser/rpp/pp-iterator.h
new file mode 100644
index 000000000..fe846bd26
--- /dev/null
+++ b/parser/rpp/pp-iterator.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_ITERATOR_H
+#define PP_ITERATOR_H
+
+#include <iterator>
+
+namespace rpp
+{
+
+class pp_null_output_iterator
+ : public std::iterator<std::output_iterator_tag, void, void, void, void>
+{
+public:
+ pp_null_output_iterator() {}
+
+ template <typename _Tp>
+ pp_null_output_iterator &operator=(_Tp const &) {
+ return *this;
+ }
+
+ inline pp_null_output_iterator &operator *() {
+ return *this;
+ }
+ inline pp_null_output_iterator &operator ++ () {
+ return *this;
+ }
+ inline pp_null_output_iterator operator ++ (int) {
+ return *this;
+ }
+};
+
+template <typename _Container>
+class pp_output_iterator
+ : public std::iterator<std::output_iterator_tag, void, void, void, void>
+{
+ std::string &_M_result;
+
+public:
+ explicit pp_output_iterator(std::string &__result):
+ _M_result(__result) {}
+
+ inline pp_output_iterator &operator=(typename _Container::const_reference __v) {
+ if (_M_result.capacity() == _M_result.size())
+ _M_result.reserve(_M_result.capacity() << 2);
+
+ _M_result.push_back(__v);
+ return *this;
+ }
+
+ inline pp_output_iterator &operator *() {
+ return *this;
+ }
+ inline pp_output_iterator &operator ++ () {
+ return *this;
+ }
+ inline pp_output_iterator operator ++ (int) {
+ return *this;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_ITERATOR_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-macro-expander.h b/parser/rpp/pp-macro-expander.h
new file mode 100644
index 000000000..fd875d980
--- /dev/null
+++ b/parser/rpp/pp-macro-expander.h
@@ -0,0 +1,351 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_MACRO_EXPANDER_H
+#define PP_MACRO_EXPANDER_H
+
+namespace rpp
+{
+
+struct pp_frame {
+ pp_macro *expanding_macro;
+ std::vector<std::string> *actuals;
+
+ pp_frame(pp_macro *__expanding_macro, std::vector<std::string> *__actuals):
+ expanding_macro(__expanding_macro), actuals(__actuals) {}
+};
+
+class pp_macro_expander
+{
+ pp_environment &env;
+ pp_frame *frame;
+
+ pp_skip_number skip_number;
+ pp_skip_identifier skip_identifier;
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+ pp_skip_argument skip_argument;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ pp_skip_blanks skip_blanks;
+ pp_skip_whitespaces skip_whitespaces;
+
+ std::string const *resolve_formal(pp_fast_string const *__name) {
+ assert(__name != 0);
+
+ if (! frame)
+ return 0;
+
+ assert(frame->expanding_macro != 0);
+
+ std::vector<pp_fast_string const *> const formals = frame->expanding_macro->formals;
+ for (std::size_t index = 0; index < formals.size(); ++index) {
+ pp_fast_string const *formal = formals[index];
+
+ if (*formal != *__name)
+ continue;
+
+ else if (frame->actuals && index < frame->actuals->size())
+ return &(*frame->actuals)[index];
+
+ else
+ assert(0); // internal error?
+ }
+
+ return 0;
+ }
+
+public: // attributes
+ int lines;
+ int generated_lines;
+
+public:
+ pp_macro_expander(pp_environment &__env, pp_frame *__frame = 0):
+ env(__env), frame(__frame), lines(0), generated_lines(0) {}
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
+ generated_lines = 0;
+ __first = skip_blanks(__first, __last);
+ lines = skip_blanks.lines;
+
+ while (__first != __last) {
+ if (*__first == '\n') {
+ *__result++ = *__first;
+ ++lines;
+
+ __first = skip_blanks(++__first, __last);
+ lines += skip_blanks.lines;
+
+ if (__first != __last && *__first == '#')
+ break;
+ } else if (*__first == '#') {
+ __first = skip_blanks(++__first, __last);
+ lines += skip_blanks.lines;
+
+ _InputIterator end_id = skip_identifier(__first, __last);
+
+ // ### rewrite: not safe
+ char name_buffer[512], *cp = name_buffer;
+ std::copy(__first, end_id, cp);
+ std::size_t name_size = end_id - __first;
+ name_buffer[name_size] = '\0';
+
+ pp_fast_string fast_name(name_buffer, name_size);
+
+ if (std::string const *actual = resolve_formal(&fast_name)) {
+ *__result++ = '\"';
+
+ for (std::string::const_iterator it = skip_whitespaces(actual->begin(), actual->end());
+ it != actual->end(); ++it) {
+ if (*it == '"') {
+ *__result++ = '\\';
+ *__result++ = *it;
+ }
+
+ else if (*it == '\n') {
+ *__result++ = '"';
+ *__result++ = '\n';
+ *__result++ = '"';
+ }
+
+ else
+ *__result++ = *it;
+ }
+
+ *__result++ = '\"';
+ __first = end_id;
+ } else
+ *__result++ = '#'; // ### warning message?
+ } else if (*__first == '\"') {
+ _InputIterator next_pos = skip_string_literal(__first, __last);
+ lines += skip_string_literal.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (*__first == '\'') {
+ _InputIterator next_pos = skip_char_literal(__first, __last);
+ lines += skip_char_literal.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (_PP_internal::comment_p(__first, __last)) {
+ __first = skip_comment_or_divop(__first, __last);
+ int n = skip_comment_or_divop.lines;
+ lines += n;
+
+ while (n-- > 0)
+ *__result++ = '\n';
+ } else if (pp_isspace(*__first)) {
+ for (; __first != __last; ++__first) {
+ if (*__first == '\n' || !pp_isspace(*__first))
+ break;
+ }
+
+ *__result = ' ';
+ } else if (pp_isdigit(*__first)) {
+ _InputIterator next_pos = skip_number(__first, __last);
+ lines += skip_number.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (pp_isalpha(*__first) || *__first == '_') {
+ _InputIterator name_begin = __first;
+ _InputIterator name_end = skip_identifier(__first, __last);
+ __first = name_end; // advance
+
+ // search for the paste token
+ _InputIterator next = skip_blanks(__first, __last);
+ if (next != __last && *next == '#') {
+ ++next;
+ if (next != __last && *next == '#')
+ __first = skip_blanks(++next, __last);
+ }
+
+ // ### rewrite: not safe
+
+ std::ptrdiff_t name_size;
+#if defined(__SUNPRO_CC)
+ std::distance(name_begin, name_end, name_size);
+#else
+ name_size = std::distance(name_begin, name_end);
+#endif
+ assert(name_size >= 0 && name_size < 512);
+
+ char name_buffer[512], *cp = name_buffer;
+ std::size_t __size = name_end - name_begin;
+ std::copy(name_begin, name_end, cp);
+ name_buffer[__size] = '\0';
+
+ pp_fast_string fast_name(name_buffer, name_size);
+
+ if (std::string const *actual = resolve_formal(&fast_name)) {
+ std::copy(actual->begin(), actual->end(), __result);
+ continue;
+ }
+
+ static bool hide_next = false; // ### remove me
+
+ pp_macro *macro = env.resolve(name_buffer, name_size);
+ if (! macro || macro->hidden || hide_next) {
+ hide_next = ! strcmp(name_buffer, "defined");
+
+ if (__size == 8 && name_buffer [0] == '_' && name_buffer [1] == '_') {
+ if (! strcmp(name_buffer, "__LINE__")) {
+ char buf [16];
+ char *end = buf + pp_snprintf(buf, 16, "%d", env.current_line + lines);
+
+ std::copy(&buf [0], end, __result);
+ continue;
+ }
+
+ else if (! strcmp(name_buffer, "__FILE__")) {
+ __result++ = '"';
+ std::copy(env.current_file.begin(), env.current_file.end(), __result); // ### quote
+ __result++ = '"';
+ continue;
+ }
+ }
+
+ std::copy(name_begin, name_end, __result);
+ continue;
+ }
+
+ if (! macro->function_like) {
+ pp_macro *m = 0;
+
+ if (macro->definition) {
+ macro->hidden = true;
+
+ std::string __tmp;
+ __tmp.reserve(256);
+
+ pp_macro_expander expand_macro(env);
+ expand_macro(macro->definition->begin(), macro->definition->end(), std::back_inserter(__tmp));
+ generated_lines += expand_macro.lines;
+
+ if (! __tmp.empty()) {
+ std::string::iterator __begin_id = skip_whitespaces(__tmp.begin(), __tmp.end());
+ std::string::iterator __end_id = skip_identifier(__begin_id, __tmp.end());
+
+ if (__end_id == __tmp.end()) {
+ std::string __id;
+ __id.assign(__begin_id, __end_id);
+
+ std::size_t x;
+#if defined(__SUNPRO_CC)
+ std::distance(__begin_id, __end_id, x);
+#else
+ x = std::distance(__begin_id, __end_id);
+#endif
+ m = env.resolve(__id.c_str(), x);
+ }
+
+ if (! m)
+ std::copy(__tmp.begin(), __tmp.end(), __result);
+ }
+
+ macro->hidden = false;
+ }
+
+ if (! m)
+ continue;
+
+ macro = m;
+ }
+
+ // function like macro
+ _InputIterator arg_it = skip_whitespaces(__first, __last);
+
+ if (arg_it == __last || *arg_it != '(') {
+ std::copy(name_begin, name_end, __result);
+ lines += skip_whitespaces.lines;
+ __first = arg_it;
+ continue;
+ }
+
+ std::vector<std::string> actuals;
+ actuals.reserve(5);
+ ++arg_it; // skip '('
+
+ pp_macro_expander expand_actual(env, frame);
+
+ _InputIterator arg_end = skip_argument_variadics(actuals, macro, arg_it, __last);
+ if (arg_it != arg_end) {
+ std::string actual(arg_it, arg_end);
+ actuals.resize(actuals.size() + 1);
+ actuals.back().reserve(255);
+ expand_actual(actual.begin(), actual.end(), std::back_inserter(actuals.back()));
+ arg_it = arg_end;
+ }
+
+ while (arg_it != __last && *arg_end == ',') {
+ ++arg_it; // skip ','
+
+ arg_end = skip_argument_variadics(actuals, macro, arg_it, __last);
+ std::string actual(arg_it, arg_end);
+ actuals.resize(actuals.size() + 1);
+ actuals.back().reserve(255);
+ expand_actual(actual.begin(), actual.end(), std::back_inserter(actuals.back()));
+ arg_it = arg_end;
+ }
+
+ assert(arg_it != __last && *arg_it == ')');
+
+ ++arg_it; // skip ')'
+ __first = arg_it;
+
+#if 0 // ### enable me
+ assert((macro->variadics && macro->formals.size() >= actuals.size())
+ || macro->formals.size() == actuals.size());
+#endif
+
+ pp_frame frame(macro, &actuals);
+ pp_macro_expander expand_macro(env, &frame);
+ macro->hidden = true;
+ expand_macro(macro->definition->begin(), macro->definition->end(), __result);
+ macro->hidden = false;
+ generated_lines += expand_macro.lines;
+ } else
+ *__result++ = *__first++;
+ }
+
+ return __first;
+ }
+
+ template <typename _InputIterator>
+ _InputIterator skip_argument_variadics(std::vector<std::string> const &__actuals, pp_macro *__macro,
+ _InputIterator __first, _InputIterator __last) {
+ _InputIterator arg_end = skip_argument(__first, __last);
+
+ while (__macro->variadics && __first != arg_end && arg_end != __last && *arg_end == ','
+ && (__actuals.size() + 1) == __macro->formals.size()) {
+ arg_end = skip_argument(++arg_end, __last);
+ }
+
+ return arg_end;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_MACRO_EXPANDER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-macro.h b/parser/rpp/pp-macro.h
new file mode 100644
index 000000000..e633834b1
--- /dev/null
+++ b/parser/rpp/pp-macro.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_MACRO_H
+#define PP_MACRO_H
+
+#include <vector>
+#include "pp-fwd.h"
+
+namespace rpp
+{
+
+struct pp_macro {
+#if defined (PP_WITH_MACRO_POSITION)
+ pp_fast_string const *file;
+#endif
+ pp_fast_string const *name;
+ pp_fast_string const *definition;
+ std::vector<pp_fast_string const *> formals;
+
+ union {
+ int unsigned state;
+
+ struct {
+ int unsigned hidden: 1;
+ int unsigned function_like: 1;
+ int unsigned variadics: 1;
+ };
+ };
+
+ int lines;
+ pp_macro *next;
+ std::size_t hash_code;
+
+ inline pp_macro():
+#if defined (PP_WITH_MACRO_POSITION)
+ file(0),
+#endif
+ name(0),
+ definition(0),
+ state(0),
+ lines(0),
+ next(0),
+ hash_code(0) {}
+};
+
+} // namespace rpp
+
+#endif // PP_MACRO_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-main.cpp b/parser/rpp/pp-main.cpp
new file mode 100644
index 000000000..4c37e754f
--- /dev/null
+++ b/parser/rpp/pp-main.cpp
@@ -0,0 +1,295 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <fstream>
+#include "pp.h"
+
+using namespace rpp;
+
+#ifndef GCC_MACHINE
+# define GCC_MACHINE "i386-redhat-linux"
+#endif
+
+#ifndef GCC_VERSION
+# define GCC_VERSION "4.1.1"
+#endif
+
+void usage()
+{
+ std::cerr << "usage: rpp file.cpp" << std::endl;
+ ::exit(EXIT_FAILURE);
+}
+
+void dump_macros(pp_environment &env, pp &, std::ostream &__out)
+{
+ for (pp_environment::const_iterator it = env.first_macro(); it != env.last_macro(); ++it) {
+ pp_macro const *m = *it;
+
+ if (m->hidden)
+ continue;
+
+ std::string id(m->name->begin(), m->name->end());
+ __out << "#define " << id;
+
+ if (m->function_like) {
+ __out << "(";
+
+ for (std::size_t i = 0; i < m->formals.size(); ++i) {
+ if (i != 0)
+ __out << ", ";
+
+ pp_fast_string const *f = m->formals [i];
+ std::string name(f->begin(), f->end());
+ __out << name;
+ }
+
+ if (m->variadics)
+ __out << "...";
+
+ __out << ")";
+ }
+
+ __out << "\t";
+ if (m->definition) {
+ std::string def(m->definition->begin(), m->definition->end());
+ __out << def;
+ }
+
+ __out << std::endl;
+ }
+}
+#if 0
+int main(int, char *argv [])
+{
+ char const *input_file = 0;
+ char const *output_file = 0;
+ char const *include_pch_file = 0;
+ bool opt_help = false;
+ bool opt_dump_macros = false;
+ bool opt_pch = false;
+
+ pp_environment env;
+ pp preprocess(env);
+
+ std::string result;
+ result.reserve(20 * 1024); // 20K
+
+ pp_output_iterator<std::string> out(result);
+ pp_null_output_iterator null_out;
+
+ preprocess.push_include_path("/usr/include");
+ preprocess.push_include_path("/usr/lib/gcc/" GCC_MACHINE "/" GCC_VERSION "/include");
+
+ preprocess.push_include_path("/usr/include/c++/" GCC_VERSION);
+ preprocess.push_include_path("/usr/include/c++/" GCC_VERSION "/" GCC_MACHINE);
+
+ std::string extra_args;
+
+ while (const char *arg = *++argv) {
+ if (arg [0] != '-')
+ input_file = arg;
+
+ else if (! strcmp(arg, "-help"))
+ opt_help = true;
+
+ else if (! strcmp(arg, "-dM"))
+ opt_dump_macros = true;
+
+ else if (! strcmp(arg, "-pch"))
+ opt_pch = true;
+
+ else if (! strcmp(arg, "-msse")) {
+ pp_macro __macro;
+ __macro.name = pp_symbol::get("__SSE__", 7);
+ env.bind(__macro.name, __macro);
+
+ __macro.name = pp_symbol::get("__MMX__", 7);
+ env.bind(__macro.name, __macro);
+ }
+
+ else if (! strcmp(arg, "-include")) {
+ if (argv [1])
+ include_pch_file = *++argv;
+ }
+
+ else if (! strncmp(arg, "-o", 2)) {
+ arg += 2;
+
+ if (! arg [0] && argv [1])
+ arg = *++argv;
+
+ if (arg)
+ output_file = arg;
+ }
+
+ else if (! strncmp(arg, "-conf", 8)) {
+ if (argv [1])
+ preprocess.file(*++argv, null_out);
+ }
+
+ else if (! strncmp(arg, "-I", 2)) {
+ arg += 2;
+
+ if (! arg [0] && argv [1])
+ arg = *++argv;
+
+ if (arg)
+ preprocess.push_include_path(arg);
+ }
+
+ else if (! strncmp(arg, "-U", 2)) {
+ arg += 2;
+
+ if (! arg [0] && argv [1])
+ arg = *++argv;
+
+ if (arg) {
+ env.unbind(arg, strlen(arg));
+ }
+ }
+
+ else if (! strncmp(arg, "-D", 2)) {
+ arg += 2;
+
+ if (! arg [0] && argv [1])
+ arg = *++argv;
+
+ if (arg) {
+ pp_macro __macro;
+
+ char const *end = arg;
+ char const *eq = 0;
+
+ for (; *end; ++end) {
+ if (*end == '=')
+ eq = end;
+ }
+
+ if (eq != 0) {
+ __macro.name = pp_symbol::get(arg, eq - arg);
+ __macro.definition = pp_symbol::get(eq + 1, end - (eq + 1));
+ }
+
+ else {
+ __macro.name = pp_symbol::get(arg, end - arg);
+ __macro.definition = 0;
+ }
+
+ env.bind(__macro.name, __macro);
+ }
+ } else {
+ extra_args += " ";
+ extra_args += arg;
+ }
+ }
+
+ if (! input_file || opt_help) {
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ std::string __ifile(input_file);
+ bool is_c_file = false;
+ if (__ifile.size() > 2 && __ifile [__ifile.size() - 1] == 'c' && __ifile [__ifile.size() - 2] == '.') {
+ is_c_file = true;
+ env.unbind("__cplusplus", 11);
+
+ pp_macro __macro;
+ __macro.name = pp_symbol::get("__null");
+ __macro.definition = pp_symbol::get("((void*) 0)");
+ env.bind(__macro.name, __macro);
+
+ // turn off the pch
+ include_pch_file = 0;
+ } else if (include_pch_file) {
+ std::string __pch(include_pch_file);
+ __pch += ".gch/c++.conf";
+
+ //std::cerr << "*** pch file " << __pch << std::endl;
+ preprocess.file(__pch, null_out);
+ }
+
+ if (opt_dump_macros) {
+ preprocess.file(input_file, null_out);
+ dump_macros(env, preprocess, std::cout);
+ return EXIT_SUCCESS;
+ }
+
+ preprocess.file(input_file, out);
+
+ if (opt_pch) {
+ if (! output_file) {
+ std::cerr << "*** WARNING expected a file name" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::string __conf_file(output_file);
+ __conf_file += ".conf";
+
+ std::ofstream __out;
+ __out.open(__conf_file.c_str());
+ dump_macros(env, preprocess, __out);
+ __out.close();
+
+ std::string __pp_file(output_file);
+ __pp_file += ".i";
+
+ __out.open(__pp_file.c_str());
+ __out.write(result.c_str(), result.size());
+ __out.close();
+ return EXIT_SUCCESS;
+ }
+
+ std::ostream *__out = &std::cout;
+ std::ofstream __ofile;
+
+ if (output_file) {
+ std::string __output_file_name(output_file);
+ __ofile.open(output_file);
+ __out = &__ofile;
+ }
+
+ if (include_pch_file) {
+ std::string __pch(include_pch_file);
+ __pch += ".gch/c++.i";
+
+ std::ifstream __in(__pch.c_str());
+
+ char buffer [1024];
+ while (__in.read(buffer, 1024))
+ __out->write(buffer, 1024);
+
+ __in.close();
+ }
+
+ __out->write(result.c_str(), result.size());
+
+ if (output_file)
+ __ofile.close();
+
+ return EXIT_SUCCESS;
+}
+#endif
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/parser/rpp/pp-qt-configuration b/parser/rpp/pp-qt-configuration
new file mode 100644
index 000000000..206c3d643
--- /dev/null
+++ b/parser/rpp/pp-qt-configuration
@@ -0,0 +1,24 @@
+#define __cplusplus 1
+
+#define __STDC__
+
+// Qt
+#define QOBJECTDEFS_H
+
+// not yet supported
+#define Q_SLOTS slots
+#define Q_SIGNALS signals
+#define Q_FLAGS(a)
+#define Q_PRIVATE_SLOT(a, b)
+#define Q_DECLARE_INTERFACE(a,b)
+#define Q_INTERFACES(a)
+#define Q_GADGET
+#define Q_OVERRIDE(a)
+#define Q_OS_OS2
+#define Q_NO_USING_KEYWORD
+#define QT_NO_QOBJECT_CHECK
+#define QT_NO_MEMBER_TEMPLATES
+// There are symbols in Qt that exist in Debug but
+// not in release
+#define QT_NO_DEBUG
+
diff --git a/parser/rpp/pp-scanner.h b/parser/rpp/pp-scanner.h
new file mode 100644
index 000000000..e97b15843
--- /dev/null
+++ b/parser/rpp/pp-scanner.h
@@ -0,0 +1,313 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_SCANNER_H
+#define PP_SCANNER_H
+
+#include "pp-cctype.h"
+#include <cassert>
+
+namespace rpp
+{
+
+struct pp_skip_blanks {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (*__first == '\\') {
+ _InputIterator __begin = __first;
+ ++__begin;
+
+ if (__begin != __last && *__begin == '\n')
+ ++__first;
+ else
+ break;
+ } else if (*__first == '\n' || !pp_isspace(*__first))
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_whitespaces {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isspace(*__first))
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_comment_or_divop {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ MAYBE_BEGIN,
+ BEGIN,
+ MAYBE_END,
+ END,
+ IN_COMMENT,
+ IN_CXX_COMMENT
+ } state(MAYBE_BEGIN);
+
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case MAYBE_BEGIN:
+ if (*__first != '/')
+ return __first;
+
+ state = BEGIN;
+ break;
+
+ case BEGIN:
+ if (*__first == '*')
+ state = IN_COMMENT;
+ else if (*__first == '/')
+ state = IN_CXX_COMMENT;
+ else
+ return __first;
+ break;
+
+ case IN_COMMENT:
+ if (*__first == '*')
+ state = MAYBE_END;
+ break;
+
+ case IN_CXX_COMMENT:
+ if (*__first == '\n')
+ return __first;
+ break;
+
+ case MAYBE_END:
+ if (*__first == '/')
+ state = END;
+ else if (*__first != '*')
+ state = IN_COMMENT;
+ break;
+
+ case END:
+ return __first;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_identifier {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isalnum(*__first) && *__first != '_')
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_number {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isalnum(*__first) && *__first != '.')
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_string_literal {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ BEGIN,
+ IN_STRING,
+ QUOTE,
+ END
+ } state(BEGIN);
+
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case BEGIN:
+ if (*__first != '\"')
+ return __first;
+ state = IN_STRING;
+ break;
+
+ case IN_STRING:
+ assert(*__first != '\n');
+
+ if (*__first == '\"')
+ state = END;
+ else if (*__first == '\\')
+ state = QUOTE;
+ break;
+
+ case QUOTE:
+ state = IN_STRING;
+ break;
+
+ case END:
+ return __first;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_char_literal {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ BEGIN,
+ IN_STRING,
+ QUOTE,
+ END
+ } state(BEGIN);
+
+ lines = 0;
+
+ for (; state != END && __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case BEGIN:
+ if (*__first != '\'')
+ return __first;
+ state = IN_STRING;
+ break;
+
+ case IN_STRING:
+ assert(*__first != '\n');
+
+ if (*__first == '\'')
+ state = END;
+ else if (*__first == '\\')
+ state = QUOTE;
+ break;
+
+ case QUOTE:
+ state = IN_STRING;
+ break;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_argument {
+ pp_skip_identifier skip_number;
+ pp_skip_identifier skip_identifier;
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ int depth = 0;
+ lines = 0;
+
+ while (__first != __last) {
+ if (!depth && (*__first == ')' || *__first == ','))
+ break;
+ else if (*__first == '(')
+ ++depth, ++__first;
+ else if (*__first == ')')
+ --depth, ++__first;
+ else if (*__first == '\"') {
+ __first = skip_string_literal(__first, __last);
+ lines += skip_string_literal.lines;
+ } else if (*__first == '\'') {
+ __first = skip_char_literal(__first, __last);
+ lines += skip_char_literal.lines;
+ } else if (*__first == '/') {
+ __first = skip_comment_or_divop(__first, __last);
+ lines += skip_comment_or_divop.lines;
+ } else if (pp_isalpha(*__first) || *__first == '_') {
+ __first = skip_identifier(__first, __last);
+ lines += skip_identifier.lines;
+ } else if (pp_isdigit(*__first)) {
+ __first = skip_number(__first, __last);
+ lines += skip_number.lines;
+ } else if (*__first == '\n') {
+ ++__first;
+ ++lines;
+ } else
+ ++__first;
+ }
+
+ return __first;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_SCANNER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-string.h b/parser/rpp/pp-string.h
new file mode 100644
index 000000000..31bca4f7b
--- /dev/null
+++ b/parser/rpp/pp-string.h
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_STRING_H
+#define PP_STRING_H
+
+namespace rpp
+{
+
+template <typename _CharT>
+class pp_string
+{
+ typedef std::char_traits<_CharT> traits_type;
+ typedef std::size_t size_type;
+
+ _CharT const *_M_begin;
+ std::size_t _M_size;
+
+public:
+ inline pp_string():
+ _M_begin(0), _M_size(0) {}
+
+ explicit pp_string(std::string const &__s):
+ _M_begin(__s.c_str()), _M_size(__s.size()) {}
+
+ inline pp_string(_CharT const *__begin, std::size_t __size):
+ _M_begin(__begin), _M_size(__size) {}
+
+ inline _CharT const *begin() const {
+ return _M_begin;
+ }
+ inline _CharT const *end() const {
+ return _M_begin + _M_size;
+ }
+
+ inline _CharT at(std::size_t index) const {
+ return _M_begin [index];
+ }
+
+ inline std::size_t size() const {
+ return _M_size;
+ }
+
+ inline int compare(pp_string const &__other) const {
+ size_type const __size = this->size();
+ size_type const __osize = __other.size();
+ size_type const __len = std::min(__size, __osize);
+
+ int __r = traits_type::compare(_M_begin, __other._M_begin, __len);
+ if (!__r)
+ __r = (int)(__size - __osize);
+
+ return __r;
+ }
+
+ inline bool operator == (pp_string const &__other) const {
+ return compare(__other) == 0;
+ }
+
+ inline bool operator != (pp_string const &__other) const {
+ return compare(__other) != 0;
+ }
+
+ inline bool operator < (pp_string const &__other) const {
+ return compare(__other) < 0;
+ }
+
+ inline bool operator == (char const *s) const {
+ std::size_t n = strlen(s);
+
+ if (n != _M_size)
+ return false;
+
+ return ! strncmp(_M_begin, s, n);
+ }
+
+ inline bool operator != (char const *s) const {
+ return ! operator == (s);
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_STRING_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp-symbol.h b/parser/rpp/pp-symbol.h
new file mode 100644
index 000000000..eef668379
--- /dev/null
+++ b/parser/rpp/pp-symbol.h
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_SYMBOL_H
+#define PP_SYMBOL_H
+
+#include <cassert>
+#include <iterator>
+#include "pp-fwd.h"
+#include "parser/rxx_allocator.h"
+
+namespace rpp
+{
+
+class pp_symbol
+{
+ static rxx_allocator<char> &allocator_instance() {
+ static rxx_allocator<char>__allocator;
+ return __allocator;
+ }
+
+public:
+ static int &N() {
+ static int __N;
+ return __N;
+ }
+
+ static pp_fast_string const *get(char const *__data, std::size_t __size) {
+ ++N();
+ char *data = allocator_instance().allocate(__size + 1);
+ memcpy(data, __data, __size);
+ data[__size] = '\0';
+
+ char *where = allocator_instance().allocate(sizeof(pp_fast_string));
+ return new(where) pp_fast_string(data, __size);
+ }
+
+ template <typename _InputIterator>
+ static pp_fast_string const *get(_InputIterator __first, _InputIterator __last) {
+ ++N();
+ std::ptrdiff_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, __last, __size);
+#else
+ __size = std::distance(__first, __last);
+#endif
+ assert(__size >= 0 && __size < 512);
+
+ char *data = allocator_instance().allocate(__size + 1);
+ std::copy(__first, __last, data);
+ data[__size] = '\0';
+
+ char *where = allocator_instance().allocate(sizeof(pp_fast_string));
+ return new(where) pp_fast_string(data, __size);
+ }
+
+ static pp_fast_string const *get(std::string const &__s) {
+ return get(__s.c_str(), __s.size());
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_SYMBOL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/pp.h b/parser/rpp/pp.h
new file mode 100644
index 000000000..3ff38c0d1
--- /dev/null
+++ b/parser/rpp/pp.h
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PP_H
+#define PP_H
+
+#if defined(_WIN64) || defined(WIN64) || defined(__WIN64__) \
+ || defined(_WIN32) || defined(WIN32) || defined(__WIN32__)
+# define PP_OS_WIN
+#endif
+
+#include <set>
+#include <map>
+#include <vector>
+#include <string>
+#include <iterator>
+#include <iostream>
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+
+#include <fcntl.h>
+
+#ifdef HAVE_MMAP
+# include <sys/mman.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if (_MSC_VER >= 1400)
+# define FILENO _fileno
+#else
+# define FILENO fileno
+#endif
+
+#if defined (PP_OS_WIN)
+# define PATH_SEPARATOR '\\'
+#else
+# define PATH_SEPARATOR '/'
+#endif
+
+#if defined (RPP_JAMBI)
+# include "parser/rxx_allocator.h"
+#else
+# include "parser/rpp-allocator.h"
+#endif
+
+#if defined (_MSC_VER)
+# define pp_snprintf _snprintf
+#else
+# define pp_snprintf snprintf
+#endif
+
+#include "pp-fwd.h"
+#include "pp-cctype.h"
+#include "pp-string.h"
+#include "pp-symbol.h"
+#include "pp-internal.h"
+#include "pp-iterator.h"
+#include "pp-macro.h"
+#include "pp-environment.h"
+#include "pp-scanner.h"
+#include "pp-macro-expander.h"
+#include "pp-engine.h"
+#include "pp-engine-bits.h"
+
+#endif // PP_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/parser/rpp/preprocessor.cpp b/parser/rpp/preprocessor.cpp
new file mode 100644
index 000000000..be6a85186
--- /dev/null
+++ b/parser/rpp/preprocessor.cpp
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Harald Fernengel <harry@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "preprocessor.h"
+
+#include <string>
+
+// register callback for include hooks
+static void includeFileHook(const std::string &, const std::string &, FILE *);
+
+#define PP_HOOK_ON_FILE_INCLUDED(A, B, C) includeFileHook(A, B, C)
+#include "pp.h"
+
+using namespace rpp;
+
+#include <QtCore/QtCore>
+
+class PreprocessorPrivate
+{
+public:
+ QByteArray result;
+ pp_environment env;
+ QStringList includePaths;
+
+ void initPP(pp &proc) {
+ foreach(QString path, includePaths)
+ proc.push_include_path(path.toStdString());
+ }
+};
+
+QHash<QString, QStringList> includedFiles;
+
+void includeFileHook(const std::string &fileName, const std::string &filePath, FILE *)
+{
+ includedFiles[QString::fromStdString(fileName)].append(QString::fromStdString(filePath));
+}
+
+Preprocessor::Preprocessor()
+{
+ d = new PreprocessorPrivate;
+ includedFiles.clear();
+}
+
+Preprocessor::~Preprocessor()
+{
+ delete d;
+}
+
+void Preprocessor::processFile(const QString &fileName)
+{
+ pp proc(d->env);
+ d->initPP(proc);
+
+ d->result.reserve(d->result.size() + 20 * 1024);
+
+ d->result += "# 1 \"" + fileName.toLatin1() + "\"\n"; // ### REMOVE ME
+ proc.file(fileName.toLocal8Bit().constData(), std::back_inserter(d->result));
+}
+
+void Preprocessor::processString(const QByteArray &str)
+{
+ pp proc(d->env);
+ d->initPP(proc);
+
+ proc(str.begin(), str.end(), std::back_inserter(d->result));
+}
+
+QByteArray Preprocessor::result() const
+{
+ return d->result;
+}
+
+void Preprocessor::addIncludePaths(const QStringList &includePaths)
+{
+ d->includePaths += includePaths;
+}
+
+QStringList Preprocessor::macroNames() const
+{
+ QStringList macros;
+
+ pp_environment::const_iterator it = d->env.first_macro();
+ while (it != d->env.last_macro()) {
+ const pp_macro *m = *it;
+ macros += QString::fromLatin1(m->name->begin(), m->name->size());
+ ++it;
+ }
+
+ return macros;
+}
+
+QList<Preprocessor::MacroItem> Preprocessor::macros() const
+{
+ QList<MacroItem> items;
+
+ pp_environment::const_iterator it = d->env.first_macro();
+ while (it != d->env.last_macro()) {
+ const pp_macro *m = *it;
+ MacroItem item;
+ item.name = QString::fromLatin1(m->name->begin(), m->name->size());
+ item.definition = QString::fromLatin1(m->definition->begin(),
+ m->definition->size());
+ for (size_t i = 0; i < m->formals.size(); ++i) {
+ item.parameters += QString::fromLatin1(m->formals[i]->begin(),
+ m->formals[i]->size());
+ }
+ item.isFunctionLike = m->function_like;
+
+#ifdef PP_WITH_MACRO_POSITION
+ item.fileName = QString::fromLatin1(m->file->begin(), m->file->size());
+#endif
+ items += item;
+
+ ++it;
+ }
+
+ return items;
+}
+
+/*
+int main()
+{
+ Preprocessor pp;
+
+ QStringList paths;
+ paths << "/usr/include";
+ pp.addIncludePaths(paths);
+
+ pp.processFile("pp-configuration");
+ pp.processFile("/usr/include/stdio.h");
+
+ qDebug() << pp.result();
+
+ return 0;
+}
+*/
+
diff --git a/parser/rpp/preprocessor.h b/parser/rpp/preprocessor.h
new file mode 100644
index 000000000..c363ea7c8
--- /dev/null
+++ b/parser/rpp/preprocessor.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright 2005 Harald Fernengel <harry@kdevelop.org>
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef PREPROCESSOR_H
+#define PREPROCESSOR_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+
+class QByteArray;
+class PreprocessorPrivate;
+
+class Preprocessor
+{
+public:
+ Preprocessor();
+ ~Preprocessor();
+
+ void processFile(const QString &fileName);
+ void processString(const QByteArray &str);
+
+ void addIncludePaths(const QStringList &includePaths);
+
+ QByteArray result() const;
+
+ QStringList macroNames() const;
+
+ struct MacroItem {
+ QString name;
+ QStringList parameters;
+ QString definition;
+ bool isFunctionLike;
+#ifdef PP_WITH_MACRO_POSITION
+ QString fileName;
+#endif
+ };
+ QList<MacroItem> macros() const;
+
+private:
+ Q_DISABLE_COPY(Preprocessor)
+ PreprocessorPrivate *d;
+};
+
+#endif