原始问题
我想要的不是标准的 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 月以来一直可用。我会检查它...今年晚些时候,或者明年,或者某个时候,或者永远不会有进一步的报告。