使用预处理器部分处理文件 [英] Partially processing a file with the preprocessor

查看:41
本文介绍了使用预处理器部分处理文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们继承了一个非常复杂的项目(500kloc),其中包含很多的预处理器条件逻辑,其中大多数不再相关,我想对其进行清理。

We have inherited a very convolved project (500kloc) with a lot of preprocessor conditional logic, most of which is no longer relevant, and I want to clean it up.

我可以使用预处理器¹来仅扩展条件逻辑的 some ,而保留所有其他预处理器宏,定义并单独包含在输出中吗?

Can I use the preprocessor¹ to expand only some of the conditional logic, and leave all other preprocessor macros, defines, and includes alone in the output?

¹这里,预处理器的意思是任何工具,可以是标准的C预处理器,可以安装的东西,甚至可以是黑客入侵的Perl或Python脚本。

¹ Here, by "the preprocessor", I really mean "any tool", either a standard C preprocessor, something I can install, or even a hacked-together Perl or Python script.

例如,假设我们有以下代码集:

For instance, suppose we have this set of code:

#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的一个版本,它不仅接受特定调用的定义列表,而且还接受在扩展期间要遵守的定义列表。不在第二个列表中的任何预处理器符号将完全保留。依次是一个示例:

The tool I want (and might need to write if it doesn't exist) would be a version of CPP that accepts not only the list of definitions for a particular invocation, but also a list of defines to respect during expansion. Any preprocessor symbol not in the second list is completely left alone. An example is in order:

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 列表中,因此被扩展了一次

Notice that even though X is defined, it was left behind, because it didn't appear in the --only list. Also note that baz was in the --only list, and so was expanded once it was defined in the source.

我尝试了一种破解解决方案:使用类似以下的管道逃避不感兴趣的内容(使用了我自己的gsub工具,但它确实达到了您的期望):

I tried a hack-solution: escaping uninteresting stuff using a pipeline like the following (my own gsub tool is used, but it does what you might expect):

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

现在我可以过滤掉很多东西,然后放我希望预处理器在 simple.h 中扩展的东西。留有注释,并省略 #line 指令。

Now I can filter out a lot of stuff, and then put the things I want the preprocessor to expand in simple.h. Comments are left alone, and #line directives are left out.

几乎这样做的窍门在于,其中包括没有被拉入,未定义 #define 块,因此不会扩展到主体中。但是,当然,它不允许我指定要保留在输出中的条件逻辑集。那很糟。保持有条件很重要。

This almost does the trick, in that includes are not pulled in, #define blocks are not defined, and so not expanded into the body. But of course it doesn't let me specify the set of conditional logic that I'd like to keep in the output. That's bad. Some of it is important to keep conditional.

#if 嵌套,并且 #else #endif 令牌在词法上不匹配,这使问题超出了正则表达式管道。我需要一个成熟的解析器,该解析器实际上与cpp本身相同,但是对扩展的内容具有更精细的控制。

#if nests, and the #else and #endif tokens don't lexically match, putting the problem beyond a regex pipeline. I need a full-blown parser, something practically identical to cpp itself, but with finer grained control of what is expanded.

因此,在深入研究实现这一目标的预处理程序之前,我想我想问问是否有人曾经解决过这个问题。我不是唯一继承了充满死枝的预处理器意大利面条巢的人。

Hence, before digging into a preprocessor to implement this, I thought I'd ask if anyone has solved this problem before. I can't be the only one to have inherited a preprocessor spaghetti nest full of dead branches.

推荐答案

有一个名为 的工具unifdef 将完成您想要的操作。

There is a tool called "unifdef" that will do what you want.

这篇关于使用预处理器部分处理文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆