macros that build macros

T

Thant Tessman

Back before C++ templates, I was taught a trick whereby one built C
macros that built other C macros. I can't remember how the heck we did
it. The problem is that there seems to be no standard way to include a
'#' or '#define' in the output of a macro. The other problem is that we
might have been using some sort of non-standard preprocessor trick to do it.

Obliged if anyone can point me in the right direction or tell me what
I'm trying to do is impossible.

-thant
 
B

borophyll

Back before C++ templates, I was taught a trick whereby one built C
macros that built other C macros. I can't remember how the heck we did
it. The problem is that there seems to be no standard way to include a
'#' or '#define' in the output of a macro. The other problem is that we
might have been using some sort of non-standard preprocessor trick to do it.

Obliged if anyone can point me in the right direction or tell me what
I'm trying to do is impossible.

-thant

It is impossible, according to the standard (paragraph 3 of 6.10.3.4
"Rescanning and further replacement")

"The resulting completely macro-replaced preprocessing token sequence
is not processed
as a preprocessing directive even if it resembles one, but all pragma
unary operator
expressions within it are then processed as specified in 6.10.9
below."

In other words, you cannot create preprocessor directives using macro
replacement. Of course, the compiler you were using in the past may
have had a non-standard extension which may have allowed such
behaviour

Regards,
B
 
J

Jack Klein

Back before C++ templates, I was taught a trick whereby one built C
macros that built other C macros. I can't remember how the heck we did
it. The problem is that there seems to be no standard way to include a
'#' or '#define' in the output of a macro. The other problem is that we
might have been using some sort of non-standard preprocessor trick to do it.

Obliged if anyone can point me in the right direction or tell me what
I'm trying to do is impossible.

-thant

"borophyll" already gave you the standard answer, that you cannot
directly generate a macro to be replaced in the expansion of another
macro.

There are other ways, depending on what it is you are trying to do,
which you haven't made clear. Show us an example of the macro you
would like to generate, and the other macros that you would like to
use in the generation. It might be possible.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
R

robertwessel2

Back before C++ templates, I was taught a trick whereby one built C
macros that built other C macros. I can't remember how the heck we did
it. The problem is that there seems to be no standard way to include a
'#' or '#define' in the output of a macro. The other problem is that we
might have been using some sort of non-standard preprocessor trick to do it.

Obliged if anyone can point me in the right direction or tell me what
I'm trying to do is impossible.


While it's not possible in general, sometimes people run C source code
through the preprocessor twice before the compiler proper. That way
any generated #defines in the first preprocessor pass get expanded in
the second.

There's no standard way of doing that, but many compilers have an
option to stop after the preprocessing phase and to emit that code.
Some compilers implement the preprocessor as a separate program, which
you can run manually. Again, all well outside the scope of the
standard.
 
B

borkhuis

Back before C++ templates, I was taught a trick whereby one built C
macros that built other C macros. I can't remember how the heck we did
it. The problem is that there seems to be no standard way to include a
'#' or '#define' in the output of a macro. The other problem is that we
might have been using some sort of non-standard preprocessor trick to do it.

Obliged if anyone can point me in the right direction or tell me what
I'm trying to do is impossible.

As indicated by others it is not possible to do this using the
standard preprocessor and compiler, you need to run the preprocessor
more than once.

A preprocessor that I used for something like this is GPP (http://
en.nothingisreal.com/wiki/GPP), which is a general purpose
preprocessor. Next to the standard evaluation rules that CPP uses it
also defines a 2-pass evaluation. This is from the manual page:

#defeval x y
This acts in a similar way to #define, but the second argument y is
evaluated immediately. Since user macro definitions are also evaluated
each time they are called, this means that the macro y will undergo
two successive evaluations.

Kind regards,
Johan Borkhuis
 
T

Thant Tessman

I said:
Back before C++ templates, I was taught a trick whereby one built C
macros that built other C macros. I can't remember how the heck we did
it. [...]

My thanks to all who replied. For the curious, the basic form of what
I'm trying to do is this:

#define FOO(A,B) stuff

should produce another macro:

#define BAR_A_B(C) stuff

The macros produce code in support of type-safe inter-process message
passing routines.

This is definitely a situation where it would be inappropriate to
deviate from the standard, and the workaround is simple enough:

#define FOO(A,B) stuff
#define BAR(A,B,C) more stuff

The reason this solution is less desirable is that the latter allows for
errors that the former would catch. But it's workable.

Again, thanks for the replies.

-thant
 
D

Dave Hansen

My thanks to all who replied. For the curious, the basic form of what
I'm trying to do is this:

#define FOO(A,B) stuff

should produce another macro:

#define BAR_A_B(C) stuff

The macros produce code in support of type-safe inter-process message
passing routines.

This is definitely a situation where it would be inappropriate to
deviate from the standard, and the workaround is simple enough:

#define FOO(A,B) stuff
#define BAR(A,B,C) more stuff

The reason this solution is less desirable is that the latter allows for
errors that the former would catch. But it's workable.

It's not really clear to me what you're trying to do. But I've used
sort of a backwards means of doing something similar. Consider the
following macros:

#define BIT(p,b) (b)

#define PORT(p,b) (PORT ## p)
#define PIN(p,b) (PIN ## p)
#define DDR(p,b) (DDR ## p)

#define MASK(b) (1 << (b))

#define Set_Port_Bit(p,b) ((p) |= MASK(b))
#define Clr_Port_Bit(p,b) ((p) &= ~MASK(b))
#define Tgl_Port_Bit(p,b) ((p) ^= MASK(b))

#define Get_Port_Bit(p,b) (((p) & MASK(b)) != 0)

#define Set_Output(io) Set_Port_Bit(PORT(io),BIT(io))
#define Reset_Output(io) Clr_Port_Bit(PORT(io),BIT(io))

#define Get_Input(io) Get_Port_Bit(PIN(io),BIT(io))

#define Tristate(io) Clr_Port_Bit(DDR(io),BIT(io))
#define Drive(io) Set_Port_Bit(DDR(io),BIT(io))

This was for an AVR microprocessor. There were for digital I/O ports,
a, B, C, and D. There were three I/O address for each digital I/O
port, PIN for reading input, PORT for writing output, and DDR (Data
Direction Register) to set each bit to be an input or an output. The
name of each register was appended with the port it referred to, e.g.,
PORTA, DDRB, PIND.

The macros above let me specify my output bits something like this

#define STATUS_LED A,7
#define SWITCH(n) D,(n+3) // switches on D3, D4, and D5

Then I could invoke the macros something like

Set_Output(STATUS_LED);
state = Get_Input(SWITCH(1));

If the hardware changes, and the status LED moved to port B, pin 3,
all I have to do is change the STATUS_LED definition to

#define STATUS_LED B,3

and everything works.

Perhaps you can adapt something like this.

Regards,

-=Dave
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top