|
|
/****************************************************************************
|
|
|
**
|
|
|
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
|
|
|
** Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
|
|
|
**
|
|
|
** This file is part of $PRODUCT$.
|
|
|
**
|
|
|
** $CPP_LICENSE$
|
|
|
**
|
|
|
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
|
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
**
|
|
|
****************************************************************************/
|
|
|
|
|
|
#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
|
|
|
};
|
|
|
|
|
|
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;
|
|
|
|