简体   繁体   English

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

[英]Is there a C pre-processor which eliminates #ifdef blocks based on values defined/undefined?

Original Question原始问题

What I'd like is not a standard C pre-processor, but a variation on it which would accept from somewhere - probably the command line via -DNAME1 and -UNAME2 options - a specification of which macros are defined, and would then eliminate dead code.我想要的不是标准的 C 预处理器,而是它的变体,它可以从某个地方接受 - 可能是通过 -DNAME1 和 -UNAME2 选项的命令行 - 定义了哪些宏的规范,然后会消除死代码。

It may be easier to understand what I'm after with some examples:通过一些示例可能更容易理解我所追求的:

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

If the command were run with '-DNAME1', the output would be:如果使用“-DNAME1”运行命令,则 output 将是:

#define ALBUQUERQUE "ambidextrous"

If the command were run with '-UNAME1', the output would be:如果使用“-UNAME1”运行命令,则 output 将是:

#define PHANTASMAGORIA "ghostly"

If the command were run with neither option, the output would be the same as the input.如果在没有任何选项的情况下运行该命令,则 output 将与输入相同。

This is a simple case - I'd be hoping that the code could handle more complex cases too.这是一个简单的案例 - 我希望代码也可以处理更复杂的案例。

To illustrate with a real-world but still simple example:用一个真实但仍然简单的例子来说明:

#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 */

I'd like to run the command with -DUSE_VOID -UPLATFORM1 and get the output:我想使用-DUSE_VOID -UPLATFORM1运行命令并获取 output:

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

Another example:另一个例子:

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

Ideally, I'd like to run with -UOLDUNIX and get the output:理想情况下,我想使用-UOLDUNIX运行并获得 output:

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

This may be pushing my luck这可能会推动我的运气

Motivation: large, ancient code base with lots of conditional code.动机:具有大量条件代码的大型古老代码库。 Many of the conditions no longer apply - the OLDUNIX platform, for example, is no longer made and no longer supported, so there is no need to have references to it in the code.许多条件不再适用 - 例如,OLDUNIX 平台不再制造且不再受支持,因此无需在代码中引用它。 Other conditions are always true.其他条件始终为真。 For example, features are added with conditional compilation so that a single version of the code can be used for both older versions of the software where the feature is not available and newer versions where it is available (more or less).例如,通过条件编译添加功能,以便单个版本的代码可用于该功能不可用的旧版本软件和可用(或多或少)的新版本。 Eventually, the old versions without the feature are no longer supported - everything uses the feature - so the condition on whether the feature is present or not should be removed, and the 'when feature is absent' code should be removed too.最终,不再支持没有该功能的旧版本 - 一切都使用该功能 - 因此应该删除该功能是否存在的条件,并且“当功能不存在时”代码也应该删除。 I'd like to have a tool to do the job automatically because it will be faster and more reliable than doing it manually (which is rather critical when the code base includes 21,500 source files).我想要一个工具来自动完成这项工作,因为它比手动完成更快、更可靠(当代码库包含 21,500 个源文件时,这一点相当重要)。

(A really clever version of the tool might read #include 'd files to determine whether the control macros - those specified by -D or -U on the command line - are defined in those files. I'm not sure whether that's truly helpful except as a backup diagnostic. Whatever else it does, though, the pseudo-pre-processor must not expand macros or include files verbatim. The output must be source similar to, but usually simpler than, the input code.) (该工具的一个非常聪明的版本可能会读取#include 'd 文件以确定控制宏(在命令行上由 -D 或 -U 指定的那些)是否在这些文件中定义。我不确定这是否真的有用除了作为备份诊断。无论如何,伪预处理器不得扩展宏或逐字包含文件。output 必须是类似于输入代码的源,但通常比输入代码更简单。)

Status Report (one year later)状态报告(一年后)

After a year of use, I am very happy with ' sunifdef ' recommended by the selected answer.经过一年的使用,我对所选答案推荐的“ sunifdef ”感到非常满意。 It hasn't made a mistake yet, and I don't expect it to.它还没有出错,我也不希望它出错。 The only quibble I have with it is stylistic.我对它的唯一质疑是风格。 Given an input such as:给定一个输入,例如:

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

and run with '-UC' (C is never defined), the output is:并使用“-UC”运行(从未定义 C),output 是:

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

This is technically correct because '&&' binds tighter than '||', but it is an open invitation to confusion.这在技术上是正确的,因为 '&&' 比 '||' 绑定得更紧密,但这是一个公开的混淆邀请。 I would much prefer it to include parentheses around the sets of '&&' conditions, as in the original:我更希望它在 '&&' 条件集周围包含括号,如原文所示:

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

However, given the obscurity of some of the code I have to work with, for that to be the biggest nit-pick is a strong compliment;然而,鉴于我必须使用的一些代码的晦涩难懂,因为这是最大的挑剔是一种强烈的赞美; it is valuable tool to me.它对我来说是很有价值的工具。


The New Kid on the Block街区新来的

Having checked the URL for inclusion in the information above, I see that (as predicted) there is an new program called Coan that is the successor to 'sunifdef'.在检查了 URL 是否包含在上述信息中之后,我看到(如预期的那样)有一个名为Coan的新程序是 'sunifdef' 的继承者。 It is available on SourceForge and has been since January 2010. I'll be checking it out...further reports later this year, or maybe next year, or sometime, or never.它在 SourceForge 上可用,自 2010 年 1 月以来一直可用。我会检查它...今年晚些时候,或者明年,或者某个时候,或者永远不会有进一步的报告。

I know absolutely nothing about C, but it sounds like you are looking for something like unifdef .我对 C 一无所知,但听起来您正在寻找类似unifdef东西。 Note that it hasn't been updated since 2000, but there is a successor called "Son of unifdef" (sunifdef) .请注意,它自 2000 年以来一直没有更新,但有一个名为“unifdef 之子” (sunifdef)的继任者。

Also you can try this tool http://coan2.sourceforge.net/你也可以试试这个工具http://coan2.sourceforge.net/

something like this will remove ifdef blocks:这样的事情将删除 ifdef 块:

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

I used unifdef years ago for just the sort of problem you describe, and it worked fine.几年前我使用 unifdef 来解决您描述的那种问题,并且效果很好。 Even if it hasn't been updated since 2000, the syntax of preprocessor ifdefs hasn't changed materially since then, so I expect it will still do what you want.即使它自 2000 年以来没有更新,预处理器 ifdefs 的语法也没有从那时起发生实质性变化,所以我希望它仍然可以做你想要的。 I suppose there might be some compile problems, although the packages appear recent.我想可能存在一些编译问题,尽管这些包是最近出现的。

I've never used sunifdef, so I can't comment on it directly.我从来没有用过 sunifdef,所以我不能直接评论它。

Around 2004 I wrote a tool that did exactly what you are looking for. 2004 年左右,我编写了一个工具,它完全符合您的要求。 I never got around to distributing the tool, but the code can be found here:我从未开始分发该工具,但可以在此处找到代码:

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

It's about 1.7k lines and implements enough of the C grammar to parse preprocessor statements, comments, and strings using bison and flex.它大约有 1.7k 行,并实现了足够的 C 语法来使用 bison 和 flex 解析预处理器语句、注释和字符串。

If you need something similar to a preprocessor, the flexible solution is Wave (from boost).如果您需要类似于预处理器的东西,灵活的解决方案是Wave (来自 boost)。 It's a library designed to build C-preprocessor-like tools (including such things as C++03 and C++0x preprocessors).它是一个旨在构建类似 C 预处理器的工具(包括 C++03 和 C++0x 预处理器之类的东西)的库。 As it's a library, you can hook into its input and output code.由于它是一个库,因此您可以挂钩其输入和输出代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM