使用预处理器部分处理文件

clo*_*ord 5 c c++ c-preprocessor

我们继承了一个非常卷积的项目(500kloc)和许多预处理器条件逻辑,其中大部分不再相关,我想要清理它.

我是否可以使用预处理器¹仅扩展某些条件逻辑,并将所有其他预处理器宏,定义和包含在输出中?

¹在这里,通过"预处理器",我的意思是"任何工具",标准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
Run Code Online (Sandbox Code Playgroud)

我想要的工具(如果它不存在则可能需要编写)将是CPP的一个版本,它不仅接受特定调用的定义列表,而且还接受在扩展期间要遵守的定义列表.任何不在第二个列表中的预处理程序符号都是完全不管的.一个例子是按顺序:

cpptreadlight -DY=22 --only=Y
Run Code Online (Sandbox Code Playgroud)

会产生:

#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
Run Code Online (Sandbox Code Playgroud)

和:

cpptreadlight -DY=22 -DZ=8 -DX --only=Y,baz,Z
Run Code Online (Sandbox Code Playgroud)

会给我:

#include <foo>
#define bar(a) do{(a)+1} \
               while(0)
#ifdef X
      so_far_so_good = true;
    something();
#else
#endif
Run Code Online (Sandbox Code Playgroud)

请注意,即使X已定义,它也会被遗忘,因为它没有出现在--only列表中.另请注意,baz 位于--only列表中,因此在源中定义后会进行扩展.


我尝试了一个黑客解决方案:使用如下所示的管道逃避无趣的东西(使用我自己的gsub工具,但它可以达到您的预期):

function escape_tr() { 
   gsub "#(define|include)" '@@@\1' < $1 | 
     (echo '#include "simple.h"' && gsub '\\$' "%%%") | 
       cpp -C -P -DY=301 -DZ > $1.new 
}
Run Code Online (Sandbox Code Playgroud)

现在我可以过滤掉很多东西,然后把我希望预处理器扩展的东西放进去simple.h.评论是单独的,并且#line指令被省略.

几乎可以解决问题,其中包括未拉入,#define未定义块,因此未扩展到正文中.但是当然它不允许我指定我想要保留在输出中的条件逻辑集.那很糟.保持有条件的一些很重要.

#if巢,并#else#endif令牌不匹配词汇,把这个问题超出了一个正则表达式的管道.我需要一个完整的解析器,它实际上与cpp本身完全相同,但是对扩展的内容进行了更精细的控制.

因此,在深入研究预处理器实现这一点之前,我想我会问是否有人之前已经解决了这个问题.我不可能是唯一一个继承了一个充满死枝的预处理器意大利面窝的人.

Pau*_*lin 9

有一个名为" unifdef " 的工具可以做你想要的.