views:

254

answers:

8
+4  Q: 

Pre-preprocessor

Hi,

I want to have a C pre-preprocessor which is filtering some #define statements from the sourcecode without changing anything else.

Why? This should be used to remove some client specific code from the sources if the source is handed out to another client.

Does anyone know of an existing solution?

Thanks! Simon

+1  A: 

I don't think you need a preprocessor for this. If you don't have nested #ifdef's in your code, any regex engine can remove anything that is located between #ifdef CLIENT and #endif (use non-greedy matching to match first #endif, not last).

qrdl
I don't think regex is the right tool for this job. It's not always the first `#endif` you want to match. If the code looks like `#if CLIENT... #if FOO... #endif... #endif` you want to match the second `#endif`. If the `if`s are the other way around, you want to match the first.
Graeme Perrow
@Graeme - that's why I wrote "If you don't have nested #ifdef's" part. However new Perl regex engine has a support for matching opening/closing braces so it can do the job even in case of nested #ifdefs
qrdl
@qrdl - sorry, I somehow missed that part of your answer.
Graeme Perrow
A: 

If you're using gcc, then you can use:

gcc <insert files here> -E

The -E option tells gcc to only preprocess the sources, and not to compile them.

Or, you could use grep to filter out specific files and let the preprocessor loose on them only.

grep -r '#define CLIENT_CODE' ./*.h
Aviral Dasgupta
Note : You are highly recommended *not* to do what you're saying you want to do. Preprocessing sources beforehand can break compatibility macros if your client is using a different system.
Aviral Dasgupta
Would downvoters care to leave a comment explaining what's wrong with this answer? I'm giving it +1 as it looks perfect to me. Even if you aren't using gcc as a compiler you could still download it and use it as a preprocessor for this task.
MarkJ
@MarkJ - Aviraldg's comment explains why this is not an ideal solution. I didn't downvote it myself, but unless the application is going to be built on an identical system to the one on which the preprocessing is done, this could lead to at best compilation failure and at worst very difficult-to-find bugs.
Graeme Perrow
@MarkJ: I didn't down vote, but might have done had it been at a positive number. The trouble is that the C pre-processor pre-processes the source, and includes the contents of <stdio.h> and so on. This is not likely to be what the questioner had in mind - they want the source except for some bits. So, I'm with Graeme and Aviraldg - this is not the right answer.
Jonathan Leffler
+10  A: 

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;
    }
Pierre
Thanks everyone, I think I will try this one.
Simon
As proposed, this involves modifying the source code so that the special patterns can be recognized. If the code does not exist yet (so you can start off with this scheme), then its fine. If your code already exists and uses #ifdef, then I recommend (strongly) using one of the many tools that deal with 'XXX is always defined' and 'YYY is always undefined'.
Jonathan Leffler
A: 

as far as I know... the preprocessor can be run as a separate step (using the correct compiler optios) . This way you can do whatever you want with the processed code.

Toad
Hi, that was the first I was thinking about. But I haven't found a simple option to use the preprocessor to replace only specific #define statements. Do you have an example for this?
Simon
looks like aviraldg beat me to it with the compiler options and all.
Toad
on a side note... in the good old days, the preprocessor was a separate step and a separate executable. It's very possible a separate preprocessor can still be found.
Toad
@reiner It is still a separate step in some environments. GCC, for example, doesn't do preprocessing itself - it calls cpp to do the job. cpp is available as separate binary.
qrdl
why again was my answer downvoted?
Toad
@reiner: your answer was downvoted because, although you can run the C preprocessor separately (either by compiler options or as a separate executable), what the questioner wants is not what the pre-processor does. For example, if the code contains '#include <stdio.h>', the output should still contain '#include <stdio.h>', and the macros (such as getchar()) should be left unchanged. On the other hand, some bits of code - those protected by #ifdef CLIENT / remove this / #else / keep this / #endif should only have the 'keep this' section of output. The standard preprocessor can't do that.
Jonathan Leffler
+1  A: 

I would put the client specific code in a separate directory or possibly part of a different project that would need to be checked out of the source control.

Put a function call that would be stubbed out or (I forget the proper term) loosely linked so that another function can be put in its place.

Robert
A: 

I recommend using an additional macro language layer for code filtering, like filepp. You may use a C preprocessor friendly syntax to express which parts belongs to which clients.

//%ifdef CLIENT_A
  code for client A
//%endif

//%ifdef CLIENT_B
  code for client B
//%endif

//%if "CLIENT_A" || "CLIENT_B"
  code for client A and B
//%endif

The '//%' prefix enables You to compile the code unmodified. You may run filepp before You giving out the code to a client.

sambowry
+2  A: 

This sounds like what I asked about in Is there a C pre-processor which eliminates ifdef blocks based on values defined. The best answer I got was sunifdef, or 'Son of unifdef', which has worked reliably for me on some excessively contorted conditional code (the accumulated crud from over 20 years of development on a wide variety of platforms with an inadequate theory of how to do platform-specific compilation).

Jonathan Leffler
A: 

You can also try unifdef which is rather simpler than sunifdef.

Tony Finch