I am working on many C-sourcecode files which contain many preprocessor #if, #elseif and #else statements.
This statements often check for a #define, e.g.
#if(Switch_TestMode == Switch_TestModeON)
/* code 1 */
#else
/*code 2 */
#endif
Often this preprocessor statements are located within c-if statements which makes the sourcecode nearly unreadable for human beeings.
The #defines used for this preprocessor #if statements are defined within an extra file.
My idea now is to have a tool which checks this #defined switch settings and then only copies the lines of sourcecode which apply using the current #defines/switch settings.
For the above example I would like to get a new .c file which contains only
/*code 2 */
assumed the #define of Switch_TestMode is not equal to Switch_TestModeON.
Are there tools (freeware || low-cost) available which do this job?
Or do I have to write my own preprocessor parser for this?
(It is impossible for me to run the compiler using a special parameter which does this job, because our company is creating the C-sourcecode, another company is compiling.)
Thanks for any hint!
Regards
Thomas
unifdef is available from http://dotat.at/prog/unifdef/.
Try Sunifdef
Edit: Which has now become Coan
You can run the GNU compiler using command line option -E to do the preprocessing.
http://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
You can use unifdef.
Related
My problem is first of all, understanding #ifndef and #ifdef. I also want to understand the difference between #if, #ifndef , and #ifdef. I understand that #if is basically an if statement. For example:
#include<iostream>
#define LINUX_GRAPHICS 011x101
int main(){
long Compare = LINUX_GRAPHICS;
#if Compare == LINUX_GRAPHICS
std::cout << "True" << std::endl;
#endif
}
But the others, although I read about them I can't comprehend. They also seem like very similar terms, but I doubt they work similarly. Help would be greatly appreciated.
Macros are expanded by the preprocessor who doesn't know anything about values of variables during runtime. It is only about textual replacement (or comparing symbols known to the preprocessor). Your line
#if Compare == LINUX_GRAPHICS
will expand to
#if Compare == 011x101
and as "Compare" is different from "011x101", it evaluates to false. Actually I am not even 100% sure about that, but the point is: you are mixing preprocessor directives with variables that are evaluated at runtime. That is non-sense. Preprocessor directives are not there to replace C++ statements.
For most traditional use cases of macros there are better way nowadays. If you don't really need to use macros, it is better not to use them. It makes it extremely hard to read the code (eg. I don't understand how that macros in your code work and unless I really need it honestly I don't want to know :P) and there are other problems with macros that can lead to very hard to find bugs in your program. Before using macros I would advice you to first consider if there isn't a more natural C++ way of achieving the same.
PS:
#ifdef SYMBOL
ifdef = "if defined"
this part of the code is excluded before the compiler even sees it
if SYMBOL is not defined (via #define)
#endif
#ifndef SYMBOL
ifndef = "if not defined"
this part of the code is excluded before the compiler even sees it
if SYMBOL is defined (via #define)
#endif
I wrote "excluded" on purpose to emphasize the bad impact it has on readability of your code. If you overuse #ifdef or #ifndef inside normal blocks of code, it will be extremely hard to read.
#if doesn't have any notion about Compare or the value it contains, so it probably doesn't do what you intend.
Remember the preprocessor does plain text replacement.
The statement will expand as seen from #if as
#if Compare == 011x101
and being expanded as
#if 0 == 011x101
which certainly won't yield true at the preprocessing stage.
The #ifdef and #ifndef directives check if a preprocessor symbol was #define'd at all, either using that (<--) preprocessor directive, or your compilers preprocessor option (most commonly -D<preprocessor-symbol>).
These don't care if the preprocessor symbol carries an empty value or something. A simple
#define MY_CONDITION
or
-DMY_CONDITION
is enough to satisfy
#ifdef MY_CONDITION
to expand the text coming afterwards (or hide it with #ifndef).
The Compare declaration isn't a preprocessor symbol and can't be used reasonably with #ifdef or #ifndef either.
#if is preprocessor if. It can only deal with with preprocessor stuff which is basically preprocessor macros (which are either function like or constant-like) and C tokens with some simple integer-literal arithmetic.
#ifdef SOMETHING is the same as #if defined(SOMETHING) and
#ifndef SOMETHING is the same as #if !defined(SOMETHING). defined is a special preprocessor operator that allows you to test whether SOMETHING is a defined macro. These are basically shortcuts for the most common uses or preprocessor conditionals -- testing whether some macros are defined or not.
You can find a detailed manual (~80 pages) on the gcc preprocessor at
https://gcc.gnu.org/onlinedocs/ .
Well the preprocessors #ifdef and #ifndef mean the followind: In your example you used #define to set a constant variable named LINUX_GRAPHICS to be equal to 011x101. So later in your program you migth want to check if this variable is defined. Then you use #ifdef, when you want to check if this variable is defined and #ifndef if not. I wish I helped you.
Basicaly, preprocessor does text substitution. Then the compiler compiles program into machine code. And then CPU executes machine instructions. This means you can't use preprocessor #if instead of operator if: one does text substitution, while second generates branching code for CPU.
So preprocessor directives such as #if, #ifdef, #ifndef serve for "semi-automatic mode" of generating (a little) different programs based on some "meta-input". Actually you can always do these substitutions yourself and get working C/C++ program without any preprocessor directives. Also compilers often have a command-line switch which outputs just preprocessed program, i.e. without any #if directives. Try to play with it, and you should get what these directives do.
#ifdef XXX is just the same as #if defined(XXX) where defined(XXX) is builtin preprocessor-only function which is true when identifier XXX is defined in program text by another preprocessor directive #define. And #ifndef XXX is just #if !defined(XXX).
I'm reading a piece of code that seems like it optionally uses the C++ Boost library. It is as follows:
#ifdef _HAVE_BOOST
#include <boost/random.hpp>
#endif
Later on in the code, there are several statements that depend on this "_HAVE_BOOST". I presume that _HAVE_BOOST is simply a flag that is set to true, if the C++ library is properly imported.
Is the "_HAVE_BOOST" flag a built-in part of C++ ifdef syntax? That is, I tried Googling for this flag but didn't find any documentation. Also, at the head of the file, no #include<boost> is present. It looks like this boost functionality is deprecated throughout the file -- would _HAVE_BOOST be set to true if this #include<boost> were added?
Is there a list or documentation somewhere for describing the kinds of capital letters that go along with #ifdef?
I presume that _HAVE_BOOST is simply a flag that is set to true...
#ifdef _HAVE_BOOST does not test whether _HAVE_BOOST is true; It test whether such preprocessor macro is defined at all, regardless of the value.
...if the C++ library is properly imported.
Yes, considering the context, this particular macro is probably meant to signify, whether Boost is available or not and thus, whether it's possible to depend on it.
Is there a list or documentation somewhere for describing the kinds of capital letters that go along with #ifdef?
Macros can be defined with either #define directive in a header file or, in the compilation command (See the -D option for gcc for example). Compilers may also predefine some macros as well.
Any header file can define macros. You should usually be able to find which macros may be defined by reading the documentation, or if you don't have documentation, by reading the header files themselves.
would _HAVE_BOOST be set to true if this #include were added?
I find it unlikely that it would be defined in <boost> itself. After all, testing if Boost is available after you try to include it would be rather pointless.
When is _HAVE_BOOST defined?
You should ask that from the person who wrote the code. Another question to ponder is, is it defined at all? If it isn't, then the code between the ifdefs is removed by the preprocessor.
My crystal ball tells me that it's probably supposed to be defined by some sort of configuration script for the build process. For example, autoconf has a macro that will define a preprocessor macro HAVE_header-file if a header exists. Note the lack of underscore at the beginning.
this just means that if you define a preprocessor macro "_HAVE_BOOST" the compiler will include boost/random.hpp. Like this:
#define _HAVE_BOOST
#ifdef _HAVE_BOOST
#include <boost/random.hpp>
#endif
Look here for more details about preprocessor directives.
If the compiler supports c++11, it will have <random> support.
With some clever use of indirect includes and typedefs (or using statements ?!) it could be made to work with or without boost for random.
When the code is burden with a lot of #if, #ifdef. Like the case below
#ifdef CASE1
#ifdef CASE1_1
#define VALUE X
#else
#define VALUE Y
#endif
#else
#define VALUE Z
#endif
Is there a way to quickly determine which branch the code will get compiled. Any suggestions are appreciated. Thanks and Best Regards
Reading nested preprocessor macros can be made easier by indenting. Most preprocessors allow:
#ifdef foo
#define bar (1)
#endif
But the following form should be universally allowed:
#ifdef foo
# define bar (1)
#endif
While that helps follow the nest, it doesn't guarantee that you'll be able to spot which path is active, particularly if you are doing definitions by passing options to your compiler via -D
One solution is to run the preprocessor over your source files and inspect the output. You can either do that by running the preprocessor executable manually (eg. cpp), or by telling your compiler to stop after running the preprocessor (eg. gcc -E)
That is guaranteed to show you what values have been substituted for your preprocessor macros. But the output from the preprocessor can be hard to follow.
If you're just trying to trace a small section of code (as in your example) you can do it manually by liberally inserting #error (or #warning if your preprocessor supports it), and looking at the errors dumped from your compiler. This is typically the simplest option as you don't have to make changes to your build system to get the visibility that you're after.
Another option, depending on the complexity of your preprocessor macros, is to run another preprocessor tool over your source files that will generate friendlier output than the preprocessor. I've had success with filepp in the past.
You could ident it as
#ifdef CASE1
# ifdef CASE1_1
# define VALUE X
# else
# define VALUE Y
# endif
#else
# define VALUE Z
#endif
The compiler won't complain and the same identation style is currently used in qglobal.h from Qt which has to support a quite a number of compilers on many platforms.
Some IDEs will highlight the "good parts" or grey out the "bad parts"; Visual Studio does this (only if it understands the #defines, though!)
And of course, you can run the preprocessor over your source and look at the output -- for example, with the -E switch to g++.
Don't trust Visual Studio. It grays out code that executes. Lots of times, especially when you mix preprocessor macros in the project settings with those defined in your header files.
Simple approach?
#ifdef CASE1
#ifdef CASE1_1
#define VALUE X
const int branch = 1;
#else
#define VALUE Y
const int branch = 2;
#endif
#else
#define VALUE Z
const int branch = 3;
#endif
At the end, you have a variable whose value will tell you which branch got compiled in. Not very elegant, but it does do what you asked and I'm guessing you need this for debugging purposes anyway :)
WebKit has a lot of pre-processor lines like this:
#if MACRO1(MACRO2)
For example:
#if PLATFORM(MAC) || (PLATFORM(QT) && USE(QTKIT))
#include "MediaPlayerPrivateQTKit.h"
#if USE(AVFOUNDATION)
#include "MediaPlayerPrivateAVFoundationObjC.h"
#endif
...
So my first thought was that they were function-like macros, but I can't see how that would work, and I couldn't find any #defines for these macros anywhere in the source code.
I asked another engineer what it was and he's never seen multiple macros used like that inside a #if before either.
I found this wiki page that talks about them but it still wasn't clear to me where they come from,
So my question then: Is this valid C++ or is it being replaced in the code by another tool/language like CMake or something else, and if it is valid C++ is there a spec anyone is aware of that talks about this?
I'm a support engineer for a C++ Static Analysis tool that isn't handling this syntax. A customer asked us to handle it, but if I'm going to take this to the senior engineer I'd like to not sound like an idiot :) So I'd like the nitty gritty if anyone knows it.
As mentioned in the wiki, in root/trunk/Source/JavaScriptCore/wtf/Platform.h we get a definition for each of these defines. For instance, the PLATFORM macro is defined as:
#define PLATFORM(WTF_FEATURE) \
(defined WTF_PLATFORM_##WTF_FEATURE \
&& WTF_PLATFORM_##WTF_FEATURE)
The value of WTF_FEATURE will be replaced by the platform name to create some macro named WTF_PLATFORM_WTF_FEATRE. For instance, with WTF_FEATURE passed into the macro as MAC, you would end up with a expansion of WTF_PLATFORM_MAC. The pre-processor defined directive combined with the logical AND is basically asking whether that macro value defined, and if it is defined, if its value is a "true" value. You would use this macro somewhere else in the pre-processor like:
#ifdef __APPLE__
#define WTF_PLATFORM_MAC 1
#end if
#define PLATFORM(WTF_FEATURE) \
(defined WTF_PLATFORM_##WTF_FEATURE \
&& WTF_PLATFORM_##WTF_FEATURE)
#if PLATFORM(MAC)
//...some code
#end if
You wouldn't use it within C++ code itself like
if (PLATFORM(MAC))
{
//...some code
}
that would cause a bunch of errors from the compiler since defined is not a C++ keyword, and the evaluation and replacement of the macro within C++ code would end up dumping the defined pre-processor directive into any C++ code that directly called the macro. That's not valid C++.
Thanks you to Johannes for pointing out some of these issues.
The #if directive roughly works by replacing all macros, and then replacing all identifier and keywords of what's left by 0 and afterwards processing what's left has a constant expression according to the rules of the C++ language (the subset of those rules applicable to what's left from that replacing - quite little :)).
So PLATFORM(MAC) may yield a 1 if MAC is defined to be 1, and a MAC if it is not defined, if PLATFORM is simply defined as
#define PLATFORM(X) X
The resulting MAC is an identifier and will later be replaced by 0. It's more likely that they are concatenating the X to something like PLATFORM, so as to support multiple queries with MAC as argument, testing for existence of different macros. As a developer of a " C++ Static Analysis" tool you probably have access to the C++ spec. Take a look at clause 16.1.
The definitions may be coming from the build scripts. Most C++ compilers let you define macros on the command line.
One way I can see to define a USE macro like in your example would be:
#define USE_QTKIT 1
#define USE(x) USE_ ## x
Or maybe like:
gcc -DUSE_QTKIT=1 '-DUSE(x)=USE_ ## x'
I would like to be able pass arguments to ./configure script, so it would add NDEBUG used by to my generated header file. How can I do that? My configure script is generated from configure.ac.
I already one great answer, but it seems that I my question is wrong. The option would have to remove this NDEBUG, because by default I would like to have assertions turned off. There is no AC_UNDEFINE, so I need to use some trick: define ASSERT_ON, which would turn off NDEBUG. Is there any easier, better way?
You'll want to use the AC_ARG_ENABLE() macro in your configure.ac file to trigger an action when someone adds --enable-foo to your command line options.
AC_ARG_ENABLE(foo, "used to turn on the NDEBUG flag",
[ AC_DEFINE(NDEBUG) ]
)
You can use AH_VERBATIM in order to add extra data to your config.h.in (and thus, config.h file).
The thing is, autoconf is going to comment out anything that looks like a #undef statement when producing the config.h file out of the template.
There is a preprocessor trick to avoid that: use #/**/undef/**/. The C preprocessor is going to strip the comments first, but autoconf will not see that as a #undef statement.
To recap, in order to enforce NDEBUG being undefined:
AH_VERBATIM([NDEBUG], [/* Never ever ignore assertions */
#ifdef NDEBUG
#/**/undef/**/ NDEBUG
#endif])