39

原始问题

我想要的不是标准的 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 平台不再制造且不再受支持,因此无需在代码中引用它。其他条件始终为真。例如,通过条件编译添加功能,以便单个版本的代码可用于该功能不可用的旧版本软件和可用(或多或少)的新版本。最终,不再支持没有该功能的旧版本 - 一切都使用该功能 - 因此应该删除该功能是否存在的条件,并且“当功能不存在时”代码也应该删除。一世'

(该工具的一个非常聪明的版本可能会读取#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 月以来一直可用。我会检查它...今年晚些时候,或者明年,或者某个时候,或者永远不会有进一步的报告。

4

5 回答 5

26

我对 C 完全一无所知,但听起来你正在寻找类似unifdef. 请注意,它自 2000 年以来一直没有更新,但有一个后继者称为"Son of unifdef" (sunifdef)

于 2009-02-08T07:09:13.017 回答
6

你也可以试试这个工具http://coan2.sourceforge.net/

这样的事情将删除 ifdef 块:

coan source -UYOUR_FLAG --filter c,h --recurse YourSourceTree

于 2013-06-20T15:58:53.303 回答
4

几年前我使用 unifdef 来解决您描述的那种问题,并且效果很好。即使它自 2000 年以来没有更新,预处理器 ifdefs 的语法从那时起也没有发生实质性的变化,所以我希望它仍然会做你想做的事。我想可能会有一些编译问题,尽管这些包是最近出现的。

我从来没有用过 sunifdef,所以我不能直接评论它。

于 2009-02-08T07:37:46.033 回答
3

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

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

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

于 2009-02-08T07:36:21.557 回答
2

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

于 2009-02-10T14:39:57.370 回答