如何从C代码生成#define值列表?

我的代码有很多复杂的#define错误代码,这些代码不容易解码,因为它们嵌套在几个级别。

有没有优雅的方法我可以获得#defines列表及其最终数值(或者他们可能是什么)?

举个例子:

 #define CREATE_ERROR_CODE(class, sc, code) ((class << 16) & (sc << 8) & code) #define EMI_MAX 16  #define MI_1 EMI_MAX  #define MODULE_ERROR_CLASS MI_1 #define MODULE_ERROR_SUBCLASS 1 #define ERROR_FOO CREATE_ERROR_CODE(MODULE_ERROR_CLASS, MODULE_ERROR_SUBCLASS, 1) 

我会有大量类似的#defines匹配ERROR _ [\ _ W _] +,我想枚举,以便我总是有一个程序可以输出的错误代码的当前列表。 我需要数值,因为这是所有程序将打印出来的(不,它不是打印出字符串的选项)。

对gcc或任何其他编译器的建议会有所帮助。

我认为解决方案是@nmichaels和@aschepler的答案的组合。

使用gcc的-dM选项获取宏列表。 使用perl或awk或其他任何方法从此列表中创建2个文件:

1)Macros.h,只包含#defines。

2)Codes.c,其中包含

 #include "Macros.h" ERROR_FOO = "ERROR_FOO" ERROR_BAR = "ERROR_BAR" 

(即:将每个#define ERROR_x提取到一个包含宏和字符串的行中。

现在运行gcc -E Codes.c 。 这应该创建一个扩展了所有宏的文件。 输出应该看起来像

 1 = "ERROR_FOO" 2 = "ERROR_BAR" 

我没有gcc方便,所以没有测试过这个……

GCC的-dM 预处理器选项可以为您提供所需的function。

程序’coan’看起来像你正在使用的工具。 它有’defs’子命令,描述如下:

defs [OPTION …] [file …] [目录…]

根据选项从输入文件中选择#define#undef指令,并根据选项在标准输出上报告它们。

有关这些选项的更多信息,请参阅引用的URL。 在这里获取代码。

如果您有一个想要查看的宏的完整列表,并且都是数字的,那么您可以为此目的编译并运行一个简短的程序:

 #include  #include  #define SHOW(x) printf(#x " = %lld\n", (long long int) x) int main(void) { SHOW(ERROR_FOO); /*...*/ return 0; } 

正如@nmichaels所提到的,gcc的-d标志可能有助于获得要显示的宏列表。

这是一个有点创意的解决方案:

编写一个程序,将所有标识符与正则表达式匹配(如\#define :b+(?[0-9_A-Za-z]+):b+(?[^(].+)$ in .NET),然后让它创建另一个只有匹配名称的C文件:

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

然后使用/ C / P选项(对于VC ++)预处理文件,并且应该将所有这些替换为值。 然后使用另一个正则表达式来交换周围的东西,并将注释放在#define格式的值之前 – 现在你有了#define的列表!

(你可以用GCC做类似的事情。)

有没有任何优雅的方式我可以获得#defines列表及其最终数值

对于各种级别的优雅,有点。

 #!/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 -xc ${CPPFLAGS} - | tail -n1; done; 

不是万无一失( #define \ \n macro(x) ...不会被抓住 - 但我见过的风格没有这样做 )。