【发布时间】:2010-10-06 05:35:51
【问题描述】:
原始问题
我想要的不是标准的 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 月以来一直可用。我会检查它...今年晚些时候,或者明年,或者某个时候,或者永远不会有进一步的报告。
【问题讨论】:
-
感谢您的建议 - 不,这不是我需要的。我知道如何查看编译器看到的内容(前几天我花了几个小时查看 37,000 行扩展输出,以找出出现问题的原因)。我希望 #include 和其他行保留,并且宏未展开。
标签: c++ c preprocessor