0

Say I have a file that translate TARGET defines into FEATURE defines:

// File options.h
#ifdef TARGET_A
#define FEATURE_X
#endif
#ifdef TARGET_B
#define FEATURE_Y
#endif
struct foo {
    int a;
    int b;
};

And I have a bunch of files ifdef'ed with FEATURE defines:

// File foo.c
#include "options.h"
#ifdef FEATURE_X
int x;
#endif
#ifdef FEATURE_Y
int y;
#endif

Then, how can I pre-process foo.c such that it will process the include statement, but keep it in the file?

Something like:

$ some-pre-process-tool -DTARGET_A -I. -o foo.pp.c foo.c
$ cat foo.pp.c
// File foo.c
#include "options.h"
int x;
$
3
  • You can probably get what you need (although possibly not quite as easily) using coan. Good luck. Commented Jul 14, 2016 at 21:37
  • I saw that when googling for a solution - but it looked like a too big effort for this purpose. Do you use/know it, and is it good for this kind of things?? I'm asking because the solution I ended up with is removing random white spaces which is annoying... Commented Jul 15, 2016 at 12:01
  • I've used coan and it has solved the problems I set out to solve. I don't know how easy it will be to solve your problem: I think you'd need two steps, in which you first identify the feature defines which result from a target selection (which you could do with GCC as long as you have a way of identifying the relevant feature macros by name), and then use coan to selectively handle only those macros. Commented Jul 15, 2016 at 17:17

3 Answers 3

2

First, why do you want to keep #include's in the preprocessed code? Are you planning to run it through the preprocessor again, or is it just helpful when reading the result?

You can get what you want with the gcc flag -Wp,-dI. -dI is documented here: https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html#index-dI-1113

Note that the output file will also have #include's from inside the files you included and all their child #include's.

Sign up to request clarification or add additional context in comments.

3 Comments

Okay my bad, I was not specific enough... I do not want to see the content of the included file in the output. I have updated the example to reflect this. FYI: I'm want this because I'm trying to understand some code that is compiled in many different variants, and I want to see the differences.
You don't want to see the content, but you still want the #define's in the include file to be used, correct?
Nope, I'm not interested in seeing the defines. I'm just interested in the pre-processor evaluating the defines.
0

There are properly better ways of doing this - but I ended up writing a small wrapper script that process the output from cpp

#!/usr/bin/env ruby
# File: pp.rb

f = open("| cpp -C -dI #{ARGV.join(" ")}")

# First line
f.gets =~ /"([^"]+)"/
file = $1
ll = []

# Skip "invisible" includes
while l = f.gets
    if l =~ /^#\s*1\s*"#{file}"$/
        ll = []
    else
        ll.push l
    end
end

inc = false
skip = false
skip_line = nil
ll.each do |l|
    if inc and l =~ /^#\s*(\d+)\s*"#{file}"$/
        inc = false
        skip = true
        skip_line = $1.to_i
    elsif skip and l =~ /^#\s*(\d+)\s*"#{file}"/
        inc = false
        if $1.to_i == skip_line + 1
            skip = false
        end
    elsif skip
        inc = false
    elsif l =~ /\s*#\s*include/
        puts l
        inc = true
    elsif l =~ /^#\s*(\d+)\s*"#{file}"/
    else
        inc = false
        puts l
    end
end

I can be called like this:

$ ./pp.rb -DTARGET_A -I.  foo.c > foo.pp.c
$ cat foo.pp.c
// File foo.c
#include "options.h"

int x;

Comments

-1

I'm afraid that preprocessed file can contain # only inside char or string literals and at the beginning of auxiliary line records.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.