macro trick

L

ld

Is there any way to stringify only the first argument of __VA_ARGS__
within a variadic macro? Maybe playing with disabling context could
do the trick?

a+, ld.
 
M

Michael Schumacher

ld said:
Is there any way to stringify only the first argument of __VA_ARGS__
within a variadic macro? Maybe playing with disabling context could
do the trick?

Not sure if it solves your actual problem, but you could use this as
a good starting point:

#define FOO1(a, ...) #a, __VA_ARGS__
#define FOO(...) FOO1(__VA_ARGS__)

FOO(\n)
FOO(%d, 1)
FOO(%d%d,1,2)
FOO(%d%d%d,1,2,3)

"gcc -E" produces the following output:

"\n",
"%d", 1
"%d%d", 1,2
"%d%d%d", 1,2,3

Looks promising, no? ;-)


mike
 
M

Michael Schumacher

io_x said:
it is not prominsing,
any programmer could do 1000 trick like that
the result: a language that nobody understand

Oh, I see -- the language barrier! However, this particular piece of
code was intended to be fed to a C preprocessor, _not_ to an Italian!

Sorry I am very, for having not this beforehand made clear! ;-)


Ciao,
mike
 
L

ld

Not sure if it solves your actual problem.

Unfortunately, it doesn't (see below).
but you could use this as a good starting point:

   #define FOO1(a, ...) #a, __VA_ARGS__
   #define FOO(...) FOO1(__VA_ARGS__)

It should be

#define FOO(...) FOO1(__VA_ARGS__,)

otherwise
   FOO(\n)

is undefined (and gcc emits a warning). The trailing comma can be
removed, but it's beyond the scope of this question.
   FOO(%d, 1)
   FOO(%d%d,1,2)
   FOO(%d%d%d,1,2,3)

"gcc -E" produces the following output:

   "\n",
   "%d", 1
   "%d%d", 1,2
   "%d%d%d", 1,2,3

Looks promising, no?  ;-)

Yes. According to my _incomplete_ question (my fault), the answer was
trivial ;-) But an important point was missing in my question
(probably erased after some reformulation)! The complete question
should have been (and justify the "disabling context" suggestion):

Q: Is there any way to stringify only the first argument of
__VA_ARGS__ without expanding __VA_ARGS__ macros?

Taking your example as a backup:

#define TRUE 1

FOO(TRUE)

should produce "TRUE" and not "1" as it does now...

The application is a variadic assert() where optional arguments could
be provided. So actually

assert( cond );

and

assert( cond, extra_args );

do not display the same stringification of cond. The former does not
expand the macro in __VA_ARGS__ while the later does...

Thanks for you reply.

a+, ld.
 
L

ld

"Michael Schumacher" <[email protected]> ha scritto nel messaggio











it is not prominsing,
any programmer could do 1000 trick like that
the result: a language that nobody understand

845 to be exact.

And you are not supposed to understand the implementation, only the
semantic of the interface which has only 48 macros ;-)

a+, ld.
 
L

ld

Is there any way to stringify only the first argument of __VA_ARGS__
within a variadic macro? Maybe playing with disabling context could
do the trick?

a+, ld.

Answering to myself for archive ;-),
the answer is that it's not possible, AFAIK

One solution I had in mind was:

#define test_assert(...) \
COS_PP_IF(COS_PP_EQ(COS_PP_NARG(__VA_ARGS__),4)) \
(COS_CTR_ASS_(COS_PP_STR1(__VA_ARGS__##_),__VA_ARGS__), \
COS_CTR_ASS_(#__VA_ARGS__,__VA_ARGS__))

#define COS_CTR_ASS_(...) \
COS_PP_CAT_NARG(COS_CTR_ASS_,__VA_ARGS__)(__VA_ARGS__)

#define COS_CTR_ASS_2(CS,C) \
COS_CTR_ASS_3(CS,C,CS)

#define COS_CTR_ASS_3(CS,C,S) \
COS_CTR_ASS_6(CS,C,S,__FUNC__,__FILE__,__LINE__)

#define COS_CTR_ASS_5(CS,C,M,F,L) \
COS_CTR_ASS_6(CS,C,CS,M,F,L)

#define COS_CTR_ASS_6(CS,C,S,M,F,L) \
((void)((C) || (cos_exception_assert(S,M,F,L),0)))

The test_assert() macro should count the number of its arguments (line
1) and if it has 4 arguments, it adds COS_PP_STR1(__VA_ARGS__##_) in
front of the list (line 2) otherwise it adds the stringified
__VA_ARGS__ (line 3) which will be used only in the case of one
argument (i.e. CS in COS_CTR_ASS_2).

So in principle:

test_assert( cond );
test_assert( cond , func, file, line );
test_assert( cond , msg_str, func, file, line );

work fine. But the (more common) case:

test_assert( cond, msg_str ); // use COS_CTR_ASS_3

like in:

assert( 0 == 0, "bug in the compiler" );

doesn't work anymore. The reason is that I use the ## operator to
delay the expansion of __VA_ARGS__ in COS_PP_STR1(__VA_ARGS__##_) and
have the time to separate the arguments before the conversion of cond
to a string. But ## is evaluated before macros start to be scanned
(6.10.3.3 §3) and therefore before the lazy COS_PP_IF has a chance to
discard the invalid construction "..."##_ which appears in this later
case.

a+, ld.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top