How can I generate a list of #define values from C code?

爷,独闯天下 提交于 2019-12-04 07:57:53

I think the solution is a combo of @nmichaels and @aschepler's answers.

Use gcc's -dM option to get a list of the macros. Use perl or awk or whatever to create 2 files from this list:

1) Macros.h, containing just the #defines.

2) Codes.c, which contains

#include "Macros.h"

ERROR_FOO = "ERROR_FOO"
ERROR_BAR = "ERROR_BAR"

(i.e: extract each #define ERROR_x into a line with the macro and a string.

now run gcc -E Codes.c. That should create a file with all the macros expanded. The output should look something like

1 = "ERROR_FOO"
2 = "ERROR_BAR"

I don't have gcc handy, so haven't tested this...

GCC's -dM preprocessor option might get you what you want.

The program 'coan' looks like the tool you are after. It has the 'defs' sub-command, which is described as:

defs [OPTION...] [file...] [directory...]

Select #define and #undef directives from the input files in accordance with the options and report them on the standard output in accordance with the options.

See the cited URL for more information about the options. Obtain the code here.

If you have a complete list of the macros you want to see, and all are numeric, you can compile and run a short program just for this purpose:

#include <header3.h>
#include <stdio.h>

#define SHOW(x) printf(#x " = %lld\n", (long long int) x)

int main(void) {
    SHOW(ERROR_FOO);
    /*...*/
    return 0;
}

As @nmichaels mentioned, gcc's -d flags may help get that list of macros to show.

Here's a little creative solution:

Write a program to match all of your identifiers with a regular expression (like \#define :b+(?<NAME>[0-9_A-Za-z]+):b+(?<VALUE>[^(].+)$ in .NET), then have it create another C file with just the names matched:

void main() {
    /*my_define_1*/ my_define_1;
    /*my_define_2*/ my_define_2;
    //...
}

Then pre-process your file using the /C /P option (for VC++), and you should get all of those replaced with the values. Then use another regex to swap things around, and put the comments before the values in #define format -- now you have the list of #define's!

(You can do something similar with GCC.)

Is there any elegant way I can get a list of #defines with their final numerical values

For various levels of elegance, sort of.

#!/bin/bash

file="mount.c";
for macro in $(grep -Po '(?<=#define)\s+(\S+)' "$file"); do
    echo -en "$macro: ";
    echo -en '#include "'"$file"'"\n'"$macro\n" | \
    cpp -E -P -x c ${CPPFLAGS} - | tail -n1;
done;

Not foolproof (#define \ \n macro(x) ... would not be caught - but no style I've seen does that).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!