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

时间:2010-12-30 17:46:18

标签: c gcc c-preprocessor

我的代码有很多复杂的#define错误代码,因为它们嵌套在几个层次上,因此不容易解码。

有没有优雅的方法可以获得#defines列表及其最终数值(或其他任何可能的值)?

举个例子:

<header1.h>
#define CREATE_ERROR_CODE(class, sc, code) ((class << 16) & (sc << 8) & code)
#define EMI_MAX 16

<header2.h>
#define MI_1 EMI_MAX

<header3.h>
#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或任何其他编译器的建议会有所帮助。

6 个答案:

答案 0 :(得分:7)

海湾合作委员会-dM preprocessor option可能会得到你想要的东西。

答案 1 :(得分:4)

我认为解决方案是@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方便,所以没有测试过这个......

答案 2 :(得分:2)

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

  

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

     

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

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

答案 3 :(得分:1)

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

#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;
}

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

答案 4 :(得分:1)

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

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

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

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

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

答案 5 :(得分:0)

  

有没有优雅的方法可以获得#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 -x c ${CPPFLAGS} - | tail -n1;
done;

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