|
I am no c programmer but have made some experience with __VA_ARGS__ and
ILE C.
My understanding is:
The number of parameters passed to the function must exceed the number
of defined parameters. That means that at least one parameter must be
passed as part of the variable parameters.
From the ILE C/C++ Language Reference:
Function-Like Macros
More complex than object-like macros, a function-like macro definition
declares the names of formal parameters within parentheses, separated
by commas. An empty formal parameter list is legal: such a macro can be
used to simulate a function that takes no arguments.
Function-like macro definition:
An identifier followed by a parameter list in parentheses and the
replacement tokens. The parameters are imbedded in the replacement
code. White space cannot separate the identifier (which is the name of
the macro) and the left parenthesis of the parameter list. A comma must
separate each parameter. For portability, you should not have more than
31 parameters for a macro. The parameter list may end with an ellipsis
(...). In this case, the identifier __VA_ARGS__ may appear in the
replacement list.
Function-like macro invocation:
An identifier followed by a comma-separated list of arguments in
parentheses. The number of arguments should match the number of
parameters in the macro definition, unless the parameter list in the
definition ends with an ellipsis. In this latter case, the number of
arguments in the invocation should exceed the number of parameters in
the definition. The excess are called trailing arguments. Once the
preprocessor identifies a function-like macro invocation, argument
substitution takes place. A parameter in the replacement code is
replaced by the corresponding argument. If trailing arguments are
permitted by the macro definition, they are merged with the intervening
commas to replace the identifier __VA_ARGS__, as if they were a single
argument. Any macro invocations contained in the argument itself are
completely replaced before the argument replaces its corresponding
parameter in the replacement code. This language feature is an
orthogonal extension of C++.
If the identifier list does not end with an ellipsis, the number of
arguments in a macro invocation must be the same as the number of
parameters in the corresponding macro definition. During parameter
substitution, any arguments remaining after all specified arguments
have been substituted (including any separating commas) are combined
into one argument called the variable argument. The variable argument
will replace any occurrence of the identifier __VA_ARGS__ in the
replacement list.
Regards
Mihael Schmidt
-----Original Message-----
From: c400-l-bounces+mihael.schmidt=rossmann.de@xxxxxxxxxxxx
[mailto:c400-l-bounces+mihael.schmidt=rossmann.de@xxxxxxxxxxxx] On
Behalf Of Simon Coulter
Sent: Monday, June 14, 2010 1:34 AM
To: AS400 programming iSeries / C400-L
Subject: [C400-L] Variadic macros prior to VRM530
I'm in the unfortunate position of trying to make a variadic macro
(from Unix/Linux gcc code) work on OS/400 VRM510.
The macro is:
#define DEBUG_LOG(...) if (ch->flags & OTPW_DEBUG) \
{ fprintf(stderr, __VA_ARGS__); fputc('\n',
stderr); }
Note the use of ellipses in the macro definition. This makes the macro
variadic and gives the 510 compiler a pink fit. The C compiler
complains with:
CZM0211 Parameter list must be empty, or consist of one or more
identifiers separated by commas.
The C++ compiler complains with:
"Expected an identifier but found "..." in the parameter list for the
macro "DEBUG_LOG".
The C compiler documentation indicates that variadic macros and the
__VA_ARGS__ identifier are supported at VRM530 and above but that
doesn't help me :)
I'm posting this because perhaps someone who hates C less than I do
may suggest a better solution.
I've tried a few things but I think the only way of making this work
on 510 is to rewrite all 37 of the macro invocations to use a function
which can then support the varying argument list. Something like:
#ifndef DEBUG_LOG
#if (__OS400_TGTVRM <= 520)
#define DEBUG_LOG if (ch->flags & OTPW_DEBUG)
#else
#define DEBUG_LOG(...) if (ch->flags & OTPW_DEBUG) \
{ fprintf(stderr, __VA_ARGS__); fputc('\n',
stderr); }
#endif
#endif
#if (__OS400_TGTVRM <= 520)
DEBUG_LOG debug_log( "Failed to change egid %d -> %d", oldgid, ch-
>gid );
#else
DEBUG_LOG("Failed to change egid %d -> %d", oldgid, ch->gid);
#endif
and then provide a print function that handles a varying argument list:
#if (__OS400_TGTVRM <= 520)
void debug_log( char * f, ...)
{
va_list args;
va_start( args, f );
vfprintf(stderr, f, args)
va_end( args );
fputc('\n', stderr);
}
#endif
However, that strikes me as somewhat ugly so if you have better
suggestions please fire away.
Regards,
Simon Coulter.
--------------------------------------------------------------------
FlyByNight Software OS/400, i5/OS Technical Specialists
http://www.flybynight.com.au/
Phone: +61 2 6657 8251 Mobile: +61 0411 091 400 /"\
Fax: +61 2 6657 8251 \ /
X
ASCII Ribbon campaign against HTML E-Mail / \
--------------------------------------------------------------------
--
This is the C programming iSeries / AS400 (C400-L) mailing list
To post a message email: C400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/c400-l
or email: C400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at http://archive.midrange.com/c400-l.
--
This is the C programming iSeries / AS400 (C400-L) mailing list
To post a message email: C400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/c400-l
or email: C400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at http://archive.midrange.com/c400-l.
As an Amazon Associate we earn from qualifying purchases.