1

(Originated from this question.)

I unsuccesfully tried to make use of this example.

My attempt was to copy and slighly edit the code at the link. The result is this (I leave the comment from Boost website to make comparing my edits with the original easier):

#include <boost/wave.hpp>
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>

int main() {
    // The following preprocesses a given input file.
    // Open the file and read it into a string variable
    std::string input("int main() { std::cout << \"Hello world\"; }");
    // The template boost::wave::cpplexer::lex_token<> is the  
    // token type to be used by the Wave library.
    // This token type is one of the central types throughout 
    // the library, because it is a template parameter to some 
    // of the public classes and templates and it is returned 
    // from the iterators.
    // The template boost::wave::cpplexer::lex_iterator<> is
    // the lexer iterator to use as the token source for the
    // preprocessing engine. In this case this is parameterized
    // with the token type.
    typedef boost::wave::cpplexer::lex_iterator<
            boost::wave::cpplexer::lex_token<> >
        lex_iterator_type;
    typedef boost::wave::context<
            std::string::iterator, lex_iterator_type>
        context_type;

    context_type ctx(input.begin(), input.end(), "preproc.cpp");

    // At this point you may want to set the parameters of the
    // preprocessing as include paths and/or predefined macros.
    //ctx.add_include_path("...");
    //ctx.add_macro_definition("...");

    // Get the preprocessor iterators and use them to generate 
    // the token sequence.
    context_type::iterator_type first = ctx.begin();
    context_type::iterator_type last = ctx.end();

    // The input stream is preprocessed for you during iteration
    // over [first, last)
    while (first != last) {
        std::cout << (*first).get_value();
        ++first;
    }
}

I can successfully compile with

g++ -std=c++17 -lboost_thread -lboost_filesystem -lboost_wave source.cpp

But upon running the executable I get this error

terminate called after throwing an instance of 'boost::wrapexcept<boost::wave::preprocess_exception>'
  what():  boost::wave::preprocess_exception
Aborted (core dumped)

As suggested in the comment, upon changing std::cout << (*first).get_value(); to std::cout << (*first).get_value() << '\n'; made apparent that the exception is thrown at the EOF. By pure guess, I tried adding \n at the end of input and the program run just fine, with no exeception.

However, when I reverted the code to what is the linked example, so that the input is read from file rather than being hardcoded,

    //std::string input("int main() { std::cout << \"Hello world\"; }");
    std::ifstream instream("somefile.cpp");
    std::string input(
        std::istreambuf_iterator<char>(instream.rdbuf()),
        std::istreambuf_iterator<char>());

then I got the same error.


One problem seems to be related to the missing \n at the end of the string, so changing this

    std::string input("int main() { std::cout << \"Hello world\"; }");

to this

    std::string input("int main() { std::cout << \"Hello world\"; }\n");

seems to solve the problem. Except that the problem is more extensive than this. Indeed, if I add an header to the string:

    std::string input("#include<iostream>\nint main() { std::cout << \"Hello world\"; }\n");

then I get the same failure. Most surprisingly, if I comment that header:

    std::string input("//#include<iostream>\nint main() { std::cout << \"Hello world\"; }\n");

then the program runs, but the ouptut is:

#line 2 "/home/enrico/preproc.cpp"
int main() { std::cout << "Hello world"; }

and I have absolutely no idea how the #include<iostream> is turned into #line 2 "/home/enrico/preproc.cpp".

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • `std::cout << (*first).get_value << '\n';` will make it clearer when exactly that exception is thrown. And/or log to `std::cerr` instead of `std::cout`. – rici Oct 06 '20 at 20:31
  • @rici, your suggestion is certainly useful, however I've updated the question. – Enlico Oct 06 '20 at 20:45
  • Glad I could be of assistance. Hopefully someone who actually knows something about the boost wave preprocessor will be able to help you more. (It might help to mention what is in that file :-). And, of course, check that you were able to actually open the file. – rici Oct 06 '20 at 20:49
  • Have you tried catching the exception and printing the message or have you tried using a debugger? – Alan Birtles Oct 06 '20 at 20:50
  • @AlanBirtles, I haven't been able to pull anything out of the exception, nor I could find something with the debugger :( – Enlico Oct 07 '20 at 17:11
  • 1
    I also got the same preprocess exception and the solution was to add a line feed at the end of the input file. Quite a weird behaviour indeed. – Sıddık Açıl Jul 04 '21 at 15:12

1 Answers1

1

Technically C source file without trailing newline is invalid. You have to make sure there's a newline on the end:

std::string input("int main() { std::cout << \"Hello world\"; }\n");
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Thanks for looking into it. I could make some more experiment. For me, if I write `#include\n` just before `int main`, the program terminates the same way (`terminate called after throwing ...`). So the problem seems to be more involved. – Enlico Nov 18 '21 at 19:00
  • And there's an even stranger thing. I'll update the question in a moment. – Enlico Nov 18 '21 at 19:02