Is There a C Pre-Processor Which Eliminates #Ifdef Blocks Based on Values Defined/Undefined

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

I know absolutely nothing about C, but it sounds like you are looking for something like unifdef. Note that it hasn't been updated since 2000, but there is a successor called "Son of unifdef" (sunifdef).

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

I know absolutely nothing about C, but it sounds like you are looking for something like unifdef. Note that it hasn't been updated since 2000, but there is a successor called "Son of unifdef" (sunifdef).

How to get rid of ifdef's in a large c project

There are two tools I know of that you could use to do this semi-automatically.

One is sunifdef (son of unifdef). AFAIK, this is no longer being maintained, though (and neither is unifdef on which it is based).

The other is coan, which is being actively maintained, and is a development of sunifdef.

See also: Is there a C pre-processor which eliminates #ifdef blocks based on values defined/undefined?.

As it happens, I'm still using sunifdef on the main project at work where I'm eliminating archaic code (for example, machines not supported since about 1996) from the code base. The only gotcha I have with it is that if a line goes in with parentheses like this:

#if (defined(MACH_A) && defined(PROP_P)) || (defined(MACH_B) && defined(PROP_Q)) || \
(defined(MACH_C) && defined(PROP_R))

and we have -UMACH_C (so machine C is no longer supported), the output line is:

#if defined(MACH_A) && defined(PROP_P) || defined(MACH_B) && defined(PROP_Q)

Technically, that's fine; it is correct. It is just preferable to keep the extra, technically redundant parentheses in the expression.

One caveat: although I can answer for these compiling on Unix-based systems, I've not personally checked them out on Windows.

Is there a C preprocessor that eliminates #ifdefs but also evaluates preprocessor macros?

With sunifdef 3.1.3, you can't do it, as you demonstrated. Nor can you do it with earlier versions of coan such as 4.2.2.

However, with coan 5.2 (the current version), you can almost do what you are after.

$ cat legacy.c
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
do(some,legacy,stuff)
#else
do(current,stuff)
#endif
$ coan source -DLINUX_VERSION_CODE=0x020635 legacy.c
coan: /Users/jleffler/soq/legacy.c: line 1: warning 0x0041c: "-DKERNEL_VERSION(a,b,c)=(((a) << 16) + ((b) << 8) + (c))" has been assumed for the current file
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
do(current,stuff)
$ coan source -DLINUX_VERSION_CODE=0x020624 legacy.c
coan: /Users/jleffler/soq/legacy.c: line 1: warning 0x0041c: "-DKERNEL_VERSION(a,b,c)=(((a) << 16) + ((b) << 8) + (c))" has been assumed for the current file
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
do(some,legacy,stuff)
$

This is close to what you want, but not quite. It gives 'correct' output, but maybe not 'helpful' output. It gives you the code that would be compiled for the LINUX_VERSION_CODE specified on the command line, whereas you'd probably like the conditionals based on LINUX_VERSION_CODE and KERNEL_VERSION that are not false to survive into the output.

Pre-preprocessor

You can use something like awk instead of CPP ? Add some flags in your code surrounding the piece of code to be removed. For example:

(...)
//BEGIN_REMOVE_THIS_CODE

printf("secret code");

//END_REMOVE_THIS_CODE
(...)

then write a awk script to remove this code, something like...

BEGIN { write=1;}
/^\/\/BEGIN_REMOVE_THIS_CODE/ { write=0; next;}
/^\/\/END_REMOVE_THIS_CODE/ { write=1; next;}
{
if(write==1) print $0;
}

Partially processing a file with the preprocessor

There is a tool called "unifdef" that will do what you want.

Is there an #ifdef stripping C/C++ utility

unifdef might be what you're looking for.

From its manual:

The unifdef utility acts on #if, #ifdef, #ifndef, #elif, #else, and
#endif lines. A directive is only processed if the symbols specified on
the command line are sufficient to allow unifdef to get a definite value
for its control expression. If the result is false, the directive and
the following lines under its control are removed. If the result is
true, only the directive is removed. An #ifdef or #ifndef directive is
passed through unchanged if its controlling symbol is not specified on
the command line. Any #if or #elif control expression that has an
unknown value or that unifdef cannot parse is passed through unchanged.

Tool to remove/Apply ifdef's/else's from codebase

It looks like unifdef is what you want, it is also used in the Linux kernel. This is the description of the tool from the linked site (emphasis mine):

The unifdef utility selectively processes conditional C preprocessor #if and #ifdef directives. It removes from a file both the directives and the additional text that they delimit, while otherwise leaving the file alone.

It is useful for avoiding distractions when studying code that uses #ifdef heavily for portability: my original motivation was to understand xterm's pty handling code. It can be used as a lightweight preprocessor; for example the Linux kernel uses unifdef to strip out #ifdef KERNEL sections from the headers it exports to userland. You can use unifdef with languages other than C; for example UIT, a publisher in Cambridge where I live, uses unifdef with LaTeX.

If you check out the manual there are some exceptions listed in the BUGS section:

Handling one line at a time means preprocessor directives split across
more than one physical line (because of comments or backslash-newline) cannot be handled in every situation.

Trigraphs are not recognized.

There is no support for macros with different definitions at different
points in the source file.

The text-mode and ignore functionality does not correspond to modern
cpp(1) behaviour.

Other options include Sunifdef whose main site no longer is available and has not been updated since 2008 and Coan: The C Preprocessor Chainsaw which describes itself as:

Coan is a software engineering tool for analysing preprocessor-based configurations of C or C++ source code. Its principal use is to simplify a body of source code by eliminating any parts that are redundant with respect to a specified configuration. Dead code removal is an application of this sort.

Coan is most useful to developers of constantly evolving products with large code bases, where preprocessor definitions and #if-directives are used differentiate progressive releases or parallel variants of the product. In these settings the upkeep of the product's configuration tree can become difficult and the incidence of configuration-related defects can become costly.

What's the use of #ifdef and #endif processor directives in iPhone?

AFAIK, #ifdef = "if defined" and #ifndef = "if not defined". These conditionals are useful, for example if you want a certain code to be compiled only for the simulator, then you'd write something like:

    #if TARGET_IPHONE_SIMULATOR
#import "AccelerometerSimulation.h"
#endif

Which means, when you compile for the simulator, the AccelerometerSimulation.h will be imported. If you are compiling on a device, it is ignored totally. Hope that helps.



Related Topics



Leave a reply



Submit