macro expansion

B

borophyll

Yet another macro question....

I am trying to ascertain a deterministic algorithm for processing
macro expansions. From my experimentation on GCC, it seems that macro
expansion is performed in roughly the following way:

1. When preprocessor comes across a macro name, it replaces name with
definition, and substitutes all formal parameters with the supplied
arguments

2. For each argument, perform macro expansion (if any). If the
result is further macros with arguments, then recursively process
these arguments.

3. Once we have descended as far as recursion can take us, we
backtrack to the previous macro that we expanded, and rescan it for
further expansion. We repeatedly backtrack until we have reached the
start

Here is an example

#define VERSION 6
#define str(x) #x
#define xstr(x) str(x)
#define INCFILE2(x) vers##x.h
#define INCFILE(x) INCFILE2(x)


#include xstr(INCFILE(VERSION))

The preprocessor sees the macro xstr, so it replaces it with its
definition

--> str(INCFILE(VERSION))

The preprocessor then performs further macro expansion on all
arguments. There is only one argument, INCFILE(VERSION), which we can
expand to

--> str(INCFILE2(VERSION))

This argument also happens to be a macro with parameters, so we
descend further. It has only one argument, VERSION, which is expanded

--> str(INCFILE2(6))

We have descended as deep as we can go, so we now back up and rescan
what we have produced, which is INCFILE2(6). This can be further
expanded, as INCFILE2 happens to be a macro. We do so...

--> str(vers##6.h)

The ## operator simplifies this to

--> str(vers6.h)

We have simplified this as far as possible, so we now backtrack again
and rescan. The preprocessor recognises str as a macro, and it
expands it

--> #vers6.h

which finally produces

"vers6.h"

We have backtracked all the way to the start, so the macro has been
fully expanded.

Is this correct? Comments welcome...

Regards, B
 
L

Laurent Deniau

Yet another macro question....

I am trying to ascertain a deterministic algorithm for processing
macro expansions. From my experimentation on GCC, it seems that macro
expansion is performed in roughly the following way:

1. When preprocessor comes across a macro name, it replaces name with
definition, and substitutes all formal parameters with the supplied
arguments

2. For each argument, perform macro expansion (if any). If the
result is further macros with arguments, then recursively process
these arguments.

3. Once we have descended as far as recursion can take us, we
backtrack to the previous macro that we expanded, and rescan it for
further expansion. We repeatedly backtrack until we have reached the
start

Here is an example

#define VERSION 6
#define str(x) #x
#define xstr(x) str(x)
#define INCFILE2(x) vers##x.h
#define INCFILE(x) INCFILE2(x)

#include xstr(INCFILE(VERSION))

The preprocessor sees the macro xstr, so it replaces it with its
definition

--> str(INCFILE(VERSION))

The preprocessor then performs further macro expansion on all
arguments. There is only one argument, INCFILE(VERSION), which we can
expand to

--> str(INCFILE2(VERSION))

This argument also happens to be a macro with parameters, so we
descend further. It has only one argument, VERSION, which is expanded

--> str(INCFILE2(6))

We have descended as deep as we can go, so we now back up and rescan
what we have produced, which is INCFILE2(6). This can be further
expanded, as INCFILE2 happens to be a macro. We do so...

--> str(vers##6.h)

The ## operator simplifies this to

--> str(vers6.h)

We have simplified this as far as possible, so we now backtrack again
and rescan. The preprocessor recognises str as a macro, and it
expands it

--> #vers6.h

which finally produces

"vers6.h"

We have backtracked all the way to the start, so the macro has been
fully expanded.

Is this correct? Comments welcome...

Regards, B

Yes, but it is not enough to explain the complete behavior of the
preprocessor and its possibilities. Paul Mensonides wrote a nice
documentation of about 20 pages on this topic (the most complete I
know). If you are really interested by cpp, you could ask him for a
copy and look into the code of the cpp library chaos-pp:

http://chaos-pp.cvs.sourceforge.net/chaos-pp/chaos-pp/

You can also have a look to fpp (much smaller):

http://cos.cvs.sourceforge.net/cos/COS/src/cos/fpp/

fpp doesn't use "slicing contexts" (interleaved invocations) for
simplicity (and maybe better portability), but it only targets code
generation by manipulating tuples, while chaos-pp target a complete
computational model and provides various data structures and
algorithms.

a+, ld.
 
B

borophyll

Yes, but it is not enough to explain the complete behavior of the
preprocessor and its possibilities. Paul Mensonides wrote a nice
documentation of about 20 pages on this topic (the most complete I
know). If you are really interested by cpp, you could ask him for a
copy and look into the code of the cpp library chaos-pp:

http://chaos-pp.cvs.sourceforge.net/chaos-pp/chaos-pp/

You can also have a look to fpp (much smaller):

http://cos.cvs.sourceforge.net/cos/COS/src/cos/fpp/

fpp doesn't use "slicing contexts" (interleaved invocations) for
simplicity (and maybe better portability), but it only targets code
generation by manipulating tuples, while chaos-pp target a complete
computational model and provides various data structures and
algorithms.

a+, ld.

It looks interesting, but I don't know how to process all that XML
stuff that the documentation seems to be in...
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top