|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r60817 - in trunk/boost/wave: . util
From: hartmut.kaiser_at_[hidden]
Date: 2010-03-24 19:36:18
Author: hkaiser
Date: 2010-03-24 19:36:17 EDT (Wed, 24 Mar 2010)
New Revision: 60817
URL: http://svn.boost.org/trac/boost/changeset/60817
Log:
Wave: added new preprocessing hook: emit_line_directive, fixed a couple related problems
Text files modified:
trunk/boost/wave/cpp_context.hpp | 7 +
trunk/boost/wave/cpp_iteration_context.hpp | 10 +
trunk/boost/wave/preprocessing_hooks.hpp | 30 +++++++
trunk/boost/wave/util/cpp_include_paths.hpp | 44 ++++++++++
trunk/boost/wave/util/cpp_iterator.hpp | 165 ++++++++++++++++++++++-----------------
5 files changed, 177 insertions(+), 79 deletions(-)
Modified: trunk/boost/wave/cpp_context.hpp
==============================================================================
--- trunk/boost/wave/cpp_context.hpp (original)
+++ trunk/boost/wave/cpp_context.hpp 2010-03-24 19:36:17 EDT (Wed, 24 Mar 2010)
@@ -136,6 +136,7 @@
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
, current_filename(fname)
#endif
+ , current_relative_filename(fname)
, macros(*this_())
, language(language_support(
support_cpp
@@ -417,6 +418,11 @@
}
#endif
+ void set_current_relative_filename(char const *real_name)
+ { current_relative_filename = real_name; }
+ std::string const &get_current_relative_filename() const
+ { return current_relative_filename; }
+
#if BOOST_WAVE_SERIALIZATION != 0
public:
BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
@@ -502,6 +508,7 @@
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
std::string current_filename; // real name of current preprocessed file
#endif
+ std::string current_relative_filename; // real relative name of current preprocessed file
boost::wave::util::if_block_stack ifblocks; // conditional compilation contexts
boost::wave::util::include_paths includes; // lists of include directories to search
Modified: trunk/boost/wave/cpp_iteration_context.hpp
==============================================================================
--- trunk/boost/wave/cpp_iteration_context.hpp (original)
+++ trunk/boost/wave/cpp_iteration_context.hpp 2010-03-24 19:36:17 EDT (Wed, 24 Mar 2010)
@@ -97,20 +97,22 @@
public:
base_iteration_context(ContextT& ctx_,
BOOST_WAVE_STRINGTYPE const &fname, std::size_t if_block_depth = 0)
- : real_filename(fname), filename(fname), line(1), emitted_lines(1),
- if_block_depth(if_block_depth), ctx(ctx_)
+ : real_filename(fname), real_relative_filename(fname), filename(fname),
+ line(1), emitted_lines(0), if_block_depth(if_block_depth), ctx(ctx_)
{}
base_iteration_context(ContextT& ctx_,
IteratorT const &first_, IteratorT const &last_,
BOOST_WAVE_STRINGTYPE const &fname, std::size_t if_block_depth = 0)
- : first(first_), last(last_), real_filename(fname), filename(fname),
- line(1), emitted_lines(1), if_block_depth(if_block_depth), ctx(ctx_)
+ : first(first_), last(last_), real_filename(fname),
+ real_relative_filename(fname), filename(fname),
+ line(1), emitted_lines(0), if_block_depth(if_block_depth), ctx(ctx_)
{}
// the actual input stream
IteratorT first; // actual input stream position
IteratorT last; // end of input stream
BOOST_WAVE_STRINGTYPE real_filename; // real name of the current file
+ BOOST_WAVE_STRINGTYPE real_relative_filename; // real relative name of the current file
BOOST_WAVE_STRINGTYPE filename; // actual processed file
unsigned int line; // line counter of underlying stream
unsigned int emitted_lines; // count of emitted newlines
Modified: trunk/boost/wave/preprocessing_hooks.hpp
==============================================================================
--- trunk/boost/wave/preprocessing_hooks.hpp (original)
+++ trunk/boost/wave/preprocessing_hooks.hpp 2010-03-24 19:36:17 EDT (Wed, 24 Mar 2010)
@@ -374,6 +374,36 @@
///////////////////////////////////////////////////////////////////////////
//
+ // The function 'emit_line_directive' is called whenever a #line directive
+ // has to be emitted into the generated output.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'pending' may be used to push tokens back into the input
+ // stream, which are to be used instead of the default output generated
+ // for the #line directive.
+ //
+ // The parameter 'act_token' contains the actual #pragma token, which may
+ // be used for error output. The line number stored in this token can be
+ // used as the line number emitted as part of the #line directive.
+ //
+ // If the return value is 'false', a default #line directive is emitted
+ // by the library. A return value of 'true' will inhibit any further
+ // actions, the tokens contained in 'pending' will be copied verbatim
+ // to the output.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT, typename ContainerT>
+ bool
+ emit_line_directive(ContextT const& ctx, ContainerT &pending,
+ typename ContextT::token_type const& act_token)
+ {
+ return false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
// The function 'defined_macro' is called, whenever a macro was defined
// successfully.
//
Modified: trunk/boost/wave/util/cpp_include_paths.hpp
==============================================================================
--- trunk/boost/wave/util/cpp_include_paths.hpp (original)
+++ trunk/boost/wave/util/cpp_include_paths.hpp 2010-03-24 19:36:17 EDT (Wed, 24 Mar 2010)
@@ -401,6 +401,42 @@
///////////////////////////////////////////////////////////////////////////////
// Set current directory from a given file name
+inline bool
+as_relative_to(boost::filesystem::path const& path,
+ boost::filesystem::path const& base, boost::filesystem::path& result)
+{
+ if (path.has_root_path()) {
+ if (path.root_path() == base.root_path())
+ return as_relative_to(path.relative_path(), base.relative_path(), result);
+
+ result = path; // that's our result
+ }
+ else {
+ if (base.has_root_path()) {
+ // cannot find relative path from a relative path and a rooted base
+ return false;
+ }
+ else {
+ typedef boost::filesystem::path::const_iterator path_iterator;
+ path_iterator path_it = path.begin();
+ path_iterator base_it = base.begin();
+ while (path_it != path.end() && base_it != base.end() ) {
+ if (*path_it != *base_it)
+ break;
+ ++path_it; ++base_it;
+ }
+
+ for (/**/; base_it != base.end(); ++base_it)
+ result /= "..";
+
+ for (/**/; path_it != path.end(); ++path_it)
+ result /= *path_it;
+ }
+ }
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
inline
void include_paths::set_current_directory(char const *path_)
{
@@ -409,12 +445,16 @@
fs::path filepath (create_path(path_));
fs::path filename = fs::complete(filepath, current_dir);
if (fs::exists(filename) && fs::is_directory(filename)) {
+ current_rel_dir.clear();
+ if (!as_relative_to(filepath, current_dir, current_rel_dir))
+ current_rel_dir = filepath;
current_dir = filename;
- current_rel_dir = filepath;
}
else {
+ current_rel_dir.clear();
+ if (!as_relative_to(branch_path(filepath), current_dir, current_rel_dir))
+ current_rel_dir = branch_path(filepath);
current_dir = branch_path(filename);
- current_rel_dir = branch_path(filepath);
}
}
Modified: trunk/boost/wave/util/cpp_iterator.hpp
==============================================================================
--- trunk/boost/wave/util/cpp_iterator.hpp (original)
+++ trunk/boost/wave/util/cpp_iterator.hpp 2010-03-24 19:36:17 EDT (Wed, 24 Mar 2010)
@@ -285,6 +285,7 @@
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
ctx_.set_current_filename(pos_.get_file().c_str());
#endif
+ iter_ctx->emitted_lines = (unsigned int)(-1); // force #line directive
}
// get the next preprocessed token
@@ -418,6 +419,7 @@
iter_ctx = ctx.pop_iteration_context();
must_emit_line_directive = true;
+ iter_ctx->emitted_lines = (unsigned int)(-1); // force #line directive
seen_newline = true;
// restore current file position
@@ -433,6 +435,7 @@
ctx.set_current_filename(real_filename.c_str());
#endif
ctx.set_current_directory(iter_ctx->real_filename.c_str());
+ ctx.set_current_relative_filename(iter_ctx->real_relative_filename.c_str());
// ensure the integrity of the #if/#endif stack
// report unbalanced #if/#endif now to make it possible to recover properly
@@ -735,16 +738,22 @@
typename ContextT::position_type pos = act_token.get_position();
+// if (must_emit_line_directive &&
+// iter_ctx->emitted_lines+1 == act_pos.get_line() &&
+// iter_ctx->filename == act_pos.get_file())
+// {
+// must_emit_line_directive = false;
+// return false;
+// }
+
if (must_emit_line_directive ||
- iter_ctx->emitted_lines != act_pos.get_line())
+ iter_ctx->emitted_lines+1 != act_pos.get_line())
{
// unput the current token
pending_queue.push_front(act_token);
pos.set_line(act_pos.get_line());
- if (!must_emit_line_directive &&
- iter_ctx->emitted_lines+1 == act_pos.get_line())
- {
+ if (iter_ctx->emitted_lines+2 == act_pos.get_line()) {
// prefer to output a single newline instead of the #line directive
// whitespace.shift_tokens(T_NEWLINE);
act_token = result_type(T_NEWLINE, "\n", pos);
@@ -752,48 +761,52 @@
else {
// account for the newline emitted here
act_pos.set_line(act_pos.get_line()-1);
- iter_ctx->emitted_lines = act_pos.get_line();
+ iter_ctx->emitted_lines = act_pos.get_line()-1;
+
+ token_sequence_type pending;
+
+ if (!ctx.get_hooks().emit_line_directive(ctx, pending, act_token))
+ {
+ unsigned int column = 6;
+
+ // the hook did not generate anything, emit default #line
+ pos.set_column(1);
+ pending.push_back(result_type(T_PP_LINE, "#line", pos));
+
+ pos.set_column(column); // account for '#line'
+ pending.push_back(result_type(T_SPACE, " ", pos));
+
+ // 21 is the max required size for a 64 bit integer represented as a
+ // string
+ char buffer[22];
- // the #line directive has to be pushed back into the pending queue in
- // reverse order
+ using namespace std; // for some systems sprintf is in namespace std
+ sprintf (buffer, "%d", pos.get_line());
- // unput the complete #line directive in reverse order
- std::string file("\"");
- boost::filesystem::path filename(
- wave::util::create_path(act_pos.get_file().c_str()));
-
- using wave::util::impl::escape_lit;
- file += escape_lit(wave::util::native_file_string(filename)) + "\"";
-
- // 21 is the max required size for a 64 bit integer represented as a
- // string
- char buffer[22];
-
- using namespace std; // for some systems sprintf is in namespace std
- sprintf (buffer, "%d", pos.get_line());
-
- // adjust the generated column numbers accordingly
- // #line<space>number<space>filename<newline>
- unsigned int filenamelen = (unsigned int)file.size();
- unsigned int column = 7 + (unsigned int)strlen(buffer) + filenamelen;
-
- pos.set_line(pos.get_line() - 1); // adjust line number
-
- pos.set_column(column);
- pending_queue.push_front(result_type(T_GENERATEDNEWLINE, "\n", pos));
- pos.set_column(column -= filenamelen); // account for filename
- pending_queue.push_front(result_type(T_STRINGLIT, file.c_str(), pos));
- pos.set_column(--column); // account for ' '
- pending_queue.push_front(result_type(T_SPACE, " ", pos));
- pos.set_column(column -= (unsigned int)strlen(buffer)); // account for <number>
- pending_queue.push_front(result_type(T_INTLIT, buffer, pos));
- pos.set_column(--column); // account for ' '
- pending_queue.push_front(result_type(T_SPACE, " ", pos));
-
- // return the #line token itself
-// whitespace.shift_tokens(T_PP_LINE);
- pos.set_column(1);
- act_token = result_type(T_PP_LINE, "#line", pos);
+ pos.set_column(++column); // account for ' '
+ pending.push_back(result_type(T_INTLIT, buffer, pos));
+ pos.set_column(column += (unsigned int)strlen(buffer)); // account for <number>
+ pending.push_back(result_type(T_SPACE, " ", pos));
+ pos.set_column(++column); // account for ' '
+
+ std::string file("\"");
+ boost::filesystem::path filename(
+ wave::util::create_path(act_pos.get_file().c_str()));
+
+ using wave::util::impl::escape_lit;
+ file += escape_lit(wave::util::native_file_string(filename)) + "\"";
+
+ pending.push_back(result_type(T_STRINGLIT, file.c_str(), pos));
+ pos.set_column(column += (unsigned int)file.size()); // account for filename
+ pending.push_back(result_type(T_GENERATEDNEWLINE, "\n", pos));
+ }
+
+ // if there is some replacement text, insert it into the pending queue
+ if (!pending.empty()) {
+ pending_queue.splice(pending_queue.begin(), pending);
+ act_token = pending_queue.front();
+ pending_queue.pop_front();
+ }
}
must_emit_line_directive = false; // we are now in sync
@@ -855,30 +868,6 @@
///////////////////////////////////////////////////////////////////////////////
namespace impl {
- template <typename ContextT, typename IteratorT>
- bool next_token_is_pp_directive(ContextT &ctx, IteratorT &it, IteratorT const &end)
- {
- using namespace boost::wave;
-
- token_id id = T_UNKNOWN;
- for (/**/; it != end; ++it) {
- id = token_id(*it);
- if (!IS_CATEGORY(id, WhiteSpaceTokenType))
- break; // skip leading whitespace
- if (IS_CATEGORY(id, EOLTokenType))
- break; // do not enter a new line
-
- // this token get's skipped
-#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
- ctx.get_hooks().skipped_token(*it);
-#else
- ctx.get_hooks().skipped_token(ctx.derived(), *it);
-#endif
- }
- BOOST_ASSERT(it == end || id != T_UNKNOWN);
- return it != end && IS_CATEGORY(id, PPTokenType);
- }
-
// call 'found_directive' preprocessing hook
template <typename ContextT>
bool call_found_directive_hook(ContextT& ctx,
@@ -905,14 +894,39 @@
#endif
}
- // verify that there is'nt anything significant left on the line
+ template <typename ContextT, typename IteratorT>
+ bool next_token_is_pp_directive(ContextT &ctx, IteratorT &it, IteratorT const &end)
+ {
+ using namespace boost::wave;
+
+ token_id id = T_UNKNOWN;
+ for (/**/; it != end; ++it) {
+ id = token_id(*it);
+ if (!IS_CATEGORY(id, WhiteSpaceTokenType))
+ break; // skip leading whitespace
+ if (IS_CATEGORY(id, EOLTokenType) || IS_CATEGORY(id, EOFTokenType))
+ break; // do not enter a new line
+ if (T_CPPCOMMENT == id ||
+ context_policies::util::ccomment_has_newline(*it))
+ {
+ break;
+ }
+
+ // this token gets skipped
+ call_skipped_token_hook(ctx, *it);
+ }
+ BOOST_ASSERT(it == end || id != T_UNKNOWN);
+ return it != end && IS_CATEGORY(id, PPTokenType);
+ }
+
+ // verify that there isn't anything significant left on the line
template <typename ContextT, typename IteratorT>
bool pp_is_last_on_line(ContextT &ctx, IteratorT &it, IteratorT const &end,
bool call_hook = true)
{
using namespace boost::wave;
- // this token get's skipped
+ // this token gets skipped
if (call_hook)
call_skipped_token_hook(ctx, *it);
@@ -931,7 +945,7 @@
if (!IS_CATEGORY(id, WhiteSpaceTokenType))
break;
- // this token get's skipped
+ // this token gets skipped
if (call_hook)
call_skipped_token_hook(ctx, *it);
}
@@ -1557,8 +1571,8 @@
// preprocess the opened file
boost::shared_ptr<base_iteration_context_type> new_iter_ctx (
- new iteration_context_type(ctx, native_path_str.c_str(),
- act_pos, boost::wave::enable_prefer_pp_numbers(ctx.get_language())));
+ new iteration_context_type(ctx, native_path_str.c_str(), act_pos,
+ boost::wave::enable_prefer_pp_numbers(ctx.get_language())));
// call the include policy trace function
#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
@@ -1570,9 +1584,11 @@
#endif
// store current file position
+ iter_ctx->real_relative_filename = ctx.get_current_relative_filename().c_str();
iter_ctx->filename = act_pos.get_file();
iter_ctx->line = act_pos.get_line();
iter_ctx->if_block_depth = ctx.get_if_block_depth();
+ iter_ctx->emitted_lines = (unsigned int)(-1); // force #line directive
// push the old iteration context onto the stack and continue with the new
ctx.push_iteration_context(act_pos, iter_ctx);
@@ -1587,6 +1603,9 @@
ctx.set_current_filename(real_filename.c_str());
#endif
+ ctx.set_current_relative_filename(dir_path.c_str());
+ iter_ctx->real_relative_filename = dir_path.c_str();
+
act_pos.set_line(iter_ctx->line);
act_pos.set_column(0);
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk