2010-11-10 63 views
5

我们继承了一个非常复杂的项目(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本身几乎完全相同,但是对扩展的内容进行了更精细的控制。

因此,在挖掘预处理器来实现它之前,我想我会问是否有人解决过这个问题。我不可能是唯一一个继承了一个充满死枝的预处理意大利面条巢。

回答

8

有一种名为“unifdef”的工具,可以做你想做的。

+0

很快。谢谢! – clord 2010-11-10 19:02:38

+0

确认这与原始问题中的'escape_tr' shell脚本相结合可以执行我想在此源代码基础上完成的所有操作。谢谢保罗。 虽然像'cpptreadlight'应该存在。它概括了'unifdef'和'cpp'。 – clord 2010-11-10 19:47:06

+0

我不知道为什么你需要'escape_tr',但可能我错过了一些东西。 – 2010-11-10 20:38:38

0

你一定要采取从boost.wave前言看看​​

所以对于波项目的主要目标是:

  • 完全符合与C++标准(ISO/IEC 14882:1998)1和C99标准(INCITS/ISO/IEC 9899:1999)
  • Spirit的使用[4] f或游戏的解析部分(当然:-)
  • STL的最大使用和/或升压库(紧凑性和可维护性)
  • 为附加功能 构建为不同的C柔性库执行直接的扩++词法和预处理需求