是否有一个C预处理器根据定义/未定义的值消除#ifdef块?

时间:2009-02-08 06:45:57

标签: c++ c preprocessor

原始问题

我想要的不是标准的C预处理器,而是可以从某处接受的变体 - 可能是命令行通过-DNAME1和-UNAME2选项 - 定义了哪些宏的规范,并且然后消除死代码。

通过一些例子可能更容易理解我所追求的内容:

#ifdef NAME1
#define ALBUQUERQUE "ambidextrous"
#else
#define PHANTASMAGORIA "ghostly"
#endif

如果命令是使用'-DNAME1'运行的,则输出为:

#define ALBUQUERQUE "ambidextrous"

如果命令以'-UNAME1'运行,则输出为:

#define PHANTASMAGORIA "ghostly"

如果命令没有选项运行,则输出与输入相同。

这是一个简单的例子 - 我希望代码也可以处理更复杂的案例。

用现实世界但仍然很简单的例子说明:

#ifdef USE_VOID
#ifdef PLATFORM1
#define VOID void
#else
#undef VOID
typedef void    VOID;
#endif /* PLATFORM1 */
typedef void *  VOIDPTR;
#else
typedef mint     VOID;
typedef char *  VOIDPTR;
#endif /* USE_VOID */

我想用-DUSE_VOID -UPLATFORM1运行命令并获取输出:

#undef VOID
typedef void    VOID;
typedef void *  VOIDPTR;

另一个例子:

#ifndef DOUBLEPAD
#if (defined NT) || (defined OLDUNIX)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */

理想情况下,我想与-UOLDUNIX一起运行并获得输出:

#ifndef DOUBLEPAD
#if (defined NT)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */

这可能会推动我的运气!

动机:具有大量条件代码的大型古老代码库。许多条件不再适用 - 例如,OLDUNIX平台不再生成且不再受支持,因此不需要在代码中引用它。其他条件总是如此。例如,使用条件编译添加功能,以便单个版本的代码可用于功能不可用的旧版本软件和可用的新版本(或多或少)。最终,不再支持没有该功能的旧版本 - 所有内容都使用该功能 - 因此应删除该功能是否存在的条件,并且应删除“何时缺少功能”代码。我想有一个工具来自动完成这项工作,因为它比手工操作更快更可靠(当代码库包含21,500个源文件时,这是非常关键的。)

(该工具的一个非常聪明的版本可能会读取#include'd文件,以确定控制宏 - 在命令行上由-D或-U指定的那些宏 - 是否在这些文件中定义。我是除了作为备份诊断之外,不确定这是否真的有用。但是,无论它做什么,伪预处理器都不能扩展宏或逐字包含文件。输出必须类似于输入代码,但通常比输入代码更简单。)

状态报告(一年后)

使用一年后,我对所选答案推荐的“sunifdef”非常满意。它还没有犯错,我不指望它。我唯一的狡辩是风格。给出如下输入:

#if (defined(A) && defined(B)) || defined(C) || (defined(D) && defined(E))

并以'-UC'运行(C从未定义),输出为:

#if defined(A) && defined(B) || defined(D) && defined(E)

这在技术上是正确的,因为'&&'绑定比'||更严格,但它是一个混乱的公开邀请。我更希望它包括围绕'&&'的集合括号条件,如原文:

#if (defined(A) && defined(B)) || (defined(D) && defined(E))

然而,考虑到我必须使用的一些代码的模糊性,因为这是最大的挑选是强烈的赞美;它对我来说是很有价值的工具。


街区新生儿

检查了包含在上述信息中的URL后,我看到(正如预测的那样)有一个名为Coan的新程序,它是'sunifdef'的继承者。它可以在SourceForge上获得,并且自2010年1月以来一直在使用。我将在今年晚些时候,或者明年,或者某个时候,或者从未进行过更多报告。

5 个答案:

答案 0 :(得分:23)

我对C一无所知,但听起来你正在寻找像unifdef这样的东西。请注意,它自2000年以来一直没有更新,但有一个名为"Son of unifdef" (sunifdef)的后继者。

答案 1 :(得分:4)

几年前我使用unifdef来解决你描述的那种问题,并且它运行良好。即使它自2000年以来还没有更新,预处理器ifdef的语法从那时起没有实质性的改变,所以我希望它仍然可以做你想要的。我想可能存在一些编译问题,尽管这些软件包最近出现了。

我从未使用过sunifdef,所以我不能直接评论它。

答案 2 :(得分:4)

您也可以尝试使用此工具http://coan2.sourceforge.net/

这样的东西会删除ifdef阻止:

coan source -UYOUR_FLAG --filter c,h - 保存YourSourceTree

答案 3 :(得分:3)

2004年左右,我写了一个完全符合您要求的工具。我从来没有开始分发这个工具,但代码可以在这里找到:

http://casey.dnsalias.org/exifdef-0.2.zip(这是一个dsl链接)

大约1.7k行并且使用bison和flex来实现足够的C语法来解析预处理器语句,注释和字符串。

答案 4 :(得分:2)

如果您需要与预处理器类似的东西,灵活的解决方案是Wave(来自boost)。它是一个用于构建类似C预处理器的工具的库(包括诸如C ++ 03和C ++ 0x预处理器之类的东西)。因为它是一个库,你可以挂钩它的输入和输出代码。