使用预处理器部分处理文件
我们inheritance了一个非常卷积的项目(500kloc)和许多预处理器条件逻辑,其中大部分不再相关,我想要清理它。
我是否可以使用预处理器¹仅扩展某些条件逻辑,并将所有其他预处理器宏,定义和包含在输出中?
¹在这里,通过“预处理器”,我的意思是“任何工具”,要么是标准的C预处理器,要么是我可以安装的,甚至是黑客攻击的Perl或Python脚本。
例如,假设我们有这组代码:
#include #define baz #define bar(a) do{(a)+1} \ while(0) #ifdef X #if Y > 20 #if Z > 5 so_far_so_good = true; #endif #ifdef baz something(); #endif #else otherthing(); #endif #else #if Z > 10 wow().this.is.bad; #endif #endif
我想要的工具(如果它不存在则可能需要编写)将是CPP的一个版本,它不仅接受特定调用的定义列表,而且还接受在扩展期间要遵守的定义列表。 任何不在第二个列表中的预处理程序符号都是完全不管的。 一个例子是按顺序:
cpptreadlight -DY=22 --only=Y
会产生:
#include #define baz #define bar(a) do{(a)+1} \ while(0) #ifdef X #if Z > 5 so_far_so_good = true; #endif #ifdef baz something(); #endif #else #if Z > 10 wow().this.is.bad; #endif #endif
和:
cpptreadlight -DY=22 -DZ=8 -DX --only=Y,baz,Z
会给我:
#include #define bar(a) do{(a)+1} \ while(0) #ifdef X so_far_so_good = true; something(); #else #endif
请注意,即使定义了X
,它也会被遗忘,因为它没有出现在--only
列表中。 另请注意, baz
位于--only
列表中,因此在源中定义后会进行扩展。
我尝试了一个黑客解决方案:使用如下所示的管道转义无趣的东西(使用我自己的gsub工具,但它可以达到您的预期):
function escape_tr() { gsub "#(define|include)" '@@@\1' $1.new }
现在我可以过滤掉很多东西,然后把我希望预处理器的东西放在simple.h
。 注释单独留下,并且省略#line
指令。
这几乎可以解决问题,因为包括没有被拉入,# #define
块没有定义,所以没有扩展到正文。 但是当然它不允许我指定我想要保留在输出中的条件逻辑集。 那很糟。 保持有条件的一些很重要。
#if
嵌套, #else
和#endif
标记在词法上不匹配,将问题置于正则表达式管道之外。 我需要一个完整的解析器,它实际上与cpp本身完全相同,但是对扩展的内容进行了更精细的控制。
因此,在深入研究预处理器实现这一点之前,我想我会问是否有人之前已经解决了这个问题。 我不可能是唯一一个inheritance了一个充满死枝的预处理器意大利面窝的人。
有一个名为“ unifdef ”的工具可以满足您的需求。
你一定要看看boost.wave
来自boost.wave前言:
所以Wave项目的主要目标是:
- 完全符合C ++标准(ISO / IEC 14882:1998) 1和C99标准(INCITS / ISO / IEC 9899:1999)
- 使用Spirit [4]来解析游戏的部分(当然:-)
- STL和/或Boost库的最大使用量(用于紧凑性和可维护性)
- 直观的可扩展性,用于实现其他function,为不同的C ++ lexing和预处理需求构建灵活的库