【问题标题】:Partially processing a file with the preprocessor [duplicate]使用预处理器部分处理文件[重复]
【发布时间】:2010-11-10 18:56:01
【问题描述】:

我们继承了一个非常复杂的项目 (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

我想要的工具(如果它不存在可能需要编写)将是一个 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 --only 列表中,因此在源中定义后被扩展。


我尝试了一个 hack 解决方案:使用如下管道转义无趣的东西(使用了我自己的 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 本身相同,但对扩展的内容有更细粒度的控制。

因此,在深入研究预处理器来实现这一点之前,我想我想问问是否有人以前解决过这个问题。我不能是唯一一个继承了一个装满枯枝的预处理器意大利面条巢的人。

【问题讨论】:

    标签: c++ c c-preprocessor


    【解决方案1】:

    有一个名为“unifdef”的工具可以满足您的需求。

    【讨论】:

    • 确认这与我在原始问题中的escape_tr shell 脚本相结合可以执行我想在此源库上执行的所有操作。谢谢保罗。不过应该存在像cpptreadlight 这样的东西。它概括了unifdefcpp
    • 我不确定你为什么需要escape_tr,但可能我遗漏了一些东西。
    • unifdef 只处理 ifdefs。我还想省略一些多余的定义。当然,这不是我在原始问题中提出的问题的一部分。
    • 我认为这不是真的 - 如果你执行 "unifdef -DY=22" 它也会处理所有 "#if Y..."。
    【解决方案2】:

    你一定要看看boost.wave

    来自 boost.wave 序言:

    Wave 项目的主要目标是:

    • 完全符合 C++ 标准 (ISO/IEC 14882:1998) 1 和 C99 标准 (INCITS/ISO/IEC 9899:1999)
    • 将 Spirit[4] 用于游戏的解析部分(当然 :-)
    • 最大限度地使用 STL 和/或 Boost 库(以实现紧凑性和可维护性)
    • 实现附加功能的直接可扩展性 为不同的 C++ 词法分析和预处理需求构建灵活的库

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      • 2011-09-22
      • 1970-01-01
      • 1970-01-01
      • 2019-06-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多