2
0
mirror of https://github.com/boostorg/wave.git synced 2026-02-23 04:02:12 +00:00

Added Wave review candidate to repository.

[SVN r1909]
This commit is contained in:
Hartmut Kaiser
2004-01-26 06:23:58 +00:00
parent b683dba9be
commit bb119d710a
140 changed files with 74210 additions and 0 deletions

27
tool/build/Jamfile Normal file
View File

@@ -0,0 +1,27 @@
# Wave: A Standard compliant C++ preprocessor
#
# Boost Wave Library Build Jamfile
#
# Copyright (c) 2001-2004 Hartmut Kaiser
# http://spirit.sourceforge.net/
#
# Use, modification, and distribution is subject to 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)
subproject tools/wave/build ;
exe wave
: ../cpp.cpp
<lib>../../../libs/wave/build/boost_wave
<lib>../../../libs/program_options/build/boost_program_options
<lib>../../../libs/filesystem/build/boost_filesystem
:
<sysinclude>$(BOOST_ROOT)
<vc7.1><*><rtti>off # workaround for compiler bug
:
release
<runtime-link>static
<threading>single
;

24
tool/build/Jamfile.v2 Normal file
View File

@@ -0,0 +1,24 @@
# Wave: A Standard compliant C++ preprocessor
#
# Boost Wave Library Build Jamfile
#
# Copyright (c) 2001-2004 Hartmut Kaiser
# http://spirit.sourceforge.net/
#
# Use, modification, and distribution is subject to 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)
exe wave
: ../cpp.cpp
../../../libs/wave/build//boost_wave
../../../libs/program_options/build//boost_program_options
../../../libs/filesystem/build//boost_filesystem
:
<vc7.1><*><rtti>off # workaround for compiler bug
:
release
<runtime-link>static
<threading>single
;

654
tool/cpp.cpp Normal file
View File

@@ -0,0 +1,654 @@
/*=============================================================================
Wave: A Standard compliant C++ preprocessor library
Copyright (c) 2001-2004 Hartmut Kaiser
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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)
=============================================================================*/
#include "cpp.hpp" // global configuration
///////////////////////////////////////////////////////////////////////////////
// This sample requires the program_options library written by Vladimir Prus,
// which is already accepted into Boost, but not included with the
// distribution yet.
// It is available here: http://boost-sandbox.sourceforge.net/program_options.
//
#include <boost/program_options.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/timer.hpp>
///////////////////////////////////////////////////////////////////////////////
// Include Wave itself
#include <boost/wave.hpp>
// Include the lexer related stuff
#include <boost/wave/token_ids.hpp> // token Id's
#include <boost/wave/cpplexer/cpp_lex_token.hpp> // token type
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer type
#include "trace_macro_expansion.hpp"
///////////////////////////////////////////////////////////////////////////////
// include lexer specifics, import lexer names
//
#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION == 0
#include <boost/wave/cpplexer/re2clex/cpp_re2c_lexer.hpp>
#endif
///////////////////////////////////////////////////////////////////////////////
// include the grammar definitions, if these shouldn't be compiled separately
// (ATTENTION: _very_ large compilation times!)
//
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION == 0
#include <boost/wave/grammars/cpp_intlit_grammar.hpp>
#include <boost/wave/grammars/cpp_chlit_grammar.hpp>
#include <boost/wave/grammars/cpp_grammar.hpp>
#include <boost/wave/grammars/cpp_expression_grammar.hpp>
#include <boost/wave/grammars/cpp_predef_macros_grammar.hpp>
#include <boost/wave/grammars/cpp_defined_grammar.hpp>
#endif
///////////////////////////////////////////////////////////////////////////////
// import required names
using namespace boost::spirit;
using std::string;
using std::pair;
using std::vector;
using std::getline;
using std::ifstream;
using std::cout;
using std::cerr;
using std::endl;
using std::ostream;
using std::istreambuf_iterator;
namespace po = boost::program_options;
namespace fs = boost::filesystem;
///////////////////////////////////////////////////////////////////////////////
// print the current version
int print_version()
{
typedef boost::wave::cpplexer::lex_iterator<
boost::wave::cpplexer::lex_token<> >
lex_iterator_t;
typedef boost::wave::context<
std::string::iterator, lex_iterator_t,
boost::wave::iteration_context_policies::load_file_to_string,
trace_macro_expansion>
context_t;
string version (context_t::get_version_string());
cout
<< version.substr(1, version.size()-2) // strip quotes
<< " (" << CPP_VERSION_DATE << ")" // add date
<< endl;
return 0; // exit app
}
///////////////////////////////////////////////////////////////////////////////
// print the copyright statement
int print_copyright()
{
char const *copyright[] = {
"",
"Wave: A Standard conformant C++ preprocessor",
"Copyright (c) 2001-2004 Hartmut Kaiser",
"It is hosted by http://spirit.sourceforge.net/.",
"",
"Use, modification and distribution is subject to 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)",
0
};
for (int i = 0; 0 != copyright[i]; ++i)
cout << copyright[i] << endl;
return 0; // exit app
}
///////////////////////////////////////////////////////////////////////////////
namespace cmd_line_util {
// Additional command line parser which interprets '@something' as an
// option "config-file" with the value "something".
pair<string, string> at_option_parser(string const&s)
{
if ('@' == s[0])
return std::make_pair(string("config-file"), s.substr(1));
else
return pair<string, string>();
}
// class, which keeps include file information from the command line
class include_paths {
public:
include_paths() : seen_separator(false) {}
vector<string> paths; // stores user paths
vector<string> syspaths; // stores system paths
bool seen_separator; // command line contains a '-I-' option
// Function which validates additional tokens from command line.
static void
validate(boost::any &v, vector<string> const &tokens)
{
if (v.empty())
v = boost::any(include_paths());
include_paths *p = boost::any_cast<include_paths>(&v);
BOOST_SPIRIT_ASSERT(p);
// Assume only one path per '-I' occurrence.
string t = tokens[0];
if (t == "-") {
// found -I- option, so switch behaviour
p->seen_separator = true;
}
else if (p->seen_separator) {
// store this path as a system path
p->syspaths.push_back(t);
}
else {
// store this path as an user path
p->paths.push_back(t);
}
}
};
// Workaround for a problem in the program_options library: all options
// stored in a variables_map, which have an assigned validator function
// need an extraction operator.
std::istream& operator>>(std::istream& is, include_paths& p)
{
return is;
}
// Read all options from a given config file, parse and add them to the
// given variables_map
void read_config_file_options(string const &filename,
po::options_description const &desc, po::variables_map &vm,
bool may_fail = false)
{
ifstream ifs(filename.c_str());
if (!ifs.is_open()) {
if (!may_fail) {
cerr << filename
<< ": command line warning: config file not found"
<< endl;
}
return;
}
vector<string> options;
string line;
while (std::getline(ifs, line)) {
// skip empty lines
string::size_type pos = line.find_first_not_of(" \t");
if (pos == string::npos)
continue;
// skip comment lines
if ('#' != line[pos])
options.push_back(line);
}
if (options.size() > 0) {
po::options_and_arguments oa = po::parse_command_line(options, desc);
po::store(oa, vm, desc);
}
}
///////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////
namespace {
class auto_stop_watch : public stop_watch
{
public:
auto_stop_watch(bool print_time_, std::ostream &outstrm_)
: print_time(print_time_), outstrm(outstrm_)
{
}
~auto_stop_watch()
{
if (print_time) {
outstrm << "Elapsed time: "
<< this->format_elapsed_time()
<< std::endl;
}
}
private:
bool print_time;
std::ostream &outstrm;
};
///////////////////////////////////////////////////////////////////////////////
} // anonymous namespace
///////////////////////////////////////////////////////////////////////////////
// do the actual preprocessing
int do_actual_work (po::options_and_arguments const opts,
po::variables_map const &vm)
{
// current file position is saved for exception handling
boost::wave::util::file_position_t current_position;
try {
// process the given file
string file_name(opts.arguments().front());
ifstream instream(file_name.c_str());
string instring;
if (!instream.is_open()) {
cerr << "wave: could not open input file: " << file_name << endl;
return -1;
}
instream.unsetf(std::ios::skipws);
#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
// this is known to be very slow for large files on some systems
copy (istream_iterator<char>(instream),
istream_iterator<char>(),
inserter(instring, instring.end()));
#else
instring = string(istreambuf_iterator<char>(instream.rdbuf()),
istreambuf_iterator<char>());
#endif
// This sample uses the lex_iterator and lex_token types predefined with
// the Wave library, but it is possible to use your own types.
typedef boost::wave::cpplexer::lex_iterator<
boost::wave::cpplexer::lex_token<> >
lex_iterator_t;
typedef boost::wave::context<
std::string::iterator, lex_iterator_t,
boost::wave::iteration_context_policies::load_file_to_string,
trace_macro_expansion>
context_t;
// The C++ preprocessor iterators shouldn't be constructed directly. They
// are to be generated through a boost::wave::context<> object. This
// boost::wave::context object is additionally to be used to initialize and
// define different parameters of the actual preprocessing.
// The preprocessing of the input stream is done on the fly behind the
// scenes during iteration over the context_t::iterator_t stream.
std::ofstream traceout;
boost::wave::trace_policies::trace_flags enable_trace =
boost::wave::trace_policies::trace_nothing;
if (vm.count("traceto")) {
// try to open the file, where to put the trace output
string trace_file (vm["traceto"].as<string>());
if (trace_file != "-") {
traceout.open(trace_file.c_str());
if (!traceout.is_open()) {
cerr << "wave: could not open trace file: " << trace_file
<< endl;
return -1;
}
}
enable_trace = boost::wave::trace_policies::trace_macros;
}
if ((enable_trace & boost::wave::trace_policies::trace_macros) &&
!traceout.is_open())
{
// by default trace to std::cerr
traceout.copyfmt(cerr);
traceout.clear(cerr.rdstate());
static_cast<std::basic_ios<char> &>(traceout).rdbuf(cerr.rdbuf());
}
context_t ctx (instring.begin(), instring.end(), file_name.c_str(),
trace_macro_expansion(traceout, enable_trace));
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
// enable C99 mode, if appropriate (implies variadics)
if (vm.count("c99")) {
#if BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
if (vm.count("c++0x")) {
cerr <<
"wave: the C99 and C++0x modes are mutually exclusive, "
"working in C99 mode." << endl;
}
#endif
ctx.set_language(boost::wave::support_c99);
}
#if BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
// enable experimental C++0x mode (implies variadics)
else if (vm.count("c++0x")) {
ctx.set_language(boost::wave::support_cpp0x);
}
#endif
else if (vm.count("variadics")) {
// enable variadics and placemarkers, if appropriate
ctx.set_language(boost::wave::enable_variadics(ctx.get_language()));
}
#endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
// add include directories to the system include search paths
if (vm.count("sysinclude")) {
vector<string> syspaths = vm["sysinclude"].as<vector<string> >();
vector<string>::const_iterator end = syspaths.end();
for (vector<string>::const_iterator cit = syspaths.begin();
cit != end; ++cit)
{
ctx.add_sysinclude_path((*cit).c_str());
}
}
// add include directories to the include search paths
if (vm.count("include")) {
cmd_line_util::include_paths const &ip =
vm["include"].as<cmd_line_util::include_paths>();
vector<string>::const_iterator end = ip.paths.end();
for (vector<string>::const_iterator cit = ip.paths.begin();
cit != end; ++cit)
{
ctx.add_include_path((*cit).c_str());
}
// if on the command line was given -I- , this has to be propagated
if (ip.seen_separator)
ctx.set_sysinclude_delimiter();
// add system include directories to the include path
vector<string>::const_iterator sysend = ip.syspaths.end();
for (vector<string>::const_iterator syscit = ip.syspaths.begin();
syscit != sysend; ++syscit)
{
ctx.add_sysinclude_path((*syscit).c_str());
}
}
// add additional defined macros
if (vm.count("define")) {
vector<string> macros = vm["define"].as<vector<string> >();
vector<string>::const_iterator end = macros.end();
for (vector<string>::const_iterator cit = macros.begin();
cit != end; ++cit)
{
ctx.add_macro_definition(*cit);
}
}
// add additional predefined macros
if (vm.count("predefine")) {
vector<string> predefmacros = vm["predefine"].as<vector<string> >();
vector<string>::const_iterator end = predefmacros.end();
for (vector<string>::const_iterator cit = predefmacros.begin();
cit != end; ++cit)
{
ctx.add_macro_definition(*cit, true);
}
}
// undefine specified macros
if (vm.count("undefine")) {
vector<string> undefmacros = vm["undefine"].as<vector<string> >();
vector<string>::const_iterator end = undefmacros.end();
for (vector<string>::const_iterator cit = undefmacros.begin();
cit != end; ++cit)
{
ctx.remove_macro_definition((*cit).c_str(), true);
}
}
// maximal include nesting depth
if (vm.count("nesting")) {
int max_depth = vm["nesting"].as<int>();
if (max_depth < 1 || max_depth > 100000) {
cerr << "wave: bogus maximal include nesting depth: "
<< max_depth << endl;
return -1;
}
ctx.set_max_include_nesting_depth(max_depth);
}
// open the output file
std::ofstream output;
if (vm.count("output")) {
// try to open the file, where to put the preprocessed output
string out_file (vm["output"].as<string>());
output.open(out_file.c_str());
if (!output.is_open()) {
cerr << "wave: could not open output file: " << out_file << endl;
return -1;
}
}
else {
// output the preprocessed result to std::cout
output.copyfmt(cout);
output.clear(cout.rdstate());
static_cast<std::basic_ios<char> &>(output).rdbuf(cout.rdbuf());
}
// analyze the input file
context_t::iterator_t first = ctx.begin();
context_t::iterator_t last = ctx.end();
// preprocess the required include files
if (vm.count("forceinclude")) {
// add the filenames to force as include files in _reverse_ order
// the second parameter 'is_last' for the force_include function should
// be set to true for the last (first given) file.
vector<string> force = vm["forceinclude"].as<vector<string> >();
vector<string>::const_reverse_iterator rend = force.rend();
for (vector<string>::const_reverse_iterator cit = force.rbegin();
cit != rend; /**/)
{
string filename(*cit);
first.force_include(filename.c_str(), ++cit == rend);
}
}
// loop over all generated tokens outputing the generated text
auto_stop_watch elapsed_time(vm.count("timer") > 0, cerr);
while (first != last) {
// print out the string representation of this token (skip comments)
using namespace boost::wave;
// store the last known good token position
current_position = (*first).get_position();
token_id id = token_id(*first);
if (T_CPPCOMMENT == id || T_NEWLINE == id) {
// C++ comment tokens contain the trailing newline
output << endl;
}
else if (id != T_CCOMMENT) {
// print out the current token value
output << (*first).get_value();
}
++first; // advance to the next token
}
}
catch (boost::wave::cpp_exception &e) {
// some preprocessing error
cerr
<< e.file_name() << "(" << e.line_no() << "): "
<< e.description() << endl;
return 1;
}
catch (boost::wave::cpplexer::lexing_exception &e) {
// some lexing error
cerr
<< e.file_name() << "(" << e.line_no() << "): "
<< e.description() << endl;
return 2;
}
catch (std::exception &e) {
// use last recognized token to retrieve the error position
cerr
<< current_position.get_file()
<< "(" << current_position.get_line() << "): "
<< "exception caught: " << e.what()
<< endl;
return 3;
}
catch (...) {
// use last recognized token to retrieve the error position
cerr
<< current_position.get_file()
<< "(" << current_position.get_line() << "): "
<< "unexpected exception caught." << endl;
return 4;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// main entry point
int
main (int argc, char const *argv[])
{
try {
// analyze the command line options and arguments
vector<string> cfg_files;
// declare the options allowed from the command line only
po::options_description desc_cmdline ("Options allowed on the command line only");
desc_cmdline.add_options()
("help,h", "", "print out program usage (this message)")
("version,v", "", "print the version number")
("copyright,c", "", "print out the copyright statement")
("config-file", po::parameter("filepath", &cfg_files),
"specify a config file (alternatively: @filepath)")
;
// declare the options allowed on command line and in config files
po::options_description desc_generic ("Options allowed additionally in a config file");
desc_generic.add_options()
("output,o", "path", "specify a file to use for output instead of stdout")
("include,I", "path", "specify an additional include directory").
validator(&cmd_line_util::include_paths::validate)
("sysinclude,S", po::parameter<vector<string> >("syspath"),
"specify an additional system include directory")
("forceinclude,F", po::parameter<vector<string> >("file"),
"force inclusion of the given file")
("define,D", po::parameter<vector<string> >("macro[=[value]]"),
"specify a macro to define")
("predefine,P", po::parameter<vector<string> >("macro[=[value]]"),
"specify a macro to predefine")
("undefine,U", po::parameter<vector<string> >("macro"),
"specify a macro to undefine")
("nesting,n", po::parameter<int>("depth"),
"specify a new maximal include nesting depth")
;
po::options_description desc_ext ("Extended options (allowed everywhere)");
desc_ext.add_options()
("traceto,t", "path", "output trace info to a file [path] or to stderr [-]")
("timer", "", "output overall elapsed computing time to stderr")
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
("variadics", "", "enable certain C99 extensions in C++ mode")
("c99", "", "enable C99 mode (implies --variadics)")
#endif
#if BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
("c++0x", "", "enable C++0x support (implies --variadics)")
#endif
;
// combine the options for the different usage schemes
po::options_description desc_overall_cmdline;
desc_overall_cmdline.add(desc_cmdline);
desc_overall_cmdline.add(desc_generic);
desc_overall_cmdline.add(desc_ext);
po::options_description desc_overall_cfgfile;
desc_overall_cfgfile.add(desc_generic);
desc_overall_cfgfile.add(desc_ext);
// parse command line and store results
po::options_and_arguments opts = po::parse_command_line(argc, argv,
desc_overall_cmdline, 0, cmd_line_util::at_option_parser);
po::variables_map vm;
po::store(opts, vm, desc_overall_cmdline);
// Try to find a wave.cfg in the same directory as the executable was
// started from. If this exists, treat it as a wave config file
fs::path filename(argv[0], fs::native);
filename = filename.branch_path() / "wave.cfg";
cmd_line_util::read_config_file_options(filename.string(),
desc_overall_cfgfile, vm, true);
// if there is specified at least one config file, parse it and add the
// options to the main variables_map
if (vm.count("config-file")) {
vector<string>::const_iterator end = cfg_files.end();
for (vector<string>::const_iterator cit = cfg_files.begin();
cit != end; ++cit)
{
// parse a single config file and store the results
cmd_line_util::read_config_file_options(*cit,
desc_overall_cfgfile, vm);
}
}
// ... act as required
if (vm.count("help")) {
po::options_description desc_help (
"Usage: wave [options] [@config-file(s)] file");
desc_help.add(desc_cmdline);
desc_help.add(desc_generic);
desc_help.add(desc_ext);
cout << desc_help << endl;
return 1;
}
if (vm.count("version")) {
return print_version();
}
if (vm.count("copyright")) {
return print_copyright();
}
// if there is no input file given, then exit
if (0 == opts.arguments().size()) {
cerr << "wave: no input file given, "
<< "use --help to get a hint." << endl;
return 5;
}
// preprocess the given input file
return do_actual_work(opts, vm);
}
catch (std::exception &e) {
cout << "wave: exception caught: " << e.what() << endl;
return 6;
}
catch (...) {
cerr << "wave: unexpected exception caught." << endl;
return 7;
}
}

44
tool/cpp.hpp Normal file
View File

@@ -0,0 +1,44 @@
/*=============================================================================
Wave: A Standard compliant C++ preprocessor library
Copyright (c) 2001-2004 Hartmut Kaiser
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED)
#define CPP_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED
///////////////////////////////////////////////////////////////////////////////
// This file may be used as a precompiled header (if applicable)
///////////////////////////////////////////////////////////////////////////////
// include often used files from the stdlib
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
///////////////////////////////////////////////////////////////////////////////
// include boost config
#include <boost/config.hpp> // global configuration information
///////////////////////////////////////////////////////////////////////////////
// build version
#include "cpp_version.hpp"
///////////////////////////////////////////////////////////////////////////////
// configure this app here (global configuration constants)
#include "cpp_config.hpp"
///////////////////////////////////////////////////////////////////////////////
// include required boost libraries
#include <boost/assert.hpp>
#include <boost/pool/pool_alloc.hpp>
#endif // !defined(CPP_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED)

228
tool/cpp_config.hpp Normal file
View File

@@ -0,0 +1,228 @@
/*=============================================================================
Wave: A Standard compliant C++ preprocessor library
Global application configuration of the Wave driver command
Copyright (c) 2001-2004 Hartmut Kaiser
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED)
#define CPP_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED
///////////////////////////////////////////////////////////////////////////////
// Decide, whether to implement macro scopes (#scope/#endscope), variadics,
// placemarkers and well defined token pasting in C++ mode
//
// To implement these features, uncomment the following
//
#define BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS 1
///////////////////////////////////////////////////////////////////////////////
// Define the macro scoping keywords to be used for the experimental macro
// scoping support.
//
// If the following macros aren't defined, the corresponding default value is
// used.
//
// Note, if you change this, you will have to change the corresponding entries
// inside the wave/cpplexer/re2c/cpp.re file too.
//
//#define BOOST_WAVE_PP_REGION "region"
//#define BOOST_WAVE_PP_REGION_UC "REGION" // uppercase of BOOST_WAVE_PP_REGION
//#define BOOST_WAVE_PP_ENDREGION "endregion"
//#define BOOST_WAVE_PP_IMPORT "import"
///////////////////////////////////////////////////////////////////////////////
// Define the maximal include nesting depth allowed. If this value isn't
// defined it defaults to 1024
//
// To define a new initial include nesting depth uncomment the following and
// supply a new integer value.
//
//#define BOOST_WAVE_MAX_INCLUDE_LEVEL_DEPTH 1024
///////////////////////////////////////////////////////////////////////////////
// Decide, whether to support variadics and placemarkers
//
// To implement support variadics and placemarkers uncomment the following
//
#define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 1
///////////////////////////////////////////////////////////////////////////////
// Decide, whether to implement a #warning directive as
//
// To implement #warning directives, uncomment the following
//
#define BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE 1
///////////////////////////////////////////////////////////////////////////////
// Decide, whether to implement #pragma once
//
// To implement #pragma once, uncomment the following
//
#define BOOST_WAVE_SUPPORT_PRAGMA_ONCE 1
///////////////////////////////////////////////////////////////////////////////
// Decide, whether to implement #include_next
// Please note, that this is an extension to the C++ Standard.
//
// To implement #include_next, uncomment the following
//
#define BOOST_WAVE_SUPPORT_INCLUDE_NEXT 1
///////////////////////////////////////////////////////////////////////////////
// Undefine the following, to enable some MS specific language extensions:
// __int8, __int16, __int32, __int64, __based, __declspec, __cdecl,
// __fastcall, __stdcall, __try, __except, __finally, __leave, __inline,
// __asm
#define BOOST_WAVE_SUPPORT_MS_EXTENSIONS 1
///////////////////////////////////////////////////////////////////////////////
// Allow the message body of the #error and #warning directives to be
// preprocessed before the diagnostic is issued.
//
// Uncommenting the following will preprocess the message bodies of #error and
// #warning messages before the error (warning) is issued
//
#define BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY 1
///////////////////////////////////////////////////////////////////////////////
// Allow the #pragma directives to be returned to the caller (optionally after
// preprocessing the body)
//
// Undefining the following will skip #pragma directives, so that the caller
// will not see them.
//
#define BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES 1
///////////////////////////////////////////////////////////////////////////////
// Allow the body of a #pragma directive to be preprocessed before the
// directive is returned to the caller.
//
// Uncommenting the following will preprocess the bodies of #pragma directives
//
#define BOOST_WAVE_PREPROCESS_PRAGMA_BODY 1
///////////////////////////////////////////////////////////////////////////////
// Allow to define macros with the command line syntax (-DMACRO(x)=definition)
//
// Uncommenting the following will enable the possibility to define macros
// based on the command line syntax
//
#define BOOST_WAVE_ENABLE_COMMANDLINE_MACROS 1
///////////////////////////////////////////////////////////////////////////////
// Define the string type to be used to store the token values and the file
// names inside a file_position template class
//
// use the following, if you have a fast std::allocator<char>
#define BOOST_WAVE_STRINGTYPE wave::util::flex_string< \
char, std::char_traits<char>, std::allocator<char>, \
wave::util::CowString</*char,*/ \
wave::util::AllocatorStringStorage<char> > \
> \
/**/
#include <boost/wave/util/flex_string.hpp>
///////////////////////////////////////////////////////////////////////////////
// Uncomment the following, if you need debug output, the
// BOOST_SPIRIT_DEBUG_FLAGS constants below help to fine control the amount of
// the generated debug output
//#define BOOST_SPIRIT_DEBUG
///////////////////////////////////////////////////////////////////////////////
// debug rules, subrules and grammars only, for possible flags see
// spirit/debug.hpp
#if defined(BOOST_SPIRIT_DEBUG)
#define BOOST_SPIRIT_DEBUG_FLAGS ( \
BOOST_SPIRIT_DEBUG_FLAGS_NODES | \
BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES \
) \
/**/
///////////////////////////////////////////////////////////////////////////////
// debug flags for the pp-iterator library, possible flags (defined in
// wave_config.hpp):
//
// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR 0x0001
// #define BOOST_SPIRIT_DEBUG_FLAGS_TIME_CONVERSION 0x0002
// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR 0x0004
// #define BOOST_SPIRIT_DEBUG_FLAGS_INTLIT_GRAMMAR 0x0008
// #define BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR 0x0010
// #define BOOST_SPIRIT_DEBUG_FLAGS_DEFINED_GRAMMAR 0x0020
// #define BOOST_SPIRIT_DEBUG_FLAGS_PREDEF_MACROS_GRAMMAR 0x0040
#define BOOST_SPIRIT_DEBUG_FLAGS_CPP (\
/* insert the required flags from above */ \
) \
/**/
#endif
///////////////////////////////////////////////////////////////////////////////
//
// For all recognized preprocessor statements the output parse trees
// formatted as xml are printed. The formatted parse trees are streamed to the
// std::ostream defined by the BOOST_WAVE_DUMP_PARSE_TREE_OUT constant.
//
// Uncomment the following, if you want to see these parse trees.
//
//#define BOOST_WAVE_DUMP_PARSE_TREE 1
//#define BOOST_WAVE_DUMP_PARSE_TREE_OUT std::cerr
///////////////////////////////////////////////////////////////////////////////
//
// For all #if and #elif directives the preprocessed expressions are printed.
// These expressions are streamed to the std::ostream defined by the
// BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT constant.
//
// Uncomment the following, if you want to see the preprocessed expressions
//
//#define BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS 1
//#define BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT std::cerr
///////////////////////////////////////////////////////////////////////////////
// Decide, whether to use the separate compilation model for the instantiation
// of the C++ lexer objects.
//
// If this is defined, you should explicitly instantiate the C++ lexer
// template with the correct parameters in a separate compilation unit of
// your program (see the files instantiate_slex_lexer.cpp and
// instantiate_re2c_lexer.cpp).
//
// To use the lexer inclusion model, uncomment the following
//
#define BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION 1
///////////////////////////////////////////////////////////////////////////////
// Decide, whether to use the separate compilation model for the instantiation
// of the grammar objects.
//
// If this is defined, you should explicitly instantiate the grammar
// templates with the correct parameters in a separate compilation unit of
// your program (see the files instantiate_cpp_grammar.cpp).
//
// To use the grammar inclusion model, uncomment the following
//
#define BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION 1
///////////////////////////////////////////////////////////////////////////////
// MSVC specific #pragma's
#if defined(BOOST_MSVC)
#pragma warning (disable: 4355) // 'this' used in base member initializer list
#pragma warning (disable: 4800) // forcing value to bool 'true' or 'false'
#pragma inline_depth(255)
#pragma inline_recursion(on)
#endif // defined(BOOST_MSVC)
///////////////////////////////////////////////////////////////////////////////
// Now include the cofiguration stuff for the Wave library itself
#include <boost/wave/wave_config.hpp>
#endif // !defined(CPP_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED)

22
tool/cpp_version.hpp Normal file
View File

@@ -0,0 +1,22 @@
/*=============================================================================
Wave: A Standard compliant C++ preprocessor library
Copyright (c) 2001-2004 Hartmut Kaiser
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED)
#define CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED
#include <boost/wave/wave_version.hpp>
#define CPP_VERSION_MAJOR BOOST_WAVE_VERSION_MAJOR
#define CPP_VERSION_MINOR BOOST_WAVE_VERSION_MINOR
#define CPP_VERSION_SUBMINOR BOOST_WAVE_VERSION_SUBMINOR
#define CPP_VERSION_DATE 20040126L
#endif // !defined(CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED)

View File

@@ -0,0 +1,471 @@
/*=============================================================================
Wave: A Standard compliant C++ preprocessor library
Copyright (c) 2001-2004 Hartmut Kaiser
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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(TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED)
#define TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED
#include <ostream>
#include <string>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/timer.hpp>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/util/macro_helpers.hpp>
#include <boost/wave/trace_policies.hpp>
#include <boost/wave/language_support.hpp>
#ifdef BOOST_NO_STRINGSTREAM
#include <strstream>
#define WAVE_OSSTREAM std::ostrstream
std::string WAVE_GETSTRING(std::ostrstream& ss)
{
ss << ends;
std::string rval = ss.str();
ss.freeze(false);
return rval;
}
#else
#include <sstream>
#define WAVE_GETSTRING(ss) ss.str()
#define WAVE_OSSTREAM std::ostringstream
#endif
///////////////////////////////////////////////////////////////////////////////
//
class stop_watch : public boost::timer {
typedef boost::timer base_t;
public:
stop_watch() : is_suspended_since(0), suspended_overall(0) {}
void suspend()
{
if (0 == is_suspended_since) {
// if not already suspended
is_suspended_since = this->base_t::elapsed();
}
}
void resume()
{
if (0 != is_suspended_since) {
// if really suspended
suspended_overall += this->base_t::elapsed() - is_suspended_since;
is_suspended_since = 0;
}
}
double elapsed() const
{
if (0 == is_suspended_since) {
// currently running
return this->base_t::elapsed() - suspended_overall;
}
// currently suspended
BOOST_ASSERT(is_suspended_since >= suspended_overall);
return is_suspended_since - suspended_overall;
}
std::string format_elapsed_time() const
{
double current = elapsed();
char time_buffer[sizeof("1234:56:78.90 abcd.")+1];
using namespace std;
if (current >= 3600) {
// show hours
sprintf (time_buffer, "%d:%02d:%02d.%03d hrs.",
(int)(current) / 3600, ((int)(current) % 3600) / 60,
((int)(current) % 3600) % 60,
(int)(current * 1000) % 1000);
}
else if (current >= 60) {
// show minutes
sprintf (time_buffer, "%d:%02d.%03d min.",
(int)(current) / 60, (int)(current) % 60,
(int)(current * 1000) % 1000);
}
else {
// show seconds
sprintf(time_buffer, "%d.%03d sec.", (int)current,
(int)(current * 1000) % 1000);
}
return time_buffer;
}
private:
double is_suspended_since;
double suspended_overall;
};
///////////////////////////////////////////////////////////////////////////////
//
// The trace_macro_expansion policy is used to trace the macro expansion of
// macros whenever it is requested from inside the input stream to preprocess
// through the '#pragma wave_option(trace: enable)' directive. The macro
// tracing is disabled with the help of a '#pragma wave_option(trace: disable)'
// directive.
//
// This policy type is used as a template parameter to the boost::wave::context<>
// object.
//
///////////////////////////////////////////////////////////////////////////////
class trace_macro_expansion
: public boost::wave::trace_policies::default_tracing
{
public:
trace_macro_expansion(std::ostream &outstrm_,
boost::wave::trace_policies::trace_flags flags_)
: outstrm(outstrm_), level(0),
flags(flags_), logging_flags(boost::wave::trace_policies::trace_nothing)
{
}
~trace_macro_expansion()
{
}
///////////////////////////////////////////////////////////////////////////
//
// The function enable_tracing is called, whenever the status of the
// tracing was changed.
//
// The parameter 'enable' is to be used as the new tracing status.
//
///////////////////////////////////////////////////////////////////////////
void enable_tracing(boost::wave::trace_policies::trace_flags flags)
{ logging_flags = flags; }
///////////////////////////////////////////////////////////////////////////
//
// The function tracing_enabled should return the current tracing status.
//
///////////////////////////////////////////////////////////////////////////
boost::wave::trace_policies::trace_flags tracing_enabled()
{ return logging_flags; }
///////////////////////////////////////////////////////////////////////////
//
// The function 'expanding_function_like_macro' is called, whenever a
// function-like macro is to be expanded.
//
// The 'macrodef' parameter marks the position, where the macro to expand
// is defined.
// The 'formal_args' parameter holds the formal arguments used during the
// definition of the macro.
// The 'definition' parameter holds the macro definition for the macro to
// trace.
//
// The 'macrocall' parameter marks the position, where this macro invoked.
// The 'arguments' parameter holds the macro arguments used during the
// invocation of the macro
//
///////////////////////////////////////////////////////////////////////////
template <typename TokenT, typename ContainerT>
void expanding_function_like_macro(
TokenT const &macrodef, std::vector<TokenT> const &formal_args,
ContainerT const &definition,
TokenT const &macrocall, std::vector<ContainerT> const &arguments)
{
if (!enabled_macro_tracing()) return;
if (0 == get_level()) {
// output header line
WAVE_OSSTREAM stream;
stream
<< macrocall.get_position() << ": "
<< macrocall.get_value() << "(";
// argument list
for (typename ContainerT::size_type i = 0; i < arguments.size(); ++i) {
stream << boost::wave::util::impl::as_string(arguments[i]);
if (i < arguments.size()-1)
stream << ", ";
}
stream << ")" << std::endl;
output(WAVE_GETSTRING(stream));
increment_level();
}
// output definition reference
{
WAVE_OSSTREAM stream;
stream
<< macrodef.get_position() << ": see macro definition: "
<< macrodef.get_value() << "(";
// formal argument list
for (typename std::vector<TokenT>::size_type i = 0;
i < formal_args.size(); ++i)
{
stream << formal_args[i].get_value();
if (i < formal_args.size()-1)
stream << ", ";
}
stream << ")" << std::endl;
output(WAVE_GETSTRING(stream));
}
if (formal_args.size() > 0) {
// map formal and real arguments
open_trace_body("invoked with\n");
for (typename std::vector<TokenT>::size_type j = 0;
j < formal_args.size(); ++j)
{
using namespace boost::wave;
WAVE_OSSTREAM stream;
stream << formal_args[j].get_value() << " = ";
#if WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
if (T_ELLIPSIS == token_id(formal_args[j])) {
// ellipsis
for (typename ContainerT::size_type k = j;
k < arguments.size(); ++k)
{
stream << boost::wave::util::impl::as_string(arguments[k]);
if (k < arguments.size()-1)
stream << ", ";
}
}
else
#endif
{
stream << boost::wave::util::impl::as_string(arguments[j]);
}
stream << std::endl;
output(WAVE_GETSTRING(stream));
}
close_trace_body();
}
open_trace_body();
}
///////////////////////////////////////////////////////////////////////////
//
// The function 'expanding_object_like_macro' is called, whenever a
// object-like macro is to be expanded .
//
// The 'macrodef' parameter marks the position, where the macro to expand
// is defined.
// The 'definition' parameter holds the macro definition for the macro to
// trace.
//
// The 'macrocall' parameter marks the position, where this macro invoked.
//
///////////////////////////////////////////////////////////////////////////
template <typename TokenT, typename ContainerT>
void expanding_object_like_macro(TokenT const &macrodef,
ContainerT const &definition, TokenT const &macrocall)
{
if (!enabled_macro_tracing()) return;
if (0 == get_level()) {
// output header line
WAVE_OSSTREAM stream;
stream
<< macrocall.get_position() << ": "
<< macrocall.get_value() << std::endl;
output(WAVE_GETSTRING(stream));
increment_level();
}
// output definition reference
{
WAVE_OSSTREAM stream;
stream
<< macrodef.get_position() << ": see macro definition: "
<< macrodef.get_value() << std::endl;
output(WAVE_GETSTRING(stream));
}
open_trace_body();
}
///////////////////////////////////////////////////////////////////////////
//
// The function 'expanded_macro' is called, whenever the expansion of a
// macro is finished but before the rescanning process starts.
//
// The parameter 'result' contains the token sequence generated as the
// result of the macro expansion.
//
///////////////////////////////////////////////////////////////////////////
template <typename ContainerT>
void expanded_macro(ContainerT const &result)
{
if (!enabled_macro_tracing()) return;
WAVE_OSSTREAM stream;
stream << boost::wave::util::impl::as_string(result) << std::endl;
output(WAVE_GETSTRING(stream));
open_trace_body("rescanning\n");
}
///////////////////////////////////////////////////////////////////////////
//
// The function 'rescanned_macro' is called, whenever the rescanning of a
// macro is finished.
//
// The parameter 'result' contains the token sequence generated as the
// result of the rescanning.
//
///////////////////////////////////////////////////////////////////////////
template <typename ContainerT>
void rescanned_macro(ContainerT const &result)
{
if (!enabled_macro_tracing() || get_level() == 0)
return;
WAVE_OSSTREAM stream;
stream << boost::wave::util::impl::as_string(result) << std::endl;
output(WAVE_GETSTRING(stream));
close_trace_body();
close_trace_body();
if (1 == get_level())
decrement_level();
}
///////////////////////////////////////////////////////////////////////////
//
// The function 'interpret_pragma' is called, whenever a #pragma wave
// directive is found, which isn't known to the core Wave library.
//
// The parameter 'pending' may be used to push tokens back into the input
// stream, which are to be used as the replacement text for the whole
// #pragma wave() directive.
//
// The parameter 'option' contains the name of the interpreted pragma.
//
// The parameter 'values' holds the values of the parameter provided to
// the pragma operator.
//
// The parameter 'act_token' contains the actual #pragma token, which may
// be used for error output.
//
// The parameter 'language' contains the current language mode, in which
// the Wave library operates.
//
// If the return value is 'false', the whole #pragma directive is
// interpreted as unknown and a corresponding error message is issued. A
// return value of 'true' signs a successful interpretation of the given
// #pragma.
//
///////////////////////////////////////////////////////////////////////////
template <typename TokenT, typename ContainerT>
bool
interpret_pragma(ContainerT &pending, TokenT const &option,
ContainerT const &values, TokenT const &act_token,
boost::wave::language_support language)
{
if (option.get_value() == "timer") {
// #pragma wave timer(value)
if (0 == values.size()) {
// no value means '1'
using namespace boost::wave;
timer(TokenT(T_INTLIT, "1", act_token.get_position()));
}
else {
timer(values.front());
}
return true;
}
return false;
}
protected:
void open_trace_body(char const *label = 0)
{
if (label)
output(label);
output("[\n");
increment_level();
}
void close_trace_body()
{
if (get_level() > 0) {
decrement_level();
output("]\n");
outstrm << std::flush; // flush the stream buffer
}
}
template <typename StringT>
void output(StringT const &outstr) const
{
indent(get_level());
outstrm << outstr; // output the given string
}
void indent(int level) const
{
for (int i = 0; i < level; ++i)
outstrm << " "; // indent
}
int increment_level() { return ++level; }
int decrement_level() { BOOST_ASSERT(level > 0); return --level; }
int get_level() const { return level; }
bool enabled_macro_tracing() const
{
using namespace boost::wave::trace_policies;
return (flags & trace_macros) && (logging_flags & trace_macros);
}
bool enabled_include_tracing() const
{
using namespace boost::wave::trace_policies;
return (flags & trace_includes) && (logging_flags & trace_includes);
}
template <typename TokenT>
void timer(TokenT const &value)
{
if (value.get_value() == "0" || value.get_value() == "restart") {
// restart the timer
elapsed_time.restart();
}
else if (value.get_value() == "1") {
// print out the current elapsed time
std::cerr
<< value.get_position() << ": "
<< elapsed_time.format_elapsed_time()
<< std::endl;
}
else if (value.get_value() == "suspend") {
// suspend the timer
elapsed_time.suspend();
}
else if (value.get_value() == "resume") {
// resume the timer
elapsed_time.resume();
}
}
private:
std::ostream &outstrm; // output stream
int level; // indentation level
boost::wave::trace_policies::trace_flags flags; // enabled globally
boost::wave::trace_policies::trace_flags logging_flags; // enabled by a #pragma
stop_watch elapsed_time; // trace timings
};
#undef WAVE_GETSTRING
#undef WAVE_OSSTREAM
#endif // !defined(TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED)