I have a project with a bunch of different options that you can turn on and off sprinkled throughout many files. You comment and uncomment the options you want, much like the php.ini file in PHP file, though this is actual code. It looks something like this:

//#ifndef _OPTION_1
//#define _OPTION_1
//#endif
#ifndef _OPTION_2
#define _OPTION_2
#endif

int menu()
{
    #ifdef _OPTION_1
        cout << "Option 1\n";
    #endif
    #ifdef _OPTION_2
        cout << "Option 2\n";
    #endif

    cout << "Pick an option : ";
    // code for picking an option, quitting, etc.
}


int main()
{
    int option;
    while(option = menu())
    {
        // code here for implementing options
    }

    return 0;
}

That's the idea, though with many, many options in many files and directories.

The pre-processor turns it into this:

int menu()
{
    cout << "Option 2\n";
    cout << "Pick an option : ";
    // code for picking an option, quitting, etc.
}


int main()
{
    int option;
    while(option = menu())
    {
        // code here for implementing options
    }

    return 0;
}

I'm getting a headache looking at the raw code with all the #define statements in it, so I'd rather look at the second version than the first. I'm looking for either a gcc/g++ compiler option that spits out the code with the #defines parsed/removed or some program that's already written that does that that I can just run. As a last resort, I suppose I can write one myself, but I'm hoping there's one that's already written. Can anyone guide me in the right direction?

Recommended Answers

All 9 Replies

I believe the switch is "-E" to preprocess but not compile.

Try this

g++ testit.cpp -E testit >testfile

Thanks. That works, to a point. Things got pretty ugly, though, when I added the old:

#include <iostream>
using namespace std;

at the top. 15,000 lines of stuff like this:

template<typename _CharT, typename _Traits>
    basic_istream<_CharT, _Traits>&
    basic_istream<_CharT, _Traits>::
    unget(void)
    {


      _M_gcount = 0;
      sentry __cerb(*this, true);
      if (__cerb)
 {
   ios_base::iostate __err = ios_base::goodbit;
   try
     {
       const int_type __eof = traits_type::eof();
       __streambuf_type* __sb = this->rdbuf();
       if (!__sb
    || traits_type::eq_int_type(__sb->sungetc(), __eof))
  __err |= ios_base::badbit;
     }
   catch(__cxxabiv1::__forced_unwind&)
     {
       this->_M_setstate(ios_base::badbit);
       throw;
     }
   catch(...)
     { this->_M_setstate(ios_base::badbit); }
   if (__err)
     this->setstate(__err);
 }
      return *this;
    }

followed by the stripped program, which strips fine, but keeps the excess lines:

int menu()
{




        cout << "Option 2\n";





        cout << "Option 4\n";


    cout << "Pick an option (0 to quit): ";
    int option;
    cin >> option;
    return option;
}


int main()
{
    int option;
    while(option = menu())
    {
        cout << "You picked " << option << endl;
    }

    return 0;
}

And if I have to pipe it into a file, that won't work because I need the files to remain separate files.

I only want the #define type statements to pre-process, not the #include. I imagine I'm looking for a program someone has written rather than a compiler option.

Is there anyway you can change the design of the program so it doesn't rely on compile time ifs? Seems like you want to implement state machine.

The code has state machines all over the place, but that isn't the issue here. The whole idea is to enable and disable options in a single configuration file. You get what you want and only what you want. The compiled code needs to fit on a 64K chip, which is impossible with all options enabled. I want this done more for code readability than anything else. I want to have a quick way of giving people (and myself) all the relevant code and only the relevant code. The #ifdef statements accomplish the task well from a compiler standpoint. I just need a quick parser that deletes the irrelevant lines. I figure I'm not the first person to want this, so it has to be out there somewhere.

>> That works, to a point. Things got pretty ugly, though, when I added the old ...
>> ... I only want the #define type statements to pre-process, not the #include.

Perhaps you'd like to 'guard' your #include s with #ifdef s, like so ..

// foo.cpp
#ifdef VERNON_COMPILES
#include <iostream>
#endif

int main()
  ...

Pre-processing would be:
g++ -E foo.cpp

and compiling would be:
g++ -D VERNON_COMPILES foo.cpp

Thanks. That could have some potential. I don't think it'll quite do what I'm after. I need to keep those #include guards in the code since it won't compile at all if the #include <iostream> is stripped out. I need them in there verbatim, plus I'm still struggling with all the blank lines (they're not he end of the world. I can probably do some condensing fairly quickly), but more importantly, these files (at least 100 of them) have to remain separate so I can't pipe them into one file.

Here's a fairly crazy proposal:
Pipe your files through sed -e 's/^#include/INCLUDE' prior to gcc -E, and then back through sed -e 's/^INCLUDE/#include/' (all that assuming that you don't want to expand any of your includes, and no line in your code begins with INCLUDE; in any case, the sed command could be tailored according to your needs). This is very much ad hoc, but I doubt there is a clean solution..

>> Here's a fairly crazy proposal

Crazy proposals can be good. If an idea works, it's not crazy, just unorthodox, but in a good way.

>> Pipe your files through sed -e 's/^#include/INCLUDE' prior to gcc -E, and then back through sed -e 's/^INCLUDE/#include/' (all that assuming that you don't want to expand any of your includes, and no line in your code begins with INCLUDE; in any case, the sed command could be tailored according to your needs). This is very much ad hoc, but I doubt there is a clean solution..

This has some nice potential. I didn't end up going with it, but I like it a lot, so maybe if/when I come back to this, I will. What I did had the same effect. I just used some global replace commands in an IDE rather than sed. I ended up using several techniques. I wrote a few really limited parsing programs, ran everything through the preprocessor, went file by file, and did a lot of edits in the IDE, deleting lines.

It definitely wasn't clean, but it ended up doing most of the job, though not nearly as nicely as I'd originally hoped.

Thanks to all.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.