【发布时间】:2017-03-16 20:52:08
【问题描述】:
我需要构建一个自动化系统来解析包含大量 #define 语句的 C++ .h 文件,并使用每个 #define 的值做一些事情。除了#define 语句之外,.h 文件中还有很多其他垃圾。
目标是创建一个键值列表,其中键是#define 语句定义的所有关键字,值是对应于定义的宏的评估。 #defines 使用一系列嵌套宏定义关键字,这些宏最终解析为编译时整数常量。有些不能解析为编译时整数常量,必须跳过这些。
.h 文件会随着时间的推移而演变,因此该工具不能是一个长硬编码的程序,它会将一个变量实例化为等于每个关键字。我无法控制 .h 文件的内容。唯一的保证是它可以使用标准的 C++ 编译器构建,并且将添加更多 #defines 但永远不会删除。宏公式随时可能发生变化。
我看到的选项是:
- 实现部分(或挂钩到现有的)C++ 编译器,并在预处理器步骤中截取宏的值。
- 使用正则表达式动态构建一个源文件,该文件将使用当前定义的所有宏,然后编译并执行源文件以获得所有宏的评估形式。不知何故(?)跳过不评估为编译时整数常量的宏。 (另外,不确定正则表达式是否足够表达以捕获所有可能的多行宏定义)
这两种方法都会给这个项目的构建过程增加相当大的复杂性和脆弱性,这是我想避免的。有没有更好的方法来评估 C++ .h 文件中的所有 #define 宏?
以下是我要解析的示例:
#ifndef Constants_h
#define Constants_h
namespace Foo
{
#define MAKE_CONSTANT(A, B) (A | (B << 4))
#define MAGIC_NUMBER_BASE 40
#define MAGIC_NUMBER MAGIC_NUMBER_BASE + 0x2
#define MORE_MAGIC_1 345
#define MORE_MAGIC_2 65
// Other stuff...
#define CONSTANT_1 MAKE_CONSTANT (MAGIC_NUMBER + 564, MORE_MAGIC_1 | MORE_MAGIC_2)
#define CONSTANT_2 MAKE_CONSTANT (MAGIC_NUMBER - 84, MORE_MAGIC_1 & MORE_MAGIC_2 ^ 0xA)
// etc...
#define SKIP_CONSTANT "What?"
// More CONSTANT_N mixed with more other stuff and constants which do
// not resolve to compile-time integers and must be skipped
}
#endif Constants_h
我需要摆脱的是所有解析为编译时整数常量的定义的名称和评估。在这种情况下,对于显示的定义,它将是
MAGIC_NUMBER_BASE 40
MAGIC_NUMBER 42
MORE_MAGIC_1 345
MORE_MAGIC_2 65
CONSTANT_1 1887
CONSTANT_2 -42
这个输出的格式并不重要,只要我可以将它作为一个键值对列表进一步处理。
【问题讨论】:
-
只需使用现有的 C 预处理器来帮助您。带有
-dU选项的常规 GNUcpp应该会让您非常接近您所追求的结果。 -
为什么
CONSTANT_1和CONSTANT_2在输出中但MAGIC_NUMBER_BASE、MAGIC_NUMBER、MORE_MAGIC_1、MORE_MAGIC_2不是?看起来它们至少和其他两个一样符合您的标准(定义解析为编译时整数常量)。 -
@BenVoigt 它们应该在输出中,我现在就修复它。
-
@MatteoItalia 当我在 cpp 上使用 -dU 标志时,我没有得到任何预期的输出值。我还需要其他标志吗?
-
@Techrocket9:问题是预处理器的规则根本不符合您的要求。当外部宏被使用时,宏使用的宏会被扩展,而不是在它被定义的地方。所以
CONSTANT_1在被使用之前不是编译时整数表达式……而且可能有些用途是,有些不是。
标签: c++ macros c-preprocessor constants compile-time-constant