Preprocessor Directives Management Tool

L

lagman

All,

I'm looking for a tool that is able to take my code base (which is
full of preprocessor directives) and spit out source code that is
"clean" of any preprocessor directives based on the options I choose
(possibly via some kind of user input screen).

Does such a tool exist? A Visual Studio plugin would be even better.

FYI: I have requirements to rid my code of all conditionally compiled
code.

Thanks,
Dan
 
I

Ian Collins

lagman said:
All,

I'm looking for a tool that is able to take my code base (which is
full of preprocessor directives) and spit out source code that is
"clean" of any preprocessor directives based on the options I choose
(possibly via some kind of user input screen).
Most compilers have an options to output the pre-processes code. -E is
often used for this.
 
I

Ian Collins

Eric said:
... but that's not a good tool for the task, because it will
expand all the macros and replace #include directives with the
included source.
Isn't #include a preprocessor directive?

The OP asked for something that would 'spit out source code that is
"clean" of any preprocessor directives'.
 
B

Ben Bacarisse

Ian Collins said:
Isn't #include a preprocessor directive?

Yes, but...
The OP asked for something that would 'spit out source code that is
"clean" of any preprocessor directives'.

They clarified the requirement:

| FYI: I have requirements to rid my code of all conditionally compiled
| code.
 
I

Ian Collins

Ben said:
Yes, but...


They clarified the requirement:

| FYI: I have requirements to rid my code of all conditionally compiled
| code.
Which -E would do.
 
B

Ben Bacarisse

Ian Collins said:
Which -E would do.

I never said otherwise! A tool that follows #includes (so it can find
#defines and so on) but does not replace them is more useful than -E.
Once you have expanded #includes you may not even have C anymore! You
certainly won't have portable C. The result might not even compile
using different compiler flags.

Eric was saying that the OP's *real* requirement might be better
served with a tool that is less crude than actually running the
pre-processor.
 
P

Pranav Peshwe

All,

I'm looking for a tool that is able to take my code base (which is
full of preprocessor directives) and spit out source code that is
"clean" of any preprocessor directives based on the options I choose
(possibly via some kind of user input screen).

Does such a tool exist?  A Visual Studio plugin would be even better.

FYI:  I have requirements to rid my code of all conditionally compiled
code.

Do you wish that your code should be 'compilable' after you get rid of
all preprocessor directives ? Or you just want to run some static code
analysis tool on it ?

- Pranav
http://pranavsbrain.peshwe.com
 
L

lagman

     You're right.  Sorry; I'd imagined for a moment that
the O.P. was asking for something useful.

     O.P.: Follow Ian's suggestion to get source code that
is completely free from preprocessor directives (perhaps
after stripping out some #line directives), and almost
completely useless.  You will never be able to move the
resulting source to another machine, or even to another
compiler.  You may not even be able to move it to your
current compiler if you decide to change the compilation
options or apply the latest patches.  Have a nice life!

--
Eric Sosman
(e-mail address removed)- Hide quoted text -

- Show quoted text -

Sorry.. I'll clarify.. Not all preprocessor directives, just
conditionally compiled code (i.e. #ifdef/#ifndef)

Thanks,
Dan
 
J

jameskuyper

lagman said:
Sorry.. I'll clarify.. Not all preprocessor directives, just
conditionally compiled code (i.e. #ifdef/#ifndef)

Do you want it to remove only the #ifdef and #ifndef statements? Do
you also want #if's removed? Do you want it to also remove the
corresponding #else, #elif, and #endif statements? Do you want it to
also remove all the code between each #ifdef/#ifndef direction and the
matching #endif directive? Those are all pretty trivial options.
They'll produce code that might not even compile, and if it does,
might not do what the original code did. But if that's what you want,
it's quite feasible.

I think it's most likely that you want it to remove all of the
conditional compilation directives, and the branches that would not
have been selected, while keeping the branches that would have been
selected. On some systems, preprocessing is performed by a completely
separate program; even when that's not the case, many compilers
provide an option (often -E) that has precisely that effect. However,
you've indicated that the conditional compilation directives are the
only ones you want removed, and that makes it much more complicated.

This is not a common need; I wouldn't know where to look for an
existing utility that performs such filtration. If you want to write
one yourself, it will get a bit complicated. The fundamental problem
is that determining which branch of a #if is used requires
implementation of macro expansion, which in turn requires implementing
#defines. In particular, it requires knowing which identifiers have
been pre-#defined by the compiler. It also requires implementation of
a large subset of C's expression syntax. Determining which branch is
chosen by #ifdef/#ifndef is simpler, because it only requires keeping
track of which macros have been #defined, without worrying about what
their definitions are. However, this also implies that #Include has to
be implemented, since the relevant #define statements might have
occurred inside of files that should have been #included. In other
words, such a program would have to implement most of the
preprocessing directives in order to decide which branch to keep, but
it must produce output that doesn't actually reflect the application
of those directives.

Given that standard headers might use non-standard extensions to C,
might #define identifiers with names reserved to the implementation,
and might not even be implemented as files in accessible locations, I
don't think that there's any way to write a portable program that
performs such a task in general. However, If you can restrict the
inputs to code which doesn't refer to any such identifiers, and
doesn't rely upon any impIementation-specific exetensions, I think it
would be feasible, but it won't be trivial.
 
J

jacob navia

lagman said:
All,

I'm looking for a tool that is able to take my code base (which is
full of preprocessor directives) and spit out source code that is
"clean" of any preprocessor directives based on the options I choose
(possibly via some kind of user input screen).

Does such a tool exist? A Visual Studio plugin would be even better.

FYI: I have requirements to rid my code of all conditionally compiled
code.

Thanks,
Dan

The lcc-win compiler will tell you which lines are active.
The utility browsegen from that system will show you which lines are
inactive.

For instance:

#ifdef FOO
int a;
#else
double a;
#endif

browsegen -showifdeflines -DFOO foo.c
3
4

browsegen -showifdeflines foo.c
1
2

Using the list of lines it is very easy to wrfite a simple utility that
will delete all the lines from a given file...

Obviously I can tailor the system to fit your needs, make it run under
linux/AIX/Solaris/ etc.

Just send me mail for price etc.
 
K

Keith Thompson

lagman wrote: [...]
Sorry.. I'll clarify.. Not all preprocessor directives, just
conditionally compiled code (i.e. #ifdef/#ifndef)

Do you want it to remove only the #ifdef and #ifndef statements? Do
you also want #if's removed? Do you want it to also remove the
corresponding #else, #elif, and #endif statements? Do you want it to
also remove all the code between each #ifdef/#ifndef direction and the
matching #endif directive? Those are all pretty trivial options.
They'll produce code that might not even compile, and if it does,
might not do what the original code did. But if that's what you want,
it's quite feasible.

I think it's most likely that you want it to remove all of the
conditional compilation directives, and the branches that would not
have been selected, while keeping the branches that would have been
selected. On some systems, preprocessing is performed by a completely
separate program; even when that's not the case, many compilers
provide an option (often -E) that has precisely that effect. However,
you've indicated that the conditional compilation directives are the
only ones you want removed, and that makes it much more complicated.
[...]

Here's an idea that won't quite work, but it might be the basis for
something that would.

Do it in three passes.

In pass 1, comment out all #include and #define directives. Do this
in a way that's reversible; each comment includes some unique string
that can be recognized in pass 3.

In pass 2, run the output of pass 1 through your preprocessor. (A
compiler isn't required to provide a preprocessor as a separate
program, but most do.)

In pass 3, uncomment the #include and #define directives that you
commented out in pass 1. Remember that if you had this line:

/* #include "foo.h" */

in your original source, it must remain as a comment in the final
result; this is why you need the unique string.

Why doesn't this actually work? Because some of your #if, #ifdef, and
#ifndef directives are likely to depend on macros that you'll have
commented out in pass 1.

My assumption is that, given this input:

#define FOO 42
#ifdef FOO
printf("FOO is defined as %d\n", FOO);
#else
puts("FOO is not defined");
#endif

you want this output:

#define FOO 42
printf("FOO is defined as %d\n", FOO);

If so, that means you need to pay attention macro definitions for
purposes of #if, #ifdef, and #ifndef, but not for purposes of
expansion. That makes it tricky.

Most Unix-like systems have a tool, originally from BSD, called
"unifdef" that might do much of what you want. If you have access to
it, read the documentation carefully; if you have questions about the
unifdef tool itself, comp.unix.programmer is probably the best place
to ask.
 
B

Ben Bacarisse

Sorry.. I'll clarify.. Not all preprocessor directives, just
conditionally compiled code (i.e. #ifdef/#ifndef)

Some C pre-processors can give you a leg up, so to speak. For
example, the GNU one has -fdirectives-only which gets you about 90% of
the way there.

It does process #includes but since it leaves a note of the files (and
line numbers) as it is reading the source, I suspect a small bit of
scripting could cut out the expansion of the includes and put the
original directives back.
 
P

Pranav Peshwe

lagman wrote: [...]
Sorry.. I'll clarify.. Not all preprocessor directives, just
conditionally compiled code (i.e. #ifdef/#ifndef)
Do you want it to remove only the #ifdef and #ifndef statements? Do
you also want #if's removed? Do you want it to also remove the
corresponding #else, #elif, and #endif statements? Do you want it to
also remove all the code between each #ifdef/#ifndef direction and the
matching #endif directive? Those are all pretty trivial options.
They'll produce code that might not even compile, and if it does,
might not do what the original code did. But if that's what you want,
it's quite feasible.
I think it's most likely that you want it to remove all of the
conditional compilation directives, and the branches that would not
have been selected, while keeping the branches that would have been
selected. On some systems, preprocessing is performed by a completely
separate program; even when that's not the case,  many compilers
provide an option (often -E) that has precisely that effect. However,
you've indicated that the conditional compilation directives are the
only ones you want removed, and that makes it much more complicated.

[...]

Here's an idea that won't quite work, but it might be the basis for
something that would.

Do it in three passes.

In pass 1, comment out all #include and #define directives.  Do this
in a way that's reversible; each comment includes some unique string
that can be recognized in pass 3.

In pass 2, run the output of pass 1 through your preprocessor.  (A
compiler isn't required to provide a preprocessor as a separate
program, but most do.)

In pass 3, uncomment the #include and #define directives that you
commented out in pass 1.  Remember that if you had this line:

/* #include "foo.h" */

in your original source, it must remain as a comment in the final
result; this is why you need the unique string.

Why doesn't this actually work?  Because some of your #if, #ifdef, and
#ifndef directives are likely to depend on macros that you'll have
commented out in pass 1.

But, why to comment out the '#define's in the first place ? Without
doing that, your idea would probably work well.
Kindly CMIIW...

Pranav
http://pranavsbrain.peshwe.com
 
K

Keith Thompson

Pranav Peshwe said:
But, why to comment out the '#define's in the first place ? Without
doing that, your idea would probably work well.
Kindly CMIIW...

If you don't comment out the #defines, then this:

#define MAX_SIZE 1000
unsigned char buf[MAX_SIZE];

becomes this:

unsigned char buf[1000];

which I presume you don't want.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,128
Latest member
ElwoodPhil
Top