Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to process C++ file to remove ifdef'd out code

I have inherited a piece of C++ code which has many #ifdef branches to adjust the behaviour depending on the platform (#ifdef __WIN32, #ifdef __APPLE__, etc.). The code is unreadable in its current form because these preprocessor directives are nested, occur in the middle of functions and even in the middle of multi-line statements.

I'm looking for a way of somehow specifying some preprocessor tags and getting out a copy of the code as if the code had been pre-processed with those flags. I'd like the #include directives to be left untouched, though. Example:

#include <iostream>

#ifdef __APPLE__
std::cout << "This is Apple!" << std::endl;
#elif __WIN32
std::cout << "This is Windows" << std::endl;
#endif

would turn into:

#include <iostream>

std::cout << "This is Apple!" << std::endl;

after being processed by: tool_i_want example.cpp __APPLE__.

I've hacked a quick script that does something similar, but I'd like to know of better tested and more thorough tools. I am running a Linux distribution.

I have decided against just running the C-preprocessor because if I'm not mistaken it will expand the header files, which would make everything more unreadable.

like image 544
user2891462 Avatar asked Nov 08 '16 09:11

user2891462


2 Answers

Use unifdef. It is designed for that purpose.

like image 57
Basile Starynkevitch Avatar answered Nov 01 '22 08:11

Basile Starynkevitch


Complementing Basile Starynkevitch's answer, I want to mention coan. The major advantage is that, when used with -m it does not require the user to unset all symbols they want undefined.

This code:

#include <iostream>

#ifdef __ANDROID__
std::cout << "In Android" << std::endl;
#endif

#ifndef __WIN32
std::cout << "Not a Windows platform" << std::endl;
#endif

#ifdef __APPLE__
std::cout << "In an Apple platform" << std::endl;
#elif __linux__
std::cout << "In a Linux platform" << std::endl;
#endif

would result in this code if simply run as: unifdef -D__APPLE__ example.cpp:

#include <iostream>

#ifdef __ANDROID__
std::cout << "In Android" << std::endl;
#endif

#ifndef __WIN32
std::cout << "Not a Windows platform" << std::endl;
#endif

std::cout << "In an Apple platform" << std::endl;

Using unifdef one would need to use

unifdef -D__APPLE__ -U__ANDROID__ -U__WIN32 -U__linux__ example.cpp:

#include <iostream>

std::cout << "Not a Windows platform" << std::endl;

std::cout << "In an Apple platform" << std::endl;

This can get exhausting quickly when dealing with code considering several different platforms. With coan it's a matter of:

coan source -D__APPLE__ -m example.cpp.

like image 43
user2891462 Avatar answered Nov 01 '22 07:11

user2891462