Code blocks as macro parameters

A

Alexander Ulyanov

Hi all.

Is it possible to pass the whole blocks of code (possibly including
" and ,) as macro parameters?

I want to do something like:

MACRO(FOO, "Foo",
"return "Foobar";",
"foo(); bar();")

(just an example, obviously this won't compile)

being parsed to:

1.
P_FOO, /* Part of enum */
2.
"FOO", /* Part of string literal array */
3.
"Foo", /* Part of string literal array */
4.
case P_FOO: /* Part of switch */
return "Foobar";
break;
5.
case P_FOO: /* Part of switch */
foo(); bar();
break;

Depending on some #define, of course. I don't want to edit five
source files to add or remove something; keeping them consistent
is difficult.

I'm currently doing this with a m4 macro and it works fine, but I'd
like to avoid using an extra tool (which may not be available on
Windows or other non-UNIX systems).
 
S

SM Ryan

# Hi all.
#
# Is it possible to pass the whole blocks of code (possibly including
# " and ,) as macro parameters?

cat <<':eof' >/tmp/xx.c
#define repeat_until(block,predicate) do {block} while (!(predicate)
(1); repeat_until(x = f(x);,x>0);
(2); repeat_until(x = f(y,"b"); y = g(x,"a");,x>0);
(3); repeat_until(repeat_until(y=f(y);,y>0),x>0);
(4); repeat_until({int x,y; x=h(x,y);},z);
(5); repeat_until(int x,y; x=h(x,y);,z);
(6); repeat_until(int x; int y; x=h(x,y);,z);
:eof
cc -E /tmp/xx.c

The preprocessor is only looking for comma and parentheses. Parentheses
have to be balanced and commas outside of parentheses are argument
separators. You can almost always avoid commas: comma expressions
can be parenthesised, and joined declarations (like int x,y;) can be
separated (int x; int y;).
 
A

Alexander Ulyanov

# Hi all.
#
# Is it possible to pass the whole blocks of code (possibly including
# " and ,) as macro parameters?

cat <<':eof' >/tmp/xx.c
#define repeat_until(block,predicate) do {block} while (!(predicate)
(1); repeat_until(x = f(x);,x>0);
(2); repeat_until(x = f(y,"b"); y = g(x,"a");,x>0);
(3); repeat_until(repeat_until(y=f(y);,y>0),x>0);
(4); repeat_until({int x,y; x=h(x,y);},z);
(5); repeat_until(int x,y; x=h(x,y);,z);
(6); repeat_until(int x; int y; x=h(x,y);,z);
:eof
cc -E /tmp/xx.c

The preprocessor is only looking for comma and parentheses. Parentheses
have to be balanced and commas outside of parentheses are argument
separators. You can almost always avoid commas: comma expressions
can be parenthesised, and joined declarations (like int x,y;) can be
separated (int x; int y;).

Thanks!
 
O

Old Wolf

Alexander Ulyanov said:
Hi all.

Is it possible to pass the whole blocks of code (possibly including
" and ,) as macro parameters?

I want to do something like:

MACRO(FOO, "Foo",
"return "Foobar";",
"foo(); bar();")

(just an example, obviously this won't compile)

Regarding the code snippets, you can use an expression in brackets:
( foo(), bar() )
My experience is that using a single expression is preferable
to a set of statements, if possible.

In this case it is possible to avoid having the "return" as part
of the macro definition (see below).
being parsed to:

1.
P_FOO, /* Part of enum */
2.
"FOO", /* Part of string literal array */
3.
"Foo", /* Part of string literal array */
4.
case P_FOO: /* Part of switch */
return "Foobar";
break;

No need to 'break' if you have just returned :)
5.
case P_FOO: /* Part of switch */
foo(); bar();
break;

Depending on some #define, of course. I don't want to edit five
source files to add or remove something; keeping them consistent
is difficult.

Obviously you can't invoke the definition once and then have it copy
the code to various places; you will have to define a new meaning
for the macro when you want to use it. If the "calls" to MACRO()
are in "macro.h" then you could go:

enum {
#define MACRO(a,b,c,d) P_##a,
#include "macro.h"
#undef MACRO
};
char const *foo1 = {
#define MACRO(a,b,c,d) #a,
#include "macro.h"
#undef MACRO
NULL /* trailing commas are not portable */
};

switch(bar) {
#define MACRO(a,b,c,d) case P_##a: d; return c;
#include "macro.h"
#undef MACRO
};

etc.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top