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

Jon*_*ler 36 c c++ preprocessor

原始问题

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

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

#ifdef NAME1
#define ALBUQUERQUE "ambidextrous"
#else
#define PHANTASMAGORIA "ghostly"
#endif
Run Code Online (Sandbox Code Playgroud)

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

#define ALBUQUERQUE "ambidextrous"
Run Code Online (Sandbox Code Playgroud)

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

#define PHANTASMAGORIA "ghostly"
Run Code Online (Sandbox Code Playgroud)

如果命令是在没有选项的情况下运行的,则输出将与输入相同.

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

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

#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 */
Run Code Online (Sandbox Code Playgroud)

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

#undef VOID
typedef void    VOID;
typedef void *  VOIDPTR;
Run Code Online (Sandbox Code Playgroud)

另一个例子:

#ifndef DOUBLEPAD
#if (defined NT) || (defined OLDUNIX)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */
Run Code Online (Sandbox Code Playgroud)

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

#ifndef DOUBLEPAD
#if (defined NT)
#define DOUBLEPAD 8
#else
#define DOUBLEPAD 0
#endif /* NT */
#endif /* !DOUBLEPAD */
Run Code Online (Sandbox Code Playgroud)

这可能是我的运气!

动机:具有大量条件代码的大型古代代码库.许多条件不再适用 - 例如,OLDUNIX平台不再生成且不再受支持,因此不需要在代码中引用它.其他条件总是如此.例如,使用条件编译添加功能,以便单个版本的代码可用于功能不可用的旧版本软件和可用的新版本(或多或少).最终,不再支持没有该功能的旧版本 - 所有内容都使用该功能 - 因此应删除该功能是否存在的条件,并且应删除"何时缺少功能"代码.一世'

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

状态报告(一年后)

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

#if (defined(A) && defined(B)) || defined(C) || (defined(D) && defined(E))
Run Code Online (Sandbox Code Playgroud)

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

#if defined(A) && defined(B) || defined(D) && defined(E)
Run Code Online (Sandbox Code Playgroud)

这在技术上是正确的,因为'&&'比'||'更紧密,但它是一个混乱的公开邀请.我更倾向于在'&&'条件的集合中包括括号,如原始:

#if (defined(A) && defined(B)) || (defined(D) && defined(E))
Run Code Online (Sandbox Code Playgroud)

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


街区新人

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

Jör*_*tag 26

我对C一无所知,但听起来你正在寻找类似的东西unifdef.请注意,自2000年以来它没有更新,但有一个名为"unifdef之子"(sunifdef)的继任者.

  • 还要注意类似的问题[这里](http://stackoverflow.com/questions/22738929/tool-to-remove-apply-ifdefs-elses-from-codebase),现在正在积极维护"unifdef"并使用它在Linux内核中. (3认同)

Dal*_*und 5

几年前我使用 unifdef 来解决你描述的那种问题,而且效果很好。即使自 2000 年以来就没有更新过,预处理器 ifdefs 的语法从那时起就没有发生重大变化,所以我预计它仍然会做你想要的事情。我想可能存在一些编译问题,尽管这些包看起来是最近的。

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


小智 5

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

这样的事情将删除ifdef块:

普通源-UYOUR_FLAG --filter c,h --recurse YourSourceTree

  • 欢迎使用堆栈溢出。请尽快阅读[FAQ]。Coan在主要问题中被称为“街区上的新孩子”。 (3认同)