Closed realazthat closed 2 years ago
Encouragingly the standalone wave
preprocessor seems to do the right thing here:
$ wave --c99 -p 3 /tmp/sample
#line 2 "/tmp/sample"
// This should be line 2
// A comment, followed by if with whitespace (line 5)
#line 13 "/tmp/sample"
// This should be line 13
// A comment, followed by ifdef with whitespace (line 15)
#line 24 "/tmp/sample"
// This should be line 24
$
OK, I think I've got it.
For emitting #line
directives it's crucial to know how many (if any) newlines were skipped during whitespace processing. The default preprocessing hooks make no attempt to count them in the may_skip_whitespace
method, which has a skipped_newline
out parameter for this purpose.
The eat_whitespace
context policy will do this for you, but without changes it will consume all the whitespace as well. So the solution (also used in the Wave preprocessing tool code) to get what you want is to implement your own may_skip_whitespace
that uses eat_whitespace
to record the presence of newlines, but always returns false
("do not consume"). A modified ContextPolicy that will do this for you is:
template <typename Token>
struct ContextPolicy
: boost::wave::context_policies::eat_whitespace<Token> {
typedef boost::wave::context_policies::eat_whitespace<Token> base_type;
template <typename ContextT, typename TokenT>
bool may_skip_whitespace(ContextT const& ctx, TokenT& token,
bool& skipped_newline) {
this->base_type::may_skip_whitespace(ctx, token, skipped_newline);
return false;
}
};
Using this I was able to duplicate your desired output.
@hkaiser should the default preprocessing hooks set skipped_newline
maybe?
@hkaiser should the default preprocessing hooks set
skipped_newline
maybe?
Two questions need to be answered for this:
In the end the answer should be yes if the answer to 1. is 'likely' and to 2. 'unlikely'.
Upon further reflection this is a bad idea, nevermind.
It is a little funny that the correct production of line directives depends on the choice of preprocessor hooks. My intuition would have been that the default would do it. Hm.
It is a little funny that the correct production of line directives depends on the choice of preprocessor hooks. My intuition would have been that the default would do it. Hm.
Indeed. I think we should make the change. If it breaks somebody's code, we'll deal with it later...
Well, I thought about it a little bit and given that the default returns false
(do not consume token), not touching skipped_newline
(or setting it to false
, maybe) actually seems like the right behavior... So maybe what's broken is the Wave core?
Yep, it looks like the paths for handling if
and ifdef
are different... and the if
path contains the code that handles emitting #line
, in particular here
I think we should move handling for ifdef
and ifndef
out of the "simple pp directives" section for consistency, if you don't object.
I think we should move handling for
ifdef
andifndef
out of the "simple pp directives" section for consistency, if you don't object.
Sure, fine with me. Thanks!
@realazthat develop branch contains another line directive-related bug fix that may be of interest to you (to be released in 1.80)
#if 0 ... #endif
it properly writes out a#line
directive that accounts for the whitespace.#ifdef NOT_DEFINED ... #endif
, no#line
directive is emitted, leading to incorrect line numbering by subsequent compiler's accounting (compiler's reconstruct line numbers via properly emitted#line
directives).Example code that is preprocessed:
Above preprocessed (with line numbering for your convenience).
Full code to reproduce (you can pretty much ignore everything outside of
main()
, is just for the nice debug output):