variadic macros

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts

  • William Ahern
    Guest replied
    Re: variadic macros

    William Ahern <william@wilbur .25thandclement .comwrote:
    Christof Warlich <cwarlich@alcat el-lucent.dewrote:
    Hi,
    is there any way to access individual elements in the body
    of a variadic macro? I only found __VA_ARGS__, which always
    expands to the complete list.
    So, using Laurent's solution you can do lots of interesting things. For
    instance, you can overload functions or macros:
    #define foreach2(p, a) \
    for (typeof(&(a)[0]) p = (a); p - (a) < lengthof(a); p++)
    #define foreach3(p, a, n) \
    for (typeof(&(a)[0]) p = (a); p - (a) < (n); p++)
    Oops. A poor example because `typeof' is an extension, but it remains
    illustrative of C99 standard compliant overloading using number of arguments
    as the differentiator.

    Leave a comment:


  • William Ahern
    Guest replied
    Re: variadic macros

    Christof Warlich <cwarlich@alcat el-lucent.dewrote:
    Hi,
    is there any way to access individual elements in the body
    of a variadic macro? I only found __VA_ARGS__, which always
    expands to the complete list.
    So, using Laurent's solution you can do lots of interesting things. For
    instance, you can overload functions or macros:

    #define foreach2(p, a) \
    for (typeof(&(a)[0]) p = (a); p - (a) < lengthof(a); p++)

    #define foreach3(p, a, n) \
    for (typeof(&(a)[0]) p = (a); p - (a) < (n); p++)

    #define foreach_(N, ...) PASTE(foreach, N)(__VA_ARGS__)
    #define foreach(...) foreach_(PP_NAR G(__VA_ARGS__), __VA_ARGS__)

    That technique has proven very useful. Another interesting trick is to peek
    into __VA_ARGS__. That requires some indirection, and extending calls with
    dummy arguments. Here's something along those lines which I wrote this past
    weekend; very simple. The '3' is the default value, which can be overridden
    by the caller merely providing a second argument, shifting the default
    argument into the ether. (Visual Studio doesn't support much of C99, but
    2005 supports __VA_ARGS__; but don't quote me, because I almost always use
    Mingw).

    /*
    * Prefetching
    */
    #if __GNUC__ >= 3
    #define prefetch_((w), (p), (l), ...) __builtin_prefe tch((p), (w), (l))
    #define prefetch(...) prefetch_(0, __VA_ARGS__, 3)
    #define prefetchw(...) prefetch_(1, __VA_ARGS__, 3)
    #elif _MSC_VER >= 1400
    #include <winnt.h>
    #define prefetch_((p), (l), ...) PreFetchCacheLi ne((l), (p))
    #define prefetch(...) prefetch_(__VA_ ARGS__, 3)
    #define prefetchw(...) prefetch_(__VA_ ARGS__, 3)
    #else
    #define prefetch(...)
    #define prefetchw(...)
    #endif


    Following below is one of my attempts to combine that with PP_NARG to get
    something more generic and reuseable. The result is PP_MAP, which is at the
    end. I've used it to prefix arguments in a DNS library, so callers can do
    things like

    dns_lookup(dnsc tx, a, aaaa, mx)

    which using

    #define dns_rr_prefix(t ype) dns_rr_##type
    #define dns_lookup(dnsc tx, ...) \
    dns_lookup((dns ctx), PP_NARG(__VA_AR GS__), (int[]) { \
    PP_MAP(dns_rr_p refix, __VA_ARGS__) \
    })

    gets turned into

    dns_lookup(dnsc tx, 3, (int[]){ dns_rr_a, dns_rr_aaaa, dns_rr_mx })

    Actually, I do something a little different by using static inline
    functions, so I can turn types into a 64-bit unsigned integral bitmap w/
    overflow (types 62) copied into a compound literal variable-length array.
    GCC -O2 can turn all of that into constants. Probably overkill for a DNS
    library, but at the very least it improves the semantics of the user API
    (and I always like to play around w/ loop elimination strategies).

    The semantics of PP_MAP leaves something to be desired. It's more an
    experiment. Laurent's PP_NARG, on the other hand, is close to perfection as
    far as reusable macros go.


    /*
    * Select leading N items from list.
    */
    #define PP_ARGV(N, ...) PASTE(PP_ARGV, N)(__VA_ARGS__)
    #define PP_ARGV1(_00,.. .) \
    _00
    #define PP_ARGV2(_00,_0 1,...) \
    _00,_01
    #define PP_ARGV3(_00,_0 1,_02,...) \
    _00,_01,_02
    #define PP_ARGV4(_00,_0 1,_02,_03,...) \
    _00,_01,_02,_03
    #define PP_ARGV5(_00,_0 1,_02,_03,_04,. ..) \
    _00,_01,_02,_03 ,_04
    #define PP_ARGV6(_00,_0 1,_02,_03,_04,_ 05,...) \
    _00,_01,_02,_03 ,_04,_05
    #define PP_ARGV7(_00,_0 1,_02,_03,_04,_ 05,_06,...) \
    _00,_01,_02,_03 ,_04,_05,_06
    #define PP_ARGV8(_00,_0 1,_02,_03,_04,_ 05,_06,_07,...) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7
    #define PP_ARGV9(_00,_0 1,_02,_03,_04,_ 05,_06,_07,_08, ...) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7,_08
    #define PP_ARGV10(_00,_ 01,_02,_03,_04, _05,_06,_07,_08 ,_09,...) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7,_08,_09
    #define PP_ARGV11(_00,_ 01,_02,_03,_04, _05,_06,_07,_08 ,_09,_0a,...) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7,_08,_09,_0a
    #define PP_ARGV12(_00,_ 01,_02,_03,_04, _05,_06,_07,_08 ,_09,_0a,_0b,.. .) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7,_08,_09,_0a,_ 0b
    #define PP_ARGV13(_00,_ 01,_02,_03,_04, _05,_06,_07,_08 ,_09,_0a,_0b,_0 c,...) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7,_08,_09,_0a,_ 0b,_0c
    #define PP_ARGV14(_00,_ 01,_02,_03,_04, _05,_06,_07,_08 ,_09,_0a,_0b,_0 c,_0d,...) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7,_08,_09,_0a,_ 0b,_0c,_0d
    #define PP_ARGV15(_00,_ 01,_02,_03,_04, _05,_06,_07,_08 ,_09,_0a,_0b,_0 c,_0d,_0e,...) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7,_08,_09,_0a,_ 0b,_0c,_0d,_0e
    #define PP_ARGV16(_00,_ 01,_02,_03,_04, _05,_06,_07,_08 ,_09,_0a,_0b,_0 c,_0d,_0e,_0f,. ..) \
    _00,_01,_02,_03 ,_04,_05,_06,_0 7,_08,_09,_0a,_ 0b,_0c,_0d,_0e, _0f


    /*
    * Apply function-like macro F to each item in argument list.
    */
    #define PP_MAP16(F,_00, _01,_02,_03,_04 ,_05,_06,_07,_0 8,_09,_0a,_0b,_ 0c,_0d,_0e,_0f, ...) \
    F(_00),F(_01),F (_02),F(_03),F( _04),F(_05),F(_ 06),F(_07), \
    F(_08),F(_09),F (_0a),F(_0b),F( _0c),F(_0d),F(_ 0e),F(_0f)

    #define PP_MAP_(F,...) PP_MAP16(F,__VA _ARGS__)
    #define PP_MAP(F,...) PP_ARGV(PP_NARG (__VA_ARGS__),P P_MAP_(F,__VA_A RGS__,0,0,0,0,0 ,0,0,0,0,0,0,0, 0,0,0))


    Leave a comment:


  • William Ahern
    Guest replied
    Re: variadic macros

    Christof Warlich <cwarlich@alcat el-lucent.dewrote:
    It would already help if there would be a way to have something
    that expands to the number of arguments being passed to the variadic macro.
    /*
    * The PP_NARG macro evaluates to the number of arguments that have been
    * passed to it.
    *
    * Laurent Deniau, "__VA_NARG_ _," 17 January 2006, <comp.std.c(2 9 November 2007).
    */
    #define PP_NARG(...) PP_NARG_(__VA_A RGS__,PP_RSEQ_N ())
    #define PP_NARG_(...) PP_ARG_N(__VA_A RGS__)

    #define PP_ARG_N( \
    _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
    _11,_12,_13,_14 ,_15,_16,_17,_1 8,_19,_20, \
    _21,_22,_23,_24 ,_25,_26,_27,_2 8,_29,_30, \
    _31,_32,_33,_34 ,_35,_36,_37,_3 8,_39,_40, \
    _41,_42,_43,_44 ,_45,_46,_47,_4 8,_49,_50, \
    _51,_52,_53,_54 ,_55,_56,_57,_5 8,_59,_60, \
    _61,_62,_63,N,. ..) N

    #define PP_RSEQ_N() \
    63,62,61,60, \
    59,58,57,56,55, 54,53,52,51,50, \
    49,48,47,46,45, 44,43,42,41,40, \
    39,38,37,36,35, 34,33,32,31,30, \
    29,28,27,26,25, 24,23,22,21,20, \
    19,18,17,16,15, 14,13,12,11,10, \
    9,8,7,6,5,4,3,2 ,1,0

    Leave a comment:


  • vippstar@gmail.com
    Guest replied
    Re: variadic macros

    On May 23, 7:20 pm, vipps...@gmail. com wrote:
    On May 23, 1:18 am, Peter Nilsson <ai...@acay.com .auwrote:
    >
    Christof Warlich <cwarl...@alcat el-lucent.dewrote:
    Christof Warlich schrieb:
    is there any way to access individual elements in
    the body of a variadic macro? I only found
    __VA_ARGS__, which always expands to the complete
    list.
    >
    Not in standard C99.
    6.10.3 p 5
    The identifier __VA_ARGS__ shall occur only in the replacement-list
    of a function-like macro that uses the ellipsis notation in the parameters.
    Whoops; I just realized you meant that accessing individual elements
    in the body of a variadic macro is not possible in C99, which is true.
    My apologies.

    Leave a comment:


  • vippstar@gmail.com
    Guest replied
    Re: variadic macros

    On May 23, 1:18 am, Peter Nilsson <ai...@acay.com .auwrote:
    Christof Warlich <cwarl...@alcat el-lucent.dewrote:
    Christof Warlich schrieb:
    is there any way to access individual elements in
    the body of a variadic macro? I only found
    __VA_ARGS__, which always expands to the complete
    list.
    >
    Not in standard C99.
    6.10.3 p 5
    The identifier _ _VA_ARGS_ _ shall occur only in the replacement-list
    of a function-like macro that uses the ellipsis notation in the parameters..

    Leave a comment:


  • Peter Nilsson
    Guest replied
    Re: variadic macros

    Christof Warlich <cwarl...@alcat el-lucent.dewrote:
    Christof Warlich schrieb:
    is there any way to access individual elements in
    the body of a variadic macro? I only found
    __VA_ARGS__, which always expands to the complete
    list.
    Not in standard C99.
    It would already help if there would be a way to
    have something that expands to the number of
    arguments being passed to the variadic macro.
    There's no shortage on the wish list for standard C.
    However that doesn't mean that your actual problem
    doesn't have a simple solution.

    Perhaps you might like to mention the real problem.
    It may be solvable quite easily in standard C.

    --
    Peter

    Leave a comment:


  • Antoninus Twink
    Guest replied
    Re: variadic macros

    On 22 May 2008 at 10:29, Christof Warlich wrote:
    is there any way to access individual elements in the body
    of a variadic macro? I only found __VA_ARGS__, which always
    expands to the complete list.
    Twelve hours, and not a single language lawyer has come along to explain
    that you can't. That's because your question is about C99, and the
    luddite regulars in this group won't tolerate any discussion of C
    standards more recent than the fall of the Berlin Wall.

    Anyway, to answer your question, no there's no way in standard C...
    there's not even any way using gcc extensions. I don't know about MS or
    lcc extensions - maybe you can with them.

    To understand why the answer is no, think about how you'd go about
    finding out how many arguments were passed to your variadic function...
    now ponder doing that in a macro.

    The only purpose of variadic macros is to facilitate providing default
    arguments for calls to variadic functions, like the usual
    fprintf(stderr, __VA_ARGS__) example.

    Leave a comment:


  • Christof Warlich
    Guest replied
    Re: variadic macros

    It would already help if there would be a way to have something
    that expands to the number of arguments being passed to the variadic macro.


    Christof Warlich schrieb:
    Hi,
    >
    is there any way to access individual elements in the body
    of a variadic macro? I only found __VA_ARGS__, which always
    expands to the complete list.
    >
    Thanks for any help,
    >
    Christof

    Leave a comment:


  • Christof Warlich
    Guest started a topic variadic macros

    variadic macros

    Hi,

    is there any way to access individual elements in the body
    of a variadic macro? I only found __VA_ARGS__, which always
    expands to the complete list.

    Thanks for any help,

    Christof
Working...