我们继承了一个非常复杂的项目(500kloc),其中大部分已不再相关,并且我想清理它,其中lot预处理器条件逻辑。使用预处理器部分处理文件
我可以使用预处理器¹仅扩展条件逻辑的的一些,并将所有其他预处理器宏,定义和单独包括在输出中吗?在这里,“预处理器”,我的意思是“任何工具”,无论是标准的C预处理器,我可以安装的东西,甚至是一个黑客一起的Perl或Python脚本。
举例来说,假设我们有这套代码:
#include <foo>
#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 <foo>
#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 <foo>
#define bar(a) do{(a)+1} \
while(0)
#ifdef X
so_far_so_good = true;
something();
#else
#endif
注意,即使X
定义,它被抛在后面,因为它没有出现在--only
列表中。还请注意,在列表中,baz
的值为,因此在源中定义它之后进行扩展。
我尝试了黑客的解决方案:逃避使用如下管道无趣的东西(我自己GSUB工具被使用,但它确实你所期望的):
function escape_tr() {
gsub "#(define|include)" '@@@\1' < $1 |
(echo '#include "simple.h"' && gsub '\\$' "%%%") |
cpp -C -P -DY=301 -DZ > $1.new
}
现在我可以过滤掉很多东西,然后把我希望预处理器扩展的东西放在simple.h
中。留下评论,#line
指令被遗漏。
这个差不多没有诀窍,因为那里面没有拉入,#define
块没有定义,所以没有扩展到正文中。但是,它当然不会让我指定我想要保留在输出中的一组条件逻辑。那很糟。其中一些重要的是保持有条件。
#if
巢穴,和#else
和#endif
令牌不从词汇上匹配,使问题超出正则表达式管道。我需要一个全面的解析器,与cpp本身几乎完全相同,但是对扩展的内容进行了更精细的控制。
因此,在挖掘预处理器来实现它之前,我想我会问是否有人解决过这个问题。我不可能是唯一一个继承了一个充满死枝的预处理意大利面条巢。
很快。谢谢! – clord 2010-11-10 19:02:38
确认这与原始问题中的'escape_tr' shell脚本相结合可以执行我想在此源代码基础上完成的所有操作。谢谢保罗。 虽然像'cpptreadlight'应该存在。它概括了'unifdef'和'cpp'。 – clord 2010-11-10 19:47:06
我不知道为什么你需要'escape_tr',但可能我错过了一些东西。 – 2010-11-10 20:38:38