Reputation: 131525
I have two C language files: foo.c
and bar.h
(and possibly many other files). I want a list of all preprocessor macros which are used in foo.c
and defined in bar.h
.
Alternatively, if that's too difficult, even a list of all preprocessor macros (but not any identifier, word or piece of text) which appear in both foo.c
and bar.h
.
How can I obtain that?
Upvotes: 2
Views: 107
Reputation: 241701
You can piece this information together from the output of gcc's preprocessing options.
To get the list of macros actually used by a file, you can use the -E -dU
options, which preprocesses the file and also includes #define
commands at the first use of any macro. (It also produces #undef
commands for undefined names tested with #ifdef
or #if defined(...)
.) (You must use the -E
option -- only preprocess -- for -dU
to be handled properly.)
Since -dU
does not suppress the preprocessed output, you need to filter it by looking only at the #define
directives. For some applications, you might also want to further filter it by looking only at the uses actually in the file in question, since the report includes uses of macros by included files as well. But in this case, the intersection with the macros actually defined in the header file is probably sufficient.
So to get a list of used macros in file.c
:
gcc -E -dU file.c | grep -Eo '^#define [_A-Za-z][_A-Za-z0-9]*'
(The grep -Eo
removes the definition of the macro.)
You can approximate a list of macros actually defined in a header file using a slightly more generous grep
invocation, something like this:
grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' header.h
That will pick up macros defined in conditional sections even if the conditional fails, and it will pick up lines in comments which look like #define
directives. Usually, neither of those will cause many problems.
You could use gcc's -E -dM
or -E -dD
options to get a list of all defines in a header, but both of those will also insert the macros defined by headers included by the header. (-dM
also includes the predefined macros.) So you would really need to do some more work to focus on the macros actually defined by the header file, unless you are interested in all the macros defined as a result of including the header file.
Then you just need to find the intersection of the two lists. One way is to exract the macro names (awk '{print $2}'
), sort -u
both lists independently and then merge them, and finally pass them both through uniq -d
to only look at the entries in both lists. (Both the following define the shell function used_and_defined
which you would invoke used_and_defined foo.c bar.h
)
used() {
gcc -E -dU "$1" |
grep -Eo '^#define [_A-Za-z][_A-Za-z0-9]*' |
cut -f2 -d' ' |
sort -u
}
defined() {
grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' "$1" |
awk '{ print $2 }' |
sort -u
}
used_and_defined() {
cat <(used "$1") <(defined "$2") | sort | uniq -d
}
Or you could do the whole operation with awk
used_and_defined() {
awk '/^[[:space:]]*#[[:space:]]*define/ {
gsub(/[ (].*/, "", $2);
if (NR == FNR) ++macros[$2];
else if (macros[$2]) print $2;
}' \
<(grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' "$2") \
<(gcc -E -dU "$1")
}
Upvotes: 2
Reputation: 10148
A gcc
-specific (but clang
has the same option with the same semantics) is to use -dD
in addition to -E
:
gcc -E -dD -o foo.i [other options] foo.c
will keep #define
lines in the output, together with # nnn "/path/to/file.h"
directives, so that you should be able to tell which macro belongs to which file. If you want to extract the macros that come from bar.h
, Depending on the number of macros you expect to find in bar.h
, the search command of your favorite editor might be sufficient, or a small awk/perl/python/... script would help.
Upvotes: 0
Reputation: 72639
One strategy (admittedly cumbersome) could be:
foreach macro identifier SOME_MACRO in bar.h
, run
gcc -E -DSOME_MACRO=recognizable_value foo.c | grep recognizable_value
i.e. preprocess the source and detect if an expansion happened. Note that this does not work for macros only used in #if
directives and such.
Upvotes: 1