Macro Expansion

V

Vittal

Hello All,

I am trying to get a cut down version of preprocessor output. Let me
make myself clear with a sample:
***************************************************************************
/*file x.c */
#include <stdio.h>

int main ()
{
int i = 10;
#ifdef TEST
i = i +10;
#else
i = i -10;
#endif
printf("The value of i = %d \n",i);
}

*************************************************************************
If I take the preprocessor output for the above file, the output file
will contain huge amount of code as the contents of all the header
files are dumped into output code.

What I am looking at is a output of this nature (if TEST is not
defined)
*********************************************************************
#include <stdio.h>

int main ()
{
int i = 10;
i = i -10;
printf("The value of i = %d \n",i);
}
*********************************************************************

Is it possible to get a output of this nature. Is there any way I can
ask the preprocessor not to dump the header file contents, or is there
any other tool available which can serve this purpose?

Any help in this regard is greatly appreciated.

Thanks
-Vittal
 
C

Chris Croughton

I am trying to get a cut down version of preprocessor output. Let me
make myself clear with a sample:
***************************************************************************
/*file x.c */
#include <stdio.h>

int main ()
{
int i = 10;
#ifdef TEST
i = i +10;
#else
i = i -10;
#endif
printf("The value of i = %d \n",i);
}

*************************************************************************
If I take the preprocessor output for the above file, the output file
will contain huge amount of code as the contents of all the header
files are dumped into output code.

What I am looking at is a output of this nature (if TEST is not
defined)
*********************************************************************
#include <stdio.h>

int main ()
{
int i = 10;
i = i -10;
printf("The value of i = %d \n",i);
}
*********************************************************************

Is it possible to get a output of this nature. Is there any way I can
ask the preprocessor not to dump the header file contents, or is there
any other tool available which can serve this purpose?

It will be specific to the preprocessor (indeed the C standard doesn't
mandate that the preprocessor stage be able to produce any output at
all, it could keep it all in memory for instance). Some preprocessors
do things like putting the line number at the start of each line, or
inserting #line directives or other oddities.

Since yours is fairly 'clean', though, the easiest way to do it is to
put some marker after the #include files:

#include <stdio.h>

/* LOAD oF RuBbIsH which WON't aPPear aNyWherE ELSE */

and then post-process the resulting file and cut out everything before
the marker line. On a *ix system I'd use sed, for example:

gcc -E x.c | sed '1,/LOAD oF RuBbIsH which WON't aPPear aNyWherE ELSE/d'

If your preprocessor inserts lines like

#line 123 "stdio.h"

then you could write a more intelligent post-processor (I'd use Perl or
AWK) which keeps track of which file produced the output and only output
that belonging to the top-level source. For instance, gcc (version 3.3.5)
produces output like:

# 1 "x.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "x.c"

char x;

# 1 "1.h" 1

char x1;
# 1 "11.h" 1
char x11;
# 4 "1.h" 2
# 1 "12.h" 1
char x12;
# 5 "1.h" 2
char x1_end;
# 5 "x.c" 2
# 1 "2.h" 1

char x2;
# 1 "21.h" 1
char x21;
# 4 "2.h" 2
# 1 "22.h" 1
char x22;
# 5 "2.h" 2
char x2_end;
# 6 "x.c" 2

char x_end;

(Sorry, I wasn't very inventive with the file or variable names!)

With system includes it puts more digits on the end of the # lines, I
have no idea what they mean. Anyway, you can see that by recognising
the string with the source file name and only doing output when the last
string matches the top file name you could extract only the code you
want...

Chris C
 
E

Eric Sosman

Chris said:
I am trying to get a cut down version of preprocessor output. [...]
> [...]
Since yours is fairly 'clean', though, the easiest way to do it is to
put some marker after the #include files:

#include <stdio.h>

/* LOAD oF RuBbIsH which WON't aPPear aNyWherE ELSE */
>
and then post-process the resulting file and cut out everything before
the marker line. [...]

If the implementation makes the preprocessor's "output"
available (not guaranteed, as you note), the original comments
are not likely to be present in it. Comments disappear in
translation phase 3, before preprocessing directives and macro
expansions are processed. A better marker would be something
you're sure will survive past phase 4, like

char *delete_thru_here = "LoAd Of rUbBiSh";

There's still a problem, though, and it's a pretty bad
one. Even though this technique lets you snip away everything
the headers injected before the marker, the effects of any
macros defined in those headers will still appear in the
preprocessed source that follows. On one compiler I happen
to have handy,

#include <stdio.h>
int main(void) {
fputs ("Hello, world!\n", stderr);
return 0;
}

becomes (after preprocessing and snipping)

int main(void) {
fputs ("Hello, world!\n", (&__dj_stderr));
return 0;
}

Observe that the portable identifier `stderr' has been
replaced by a non-portable expression -- it happens to be
correct for the system at hand, but this transformed source
is no longer portable. Similar problems can be expected
with any other header-defined macros: INT_MAX, setjmp, ERANGE,
offsetof, ... In fact, all standard library functions are
subject to this sort of mangling, since the implementation is
permitted to define "masking" macros for them.

The compiler's job is to transform portable (we hope)
source code into a non-portable construct specialized for one
implementation. The preprocessor performs part of that
specialization, and its output has usually lost a good deal
of the portability the original source may have had. This
makes the "run it through the preprocessor and then fool
around with the output" strategy problematic at best.
 

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,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top