📄 cpp_macromap.hpp
字号:
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
Macro expansion engine
http://www.boost.org/
Copyright (c) 2001-2005 Hartmut Kaiser. Distributed under the Boost
Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED)
#define CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <list>
#include <map>
#include <set>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/wave/wave_config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/wave/util/time_conversion_helper.hpp>
#include <boost/wave/util/unput_queue_iterator.hpp>
#include <boost/wave/util/macro_helpers.hpp>
#include <boost/wave/util/macro_definition.hpp>
#include <boost/wave/util/symbol_table.hpp>
#include <boost/wave/util/cpp_macromap_utils.hpp>
#include <boost/wave/util/cpp_macromap_predef.hpp>
#include <boost/wave/grammars/cpp_defined_grammar_gen.hpp>
#include <boost/wave/wave_version.hpp>
#include <boost/wave/cpp_exceptions.hpp>
#include <boost/wave/language_support.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace wave {
namespace util {
///////////////////////////////////////////////////////////////////////////////
//
// macromap
//
// This class holds all currently defined macros and on demand expands
// those macrodefinitions
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
class macromap {
typedef macromap<ContextT> self_type;
typedef typename ContextT::token_type token_type;
typedef typename token_type::string_type string_type;
typedef typename token_type::position_type position_type;
typedef typename ContextT::token_sequence_type definition_container_type;
typedef std::vector<token_type> parameter_container_type;
typedef macro_definition<token_type, definition_container_type>
macro_definition_type;
typedef symbol_table<string_type, macro_definition_type>
defined_macros_type;
typedef typename defined_macros_type::value_type::second_type
macro_ref_type;
public:
macromap(ContextT &ctx_)
: current_macros(0), defined_macros(new defined_macros_type(1)),
main_pos("", 0), ctx(ctx_), macro_uid(1)
{
current_macros = defined_macros.get();
}
~macromap() {}
// Add a new macro to the given macro scope
bool add_macro(token_type const &name, bool has_parameters,
parameter_container_type ¶meters,
definition_container_type &definition, bool is_predefined = false,
defined_macros_type *scope = 0);
// Tests, whether the given macro name is defined in the given macro scope
bool is_defined(string_type const &name,
typename defined_macros_type::iterator &it,
defined_macros_type *scope = 0) const;
template <typename IteratorT>
bool is_defined(IteratorT const &begin, IteratorT const &end);
// Remove a macro name from the given macro scope
bool remove_macro(token_type const &token, bool even_predefined = false);
template <typename IteratorT, typename ContainerT>
token_type const &expand_tokensequence(IteratorT &first,
IteratorT const &last, ContainerT &pending, ContainerT &expanded,
bool expand_operator_defined);
// Expand all macros inside the given token sequence
template <typename IteratorT, typename ContainerT>
void expand_whole_tokensequence(ContainerT &expanded,
IteratorT &first, IteratorT const &last,
bool expand_operator_defined);
// Init the predefined macros (add them to the given scope)
void init_predefined_macros(char const *fname = "<Unknown>",
defined_macros_type *scope = 0, bool at_global_scope = true);
void predefine_macro(defined_macros_type *scope, string_type const &name,
token_type const &t);
// Init the internal macro symbol namespace
void reset_macromap();
position_type &get_main_pos() { return main_pos; }
protected:
// Helper functions for expanding all macros in token sequences
template <typename IteratorT, typename ContainerT>
token_type const &expand_tokensequence_worker(ContainerT &pending,
unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
bool expand_operator_defined);
// Collect all arguments supplied to a macro invocation
template <typename IteratorT, typename ContainerT, typename SizeT>
typename std::vector<ContainerT>::size_type collect_arguments (
token_type const curr_token, std::vector<ContainerT> &arguments,
IteratorT &next, IteratorT const &end, SizeT const ¶meter_count);
// Expand a single macro name
template <typename IteratorT, typename ContainerT>
bool expand_macro(ContainerT &pending, token_type const &name,
typename defined_macros_type::iterator it,
IteratorT &first, IteratorT const &last, bool expand_operator_defined,
defined_macros_type *scope = 0, ContainerT *queue_symbol = 0);
// Expand a predefined macro (__LINE__, __FILE__ and __INCLUDE_LEVEL__)
template <typename ContainerT>
bool expand_predefined_macro(token_type const &curr_token,
ContainerT &expanded);
// Expand a single macro argument
template <typename ContainerT>
void expand_argument (typename std::vector<ContainerT>::size_type arg,
std::vector<ContainerT> &arguments,
std::vector<ContainerT> &expanded_args, bool expand_operator_defined,
std::vector<bool> &has_expanded_args);
// Expand the replacement list (replaces parameters with arguments)
template <typename ContainerT>
void expand_replacement_list(
macro_definition_type const ¯odefinition,
std::vector<ContainerT> &arguments,
bool expand_operator_defined, ContainerT &expanded);
// Rescans the replacement list for macro expansion
template <typename IteratorT, typename ContainerT>
void rescan_replacement_list(token_type const &curr_token,
macro_definition_type ¯odef, ContainerT &replacement_list,
ContainerT &expanded, bool expand_operator_defined,
IteratorT &nfirst, IteratorT const &nlast);
// Resolves the operator defined() and replces the token with "0" or "1"
template <typename IteratorT, typename ContainerT>
token_type const &resolve_defined(IteratorT &first, IteratorT const &last,
ContainerT &expanded);
// Resolve operator _Pragma or the #pragma directive
template <typename IteratorT, typename ContainerT>
bool resolve_operator_pragma(IteratorT &first,
IteratorT const &last, ContainerT &expanded);
// Handle the concatenation operator '##'
template <typename ContainerT>
void concat_tokensequence(ContainerT &expanded);
template <typename ContainerT>
bool is_valid_concat(string_type new_value,
position_type const &pos, ContainerT &rescanned);
private:
defined_macros_type *current_macros; // current symbol table
boost::shared_ptr<defined_macros_type> defined_macros; // global symbol table
token_type act_token; // current token
position_type main_pos; // last token position in the pp_iterator
string_type base_name; // the name to be expanded by __BASE_FILE__
ContextT &ctx; // context object associated with the macromap
long macro_uid;
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// add_macro(): adds a new macro to the macromap
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline bool
macromap<ContextT>::add_macro(token_type const &name, bool has_parameters,
parameter_container_type ¶meters, definition_container_type &definition,
bool is_predefined, defined_macros_type *scope)
{
if (!is_predefined && impl::is_special_macroname (name.get_value())) {
// exclude special macro names
BOOST_WAVE_THROW(preprocess_exception, illegal_redefinition,
name.get_value().c_str(), main_pos);
}
if (AltExtTokenType == (token_id(name) & ExtTokenOnlyMask)) {
// exclude special operator names
BOOST_WAVE_THROW(preprocess_exception, illegal_operator_redefinition,
name.get_value().c_str(), main_pos);
}
// try to define the new macro
defined_macros_type *current_scope = scope ? scope : current_macros;
typename defined_macros_type::iterator it = current_scope->find(name.get_value());
if (it != current_scope->end()) {
// redefinition, should not be different
if ((*it).second->is_functionlike != has_parameters ||
!impl::parameters_equal((*it).second->macroparameters, parameters) ||
!impl::definition_equals((*it).second->macrodefinition, definition))
{
BOOST_WAVE_THROW(preprocess_exception, macro_redefinition,
name.get_value().c_str(), main_pos);
}
return false;
}
// test the validity of the parameter names
if (has_parameters) {
std::set<typename token_type::string_type> names;
typedef typename parameter_container_type::iterator
parameter_iterator_type;
typedef typename std::set<typename token_type::string_type>::iterator
name_iterator_type;
parameter_iterator_type end = parameters.end();
for (parameter_iterator_type itp = parameters.begin(); itp != end; ++itp)
{
name_iterator_type pit = names.find((*itp).get_value());
if (pit != names.end()) {
// duplicate parameter name
BOOST_WAVE_THROW(preprocess_exception, duplicate_parameter_name,
(*pit).c_str(), main_pos);
}
names.insert((*itp).get_value());
}
}
// insert a new macro node
std::pair<typename defined_macros_type::iterator, bool> p =
current_scope->insert(
typename defined_macros_type::value_type(
name.get_value(),
macro_ref_type(new macro_definition_type(name,
has_parameters, is_predefined, ++macro_uid)
)
)
);
if (!p.second) {
BOOST_WAVE_THROW(preprocess_exception, macro_insertion_error,
name.get_value().c_str(), main_pos);
}
// add the parameters and the definition
std::swap((*p.first).second->macroparameters, parameters);
std::swap((*p.first).second->macrodefinition, definition);
// call the context supplied preprocessing hook
ctx.defined_macro(name, has_parameters, (*p.first).second->macroparameters,
(*p.first).second->macrodefinition, is_predefined);
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// is_defined(): returns, whether a given macro is already defined
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline bool
macromap<ContextT>::is_defined(typename token_type::string_type const &name,
typename defined_macros_type::iterator &it,
defined_macros_type *scope) const
{
if (0 == scope) scope = current_macros;
if ((it = scope->find(name)) != scope->end())
return true; // found in symbol table
// quick pre-check
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -