By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,934 Members | 1,692 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,934 IT Pros & Developers. It's quick & easy.

Code blocks as macro parameters

P: n/a
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).

--
Alexander Ulyanov, maintainer of PosBand roguelike
E-mail: uav AT urmail DOT ru Web: http://orthanc.chat.ru/pos/
"...And his name is Melkor, Lord of All, Giver of Freedom, and he shall
make you stronger that they." -- Akallabeth, the Downfall of Numenor
Nov 14 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Alexander Ulyanov <ua*@urmail.ru> wrote:
# 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;).

--
SM Ryan http://www.rawbw.com/~wyrmwif/
Quit killing people. That's high profile.
Nov 14 '05 #2

P: n/a
On 2004-08-20, SM Ryan <wy*****@tango-sierra-oscar-foxtrot-tango.fake.org> wrote:
Alexander Ulyanov <ua*@urmail.ru> wrote:
# 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!

--
Alexander Ulyanov, maintainer of PosBand roguelike
E-mail: uav AT urmail DOT ru Web: http://orthanc.chat.ru/pos/
"...And his name is Melkor, Lord of All, Giver of Freedom, and he shall
make you stronger that they." -- Akallabeth, the Downfall of Numenor
Nov 14 '05 #3

P: n/a
Alexander Ulyanov <ua*@urmail.ru> wrote:
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.
Nov 14 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.