• Help requested with P99-based macro to create Wayland listeners

    From Blue-Maned_Hawk@bluemanedhawk@invalid.invalid to comp.lang.c on Tue Apr 9 00:36:11 2024
    From Newsgroup: comp.lang.c

    This macro doesn't work and i don't know why. I've tried multiple
    different things to try to delay the expansion of _0MAKE_LISTENER and none
    of them have worked. I don't know if there's a more idiomatic way to do
    this. I've tried looking at the output from putting it through ‘cpp’ and that didn't work because it errored out before i could see what it
    expanded to.

    #define MAKE_LISTENER(object_type, ...) static const struct\ object_type##_listener object_type##_listener = { P99_SEQ(\
    _0MAKE_LISTENER, P99_SEQ((object_type), __VA_ARGS__)) }
    #define _0MAKE_LISTENER(x) _1MAKE_LISTENER (x, _2MAKE_LISTENER
    #define _1MAKE_LISTENER _3MAKE_LISTENER
    #define _2MAKE_LISTENER(y) y)
    #define _3MAKE_LISTENER _4MAKE_LISTENER
    #define _4MAKE_LISTENER(object_type, event_name) .event_name =\ callback_##object_type##_##event_name
    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    Like many 40-year-olds, these machines have more health issues than
    expected.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Tim Rentsch@tr.17687@z991.linuxsc.com to comp.lang.c on Tue Apr 9 09:22:46 2024
    From Newsgroup: comp.lang.c

    Blue-Maned_Hawk <bluemanedhawk@invalid.invalid> writes:

    This macro doesn't work and i don't know why. I've tried multiple
    different things to try to delay the expansion of _0MAKE_LISTENER and none
    of them have worked. I don't know if there's a more idiomatic way to do this. I've tried looking at the output from putting it through ?cpp? and that didn't work because it errored out before i could see what it
    expanded to.

    #define MAKE_LISTENER(object_type, ...) static const struct\ object_type##_listener object_type##_listener = { P99_SEQ(\
    _0MAKE_LISTENER, P99_SEQ((object_type), __VA_ARGS__)) }
    #define _0MAKE_LISTENER(x) _1MAKE_LISTENER (x, _2MAKE_LISTENER
    #define _1MAKE_LISTENER _3MAKE_LISTENER
    #define _2MAKE_LISTENER(y) y)
    #define _3MAKE_LISTENER _4MAKE_LISTENER
    #define _4MAKE_LISTENER(object_type, event_name) .event_name =\ callback_##object_type##_##event_name

    What is it that you want to accomplish?
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Blue-Maned_Hawk@bluemanedhawk@invalid.invalid to comp.lang.c on Tue Apr 9 18:17:45 2024
    From Newsgroup: comp.lang.c

    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to create Wayland listeners.
    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    Nothing's thoroughly disposed of until it's been through a digestive
    system.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Apr 9 21:59:12 2024
    From Newsgroup: comp.lang.c

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:
    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to create Wayland listeners.


    Assume, for the sake of argument, that no one knows or cares anything
    about Wayland or listeners.

    You are trying to use a set macros to expand to some code. Start by
    showing what code you want to get from examples of using your macros -
    then people can try to help get the macros right.


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Blue-Maned_Hawk@bluemanedhawk@invalid.invalid to comp.lang.c on Tue Apr 9 20:20:18 2024
    From Newsgroup: comp.lang.c

    David Brown wrote:

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:
    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to
    create Wayland listeners.


    Assume, for the sake of argument, that no one knows or cares anything
    about Wayland or listeners.

    <https://xkcd.com/1432/>

    You are trying to use a set macros to expand to some code. Start by
    showing what code you want to get from examples of using your macros -
    then people can try to help get the macros right.

    MAKE_LISTENER(wl_registry, global, global_remove);



    static const struct wl_registry_listener wl_registry_listener = { .global
    = callback_wl_registry_global, .global_remove = callback_wl_registry_global_remove };



    MAKE_LISTENER(xdg_wm_base, configure, close, configure_bounds, wm_capabilities);



    static const struct xdg_wm_base_listener xdg_wm_base_listener =
    { .configure = callback_xdg_wm_base_configure, .close = callback_xdg_wm_base_close, .configure_bounds = callback_xdg_wm_base_configure_bounds, .wm_capabilities = callback_xdg_wm_base_wm_capabilities };
    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    Eating carpets strictly prohibited!
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Wed Apr 10 02:49:03 2024
    From Newsgroup: comp.lang.c

    On 4/8/24 20:36, Blue-Maned_Hawk wrote:
    This macro doesn't work and i don't know why. I've tried multiple
    different things to try to delay the expansion of _0MAKE_LISTENER and none of them have worked. I don't know if there's a more idiomatic way to do this. I've tried looking at the output from putting it through ‘cpp’ and
    that didn't work because it errored out before i could see what it
    expanded to.

    #define MAKE_LISTENER(object_type, ...) static const struct\ object_type##_listener object_type##_listener = { P99_SEQ(\

    This isn't a C problem, or at least,not entirely a C problem. I'd
    thought that the P99 in your subject line might be a typo for C99, but I
    have no idea what P99_SEQ is. Wikipedia knows 9 different meanings for
    P99. Google gives me way too many hits from P99, I have no idea which
    one is relevant. You might need to take this up with someone who has
    some idea what P99 is.

    The basic technique for delaying expansion is as follows:

    #define STR(e) #e
    #define STRSTR(e) STR(e)

    and then replace WHATEVER with STRSTR(WHATEVER).

    There are, I understand, good reasons based upon how macro expansion
    works why this solution is necessary, but even when I was a lot younger
    I had trouble understanding those reasons. I generally had to rely upon
    trial and error to figure out the right way to use STRSTR().
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Apr 10 11:05:55 2024
    From Newsgroup: comp.lang.c

    On 09/04/2024 22:20, Blue-Maned_Hawk wrote:
    David Brown wrote:

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:
    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to
    create Wayland listeners.


    Assume, for the sake of argument, that no one knows or cares anything
    about Wayland or listeners.

    <https://xkcd.com/1432/>

    You are trying to use a set macros to expand to some code. Start by
    showing what code you want to get from examples of using your macros -
    then people can try to help get the macros right.

    MAKE_LISTENER(wl_registry, global, global_remove);



    static const struct wl_registry_listener wl_registry_listener = { .global
    = callback_wl_registry_global, .global_remove = callback_wl_registry_global_remove };

    #define _get_6th_arg(_1, _2, _3, _4, _5, _arg, ...) _arg
    #define _fe_0(_global, _call, ...)
    #define _fe_1(_global, _call, x) _call(_global, x)
    #define _fe_2(_global, _call, x, ...) _call(_global, x) _fe_1(_global,
    _call, __VA_ARGS__)
    #define _fe_3(_global, _call, x, ...) _call(_global, x) _fe_2(_global,
    _call, __VA_ARGS__)
    #define _fe_4(_global, _call, x, ...) _call(_global, x) _fe_3(_global,
    _call, __VA_ARGS__)
    #define expand_macro_for_each(_global, _macro, ...) \
    _get_6th_arg("ignored", __VA_ARGS__, \
    _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(_global, _macro, __VA_ARGS__)



    #define MAKE_LISTENER(object_type, ...) _make_listener(object_type, __VA_ARGS__)
    #define _listener_entry(_global, _field) , . _field = callback_ ##
    _global ## _ ## field
    #define _make_listener(object_type, first_field, ...) static const struct \
    object_type ## _listener object_type ## _listener = { \
    .first_field = callback_ ## object_type ## _ ## first_field \
    expand_macro_for_each(object_type, _listener_entry, __VA_ARGS__) \
    }



    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Blue-Maned_Hawk@bluemanedhawk@invalid.invalid to comp.lang.c on Wed Apr 10 13:57:48 2024
    From Newsgroup: comp.lang.c

    James Kuyper wrote:

    This isn't a C problem, or at least,not entirely a C problem. I'd
    thought that the P99 in your subject line might be a typo for C99, but I
    have no idea what P99_SEQ is. Wikipedia knows 9 different meanings for
    P99. Google gives me way too many hits from P99, I have no idea which
    one is relevant. You might need to take this up with someone who has
    some idea what P99 is.

    This is the P99 that i am referring to: <https:// gustedt.gitlabpages.inria.fr/p99/p99-html/index.html>.
    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    Indisputably a ring!
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Wed Apr 10 14:26:13 2024
    From Newsgroup: comp.lang.c

    David Brown <david.brown@hesbynett.no> writes:
    On 09/04/2024 22:20, Blue-Maned_Hawk wrote:
    David Brown wrote:

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:
    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to
    create Wayland listeners.


    Assume, for the sake of argument, that no one knows or cares anything
    about Wayland or listeners.

    <https://xkcd.com/1432/>

    You are trying to use a set macros to expand to some code. Start by
    showing what code you want to get from examples of using your macros -
    then people can try to help get the macros right.

    MAKE_LISTENER(wl_registry, global, global_remove);



    static const struct wl_registry_listener wl_registry_listener = { .global
    = callback_wl_registry_global, .global_remove =
    callback_wl_registry_global_remove };

    #define _get_6th_arg(_1, _2, _3, _4, _5, _arg, ...) _arg
    #define _fe_0(_global, _call, ...)
    #define _fe_1(_global, _call, x) _call(_global, x)
    #define _fe_2(_global, _call, x, ...) _call(_global, x) _fe_1(_global, >_call, __VA_ARGS__)
    #define _fe_3(_global, _call, x, ...) _call(_global, x) _fe_2(_global, >_call, __VA_ARGS__)
    #define _fe_4(_global, _call, x, ...) _call(_global, x) _fe_3(_global, >_call, __VA_ARGS__)
    #define expand_macro_for_each(_global, _macro, ...) \
    _get_6th_arg("ignored", __VA_ARGS__, \
    _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(_global, _macro, __VA_ARGS__)



    #define MAKE_LISTENER(object_type, ...) _make_listener(object_type, >__VA_ARGS__)
    #define _listener_entry(_global, _field) , . _field = callback_ ##
    _global ## _ ## field
    #define _make_listener(object_type, first_field, ...) static const struct \
    object_type ## _listener object_type ## _listener = { \
    .first_field = callback_ ## object_type ## _ ## first_field \
    expand_macro_for_each(object_type, _listener_entry, __VA_ARGS__) \
    }


    Frankly I'd reject that code in any code review request.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ben Bacarisse@ben.usenet@bsb.me.uk to comp.lang.c on Wed Apr 10 15:49:09 2024
    From Newsgroup: comp.lang.c

    David Brown <david.brown@hesbynett.no> writes:

    On 09/04/2024 22:20, Blue-Maned_Hawk wrote:
    David Brown wrote:

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:
    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to
    create Wayland listeners.


    Assume, for the sake of argument, that no one knows or cares anything
    about Wayland or listeners.
    <https://xkcd.com/1432/>

    You are trying to use a set macros to expand to some code. Start by
    showing what code you want to get from examples of using your macros -
    then people can try to help get the macros right.
    MAKE_LISTENER(wl_registry, global, global_remove);

    static const struct wl_registry_listener wl_registry_listener = { .global
    = callback_wl_registry_global, .global_remove =
    callback_wl_registry_global_remove };

    #define _get_6th_arg(_1, _2, _3, _4, _5, _arg, ...) _arg
    #define _fe_0(_global, _call, ...)
    #define _fe_1(_global, _call, x) _call(_global, x)
    #define _fe_2(_global, _call, x, ...) _call(_global, x) _fe_1(_global,
    _call, __VA_ARGS__)
    #define _fe_3(_global, _call, x, ...) _call(_global, x) _fe_2(_global,
    _call, __VA_ARGS__)
    #define _fe_4(_global, _call, x, ...) _call(_global, x) _fe_3(_global,
    _call, __VA_ARGS__)
    #define expand_macro_for_each(_global, _macro, ...) \
    _get_6th_arg("ignored", __VA_ARGS__, \
    _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(_global, _macro, __VA_ARGS__)


    #define MAKE_LISTENER(object_type, ...) _make_listener(object_type,
    __VA_ARGS__)
    #define _listener_entry(_global, _field) , . _field = callback_ ## _global
    ## _ ## field

    s/field/_field/

    #define _make_listener(object_type, first_field, ...) static const struct \
    object_type ## _listener object_type ## _listener = { \
    .first_field = callback_ ## object_type ## _ ## first_field \
    expand_macro_for_each(object_type, _listener_entry, __VA_ARGS__) \
    }
    --
    Ben.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Apr 10 16:54:11 2024
    From Newsgroup: comp.lang.c

    On 10/04/2024 16:26, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 09/04/2024 22:20, Blue-Maned_Hawk wrote:
    David Brown wrote:

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:
    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to
    create Wayland listeners.


    Assume, for the sake of argument, that no one knows or cares anything
    about Wayland or listeners.

    <https://xkcd.com/1432/>

    You are trying to use a set macros to expand to some code. Start by
    showing what code you want to get from examples of using your macros - >>>> then people can try to help get the macros right.

    MAKE_LISTENER(wl_registry, global, global_remove);



    static const struct wl_registry_listener wl_registry_listener = { .global >>> = callback_wl_registry_global, .global_remove =
    callback_wl_registry_global_remove };

    #define _get_6th_arg(_1, _2, _3, _4, _5, _arg, ...) _arg
    #define _fe_0(_global, _call, ...)
    #define _fe_1(_global, _call, x) _call(_global, x)
    #define _fe_2(_global, _call, x, ...) _call(_global, x) _fe_1(_global,
    _call, __VA_ARGS__)
    #define _fe_3(_global, _call, x, ...) _call(_global, x) _fe_2(_global,
    _call, __VA_ARGS__)
    #define _fe_4(_global, _call, x, ...) _call(_global, x) _fe_3(_global,
    _call, __VA_ARGS__)
    #define expand_macro_for_each(_global, _macro, ...) \
    _get_6th_arg("ignored", __VA_ARGS__, \
    _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(_global, _macro, __VA_ARGS__)



    #define MAKE_LISTENER(object_type, ...) _make_listener(object_type,
    __VA_ARGS__)
    #define _listener_entry(_global, _field) , . _field = callback_ ##
    _global ## _ ## field
    #define _make_listener(object_type, first_field, ...) static const struct \ >> object_type ## _listener object_type ## _listener = { \
    .first_field = callback_ ## object_type ## _ ## first_field \
    expand_macro_for_each(object_type, _listener_entry, __VA_ARGS__) \
    }


    Frankly I'd reject that code in any code review request.

    I normally like code to be so clear that comments about how it works are unnecessary. But I think for something like this, a few comments would
    be helpful!

    When doing this kind of messing around with advanced preprocessing, it's useful to have a set of re-usable macros that can be written and
    documented once. The "expand_macro_for_each" macro and its parts is
    partly there, and once that is in place and accepted, the rest is a lot smaller step to accept in a code review.

    But this is code to help the OP get his macro generations working.
    Whether he likes it, rejects it, or uses it for inspiration is up to him.


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Tim Rentsch@tr.17687@z991.linuxsc.com to comp.lang.c on Wed Apr 10 09:03:43 2024
    From Newsgroup: comp.lang.c

    Blue-Maned_Hawk <bluemanedhawk@invalid.invalid> writes:

    [request for example]

    MAKE_LISTENER(wl_registry, global, global_remove);

    ?

    static const struct wl_registry_listener wl_registry_listener = {
    .global = callback_wl_registry_global,
    .global_remove = callback_wl_registry_global_remove
    };

    ?

    MAKE_LISTENER(xdg_wm_base, configure, close, configure_bounds, wm_capabilities);

    ?

    static const struct xdg_wm_base_listener xdg_wm_base_listener = {
    .configure = callback_xdg_wm_base_configure,
    .close = callback_xdg_wm_base_close,
    .configure_bounds = callback_xdg_wm_base_configure_bounds,
    .wm_capabilities = callback_xdg_wm_base_wm_capabilities
    };

    I think it isn't too hard to write a macro to do what you
    want. I'm pretty sure it's possible to define such a macro
    using the P99 macros to do the iteration, but I don't see
    an easy way to do it. If I were in need of such a macro,
    probably I would ignore the P99 macros and just build a
    simpler solution that works for the task at hand.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Tim Rentsch@tr.17687@z991.linuxsc.com to comp.lang.c on Wed Apr 10 09:05:48 2024
    From Newsgroup: comp.lang.c

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:

    On 4/8/24 20:36, Blue-Maned_Hawk wrote:

    This macro doesn't work and i don't know why. I've tried multiple
    different things to try to delay the expansion of _0MAKE_LISTENER and none >> of them have worked. I don't know if there's a more idiomatic way to do
    this. I've tried looking at the output from putting it through ?cpp? and >> that didn't work because it errored out before i could see what it
    expanded to.

    #define MAKE_LISTENER(object_type, ...) static const struct\
    object_type##_listener object_type##_listener = { P99_SEQ(\

    This isn't a C problem, or at least,not entirely a C problem. I'd
    thought that the P99 in your subject line might be a typo for C99, but I
    have no idea what P99_SEQ is. Wikipedia knows 9 different meanings for
    P99. [...]

    Someone might tell James that it is entirely a C problem for
    anyone with enough sense to search for P99_SEQ rather than
    just P99.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Tim Rentsch@tr.17687@z991.linuxsc.com to comp.lang.c on Wed Apr 10 09:08:41 2024
    From Newsgroup: comp.lang.c

    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

    David Brown <david.brown@hesbynett.no> writes:

    On 09/04/2024 22:20, Blue-Maned_Hawk wrote:

    David Brown wrote:

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:

    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to
    create Wayland listeners.

    Assume, for the sake of argument, that no one knows or cares anything
    about Wayland or listeners.

    <https://xkcd.com/1432/>

    You are trying to use a set macros to expand to some code. Start by
    showing what code you want to get from examples of using your macros - >>>> then people can try to help get the macros right.

    MAKE_LISTENER(wl_registry, global, global_remove);
    ?
    static const struct wl_registry_listener wl_registry_listener = { .global >>> = callback_wl_registry_global, .global_remove =
    callback_wl_registry_global_remove };

    #define _get_6th_arg(_1, _2, _3, _4, _5, _arg, ...) _arg
    #define _fe_0(_global, _call, ...)
    #define _fe_1(_global, _call, x) _call(_global, x)
    #define _fe_2(_global, _call, x, ...) _call(_global, x) _fe_1(_global,
    _call, __VA_ARGS__)
    #define _fe_3(_global, _call, x, ...) _call(_global, x) _fe_2(_global,
    _call, __VA_ARGS__)
    #define _fe_4(_global, _call, x, ...) _call(_global, x) _fe_3(_global,
    _call, __VA_ARGS__)
    #define expand_macro_for_each(_global, _macro, ...) \
    _get_6th_arg("ignored", __VA_ARGS__, \
    _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(_global, _macro, __VA_ARGS__)


    #define MAKE_LISTENER(object_type, ...) _make_listener(object_type,
    __VA_ARGS__)
    #define _listener_entry(_global, _field) , . _field = callback_ ## _global >> ## _ ## field

    s/field/_field/

    The bigger problem is that the proposed solution doesn't work
    for more than five fields. Clearly the idea is to define a
    macro that works for an unlimited number of fields, or at least
    a fairly large number.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Apr 10 18:40:44 2024
    From Newsgroup: comp.lang.c

    On 10/04/2024 18:08, Tim Rentsch wrote:
    Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

    David Brown <david.brown@hesbynett.no> writes:

    On 09/04/2024 22:20, Blue-Maned_Hawk wrote:

    David Brown wrote:

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:

    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to
    create Wayland listeners.

    Assume, for the sake of argument, that no one knows or cares anything >>>>> about Wayland or listeners.

    <https://xkcd.com/1432/>

    You are trying to use a set macros to expand to some code. Start by >>>>> showing what code you want to get from examples of using your macros - >>>>> then people can try to help get the macros right.

    MAKE_LISTENER(wl_registry, global, global_remove);
    ?
    static const struct wl_registry_listener wl_registry_listener = { .global >>>> = callback_wl_registry_global, .global_remove =
    callback_wl_registry_global_remove };

    #define _get_6th_arg(_1, _2, _3, _4, _5, _arg, ...) _arg
    #define _fe_0(_global, _call, ...)
    #define _fe_1(_global, _call, x) _call(_global, x)
    #define _fe_2(_global, _call, x, ...) _call(_global, x) _fe_1(_global,
    _call, __VA_ARGS__)
    #define _fe_3(_global, _call, x, ...) _call(_global, x) _fe_2(_global,
    _call, __VA_ARGS__)
    #define _fe_4(_global, _call, x, ...) _call(_global, x) _fe_3(_global,
    _call, __VA_ARGS__)
    #define expand_macro_for_each(_global, _macro, ...) \
    _get_6th_arg("ignored", __VA_ARGS__, \
    _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(_global, _macro, __VA_ARGS__)


    #define MAKE_LISTENER(object_type, ...) _make_listener(object_type,
    __VA_ARGS__)
    #define _listener_entry(_global, _field) , . _field = callback_ ## _global >>> ## _ ## field

    s/field/_field/

    Correct - sorry about the typo.


    The bigger problem is that the proposed solution doesn't work
    for more than five fields.

    I have no idea how many fields the OP might want, in order to judge if
    that is a big problem or not. But I believe he'll be able to figure out
    how to extend it as necessary.

    Clearly the idea is to define a
    macro that works for an unlimited number of fields, or at least
    a fairly large number.

    If you have a way to extend it to unlimited numbers of fields, I would
    love to know - as far as I am aware, the lack of recursion or loops in
    the C pre-processor means that you always have to be limited like this.
    It is, I think, possible to make sequence of macros like this that split
    lists in half, so that you only need O(log N) submacros in order to
    support up to N arguments. That would let you get to the level of very
    large numbers pretty quickly.


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Apr 10 11:44:58 2024
    From Newsgroup: comp.lang.c

    On 4/10/2024 7:54 AM, David Brown wrote:
    On 10/04/2024 16:26, Scott Lurndal wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 09/04/2024 22:20, Blue-Maned_Hawk wrote:
    David Brown wrote:

    On 09/04/2024 20:17, Blue-Maned_Hawk wrote:
    Tim Rentsch wrote:

    What is it that you want to accomplish?

    As i stated in the subject line, i am trying to create a macro to
    create Wayland listeners.


    Assume, for the sake of argument, that no one knows or cares anything >>>>> about Wayland or listeners.

    <https://xkcd.com/1432/>

    You are trying to use a set macros to expand to some code.  Start by >>>>> showing what code you want to get from examples of using your macros - >>>>> then people can try to help get the macros right.

    MAKE_LISTENER(wl_registry, global, global_remove);



    static const struct wl_registry_listener wl_registry_listener = {
    .global
    = callback_wl_registry_global, .global_remove =
    callback_wl_registry_global_remove };

    #define _get_6th_arg(_1, _2, _3, _4, _5, _arg, ...) _arg
    #define _fe_0(_global, _call, ...)
    #define _fe_1(_global, _call, x) _call(_global, x)
    #define _fe_2(_global, _call, x, ...) _call(_global, x) _fe_1(_global,
    _call, __VA_ARGS__)
    #define _fe_3(_global, _call, x, ...) _call(_global, x) _fe_2(_global,
    _call, __VA_ARGS__)
    #define _fe_4(_global, _call, x, ...) _call(_global, x) _fe_3(_global,
    _call, __VA_ARGS__)
    #define expand_macro_for_each(_global, _macro, ...) \
         _get_6th_arg("ignored", __VA_ARGS__, \
         _fe_4, _fe_3, _fe_2, _fe_1, _fe_0)(_global, _macro, __VA_ARGS__) >>>


    #define MAKE_LISTENER(object_type, ...) _make_listener(object_type,
    __VA_ARGS__)
    #define _listener_entry(_global, _field) , . _field = callback_ ##
    _global ## _ ## field
    #define _make_listener(object_type, first_field, ...) static const
    struct \
         object_type ## _listener object_type ## _listener = { \
         .first_field = callback_ ## object_type ## _ ## first_field \
         expand_macro_for_each(object_type, _listener_entry, __VA_ARGS__) \ >>>      }


    Frankly I'd reject that code in any code review request.

    I normally like code to be so clear that comments about how it works are unnecessary.  But I think for something like this, a few comments would
    be helpful!

    When doing this kind of messing around with advanced preprocessing, it's useful to have a set of re-usable macros that can be written and
    documented once.  The "expand_macro_for_each" macro and its parts is
    partly there, and once that is in place and accepted, the rest is a lot smaller step to accept in a code review.

    But this is code to help the OP get his macro generations working.
    Whether he likes it, rejects it, or uses it for inspiration is up to him.



    The OP needs a deep read of the chaos lib:

    https://github.com/rofl0r/chaos-pp

    Might help... ? ;^)
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Apr 10 21:29:08 2024
    From Newsgroup: comp.lang.c

    On 10/04/2024 20:44, Chris M. Thomasson wrote:


    The OP needs a deep read of the chaos lib:

    https://github.com/rofl0r/chaos-pp

    Might help... ? ;^)

    I think more people would respond to your posts if you actually included content, rather than just random links and smilies.

    Assume that no one here will ever click on a youtube link - then you
    clearly don't need to post them.

    Assume that no one will click on any random webpage link, or even to
    known sites like github, unless there's plenty of information in the
    posts to make it clear why the linked software is relevant.

    You do a lot of interesting programming, have interesting ideas, and are energetic about sharing them and helping people. That's all great. But
    you could do so much better at getting your thoughts across.

    So if you don't mind - please try again. Tell us what "the chaos lib"
    is. Say why it is exciting. Explain how it might help the OP, or
    anyone else.

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From bart@bc@freeuk.com to comp.lang.c on Wed Apr 10 20:39:50 2024
    From Newsgroup: comp.lang.c

    On 10/04/2024 20:29, David Brown wrote:
    On 10/04/2024 20:44, Chris M. Thomasson wrote:


    The OP needs a deep read of the chaos lib:

    https://github.com/rofl0r/chaos-pp

    Might help... ? ;^)

    I think more people would respond to your posts if you actually included content, rather than just random links and smilies.

    Assume that no one here will ever click on a youtube link - then you
    clearly don't need to post them.

    Assume that no one will click on any random webpage link, or even to
    known sites like github, unless there's plenty of information in the
    posts to make it clear why the linked software is relevant.

    You do a lot of interesting programming, have interesting ideas, and are energetic about sharing them and helping people.  That's all great.  But you could do so much better at getting your thoughts across.

    So if you don't mind - please try again.  Tell us what "the chaos lib" is.  Say why it is exciting.  Explain how it might help the OP, or
    anyone else.


    I spent a few minutes looking at the link. I didn't learn anything. Just
    loads of raw XML, XSL and HTML files. No explanation anywhere of what is
    what.

    The only two files in plaintext were LICENCE and README, both showing
    licence info.

    I've seen lots of github projects and this is poor. But then, I don't
    know if this was ever meant to be seen like this; maybe it is just data referenced by another project. Or you need special tools to view.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Apr 10 13:40:59 2024
    From Newsgroup: comp.lang.c

    On 4/10/2024 12:29 PM, David Brown wrote:
    On 10/04/2024 20:44, Chris M. Thomasson wrote:


    The OP needs a deep read of the chaos lib:

    https://github.com/rofl0r/chaos-pp

    Might help... ? ;^)

    I think more people would respond to your posts if you actually included content, rather than just random links and smilies.

    Assume that no one here will ever click on a youtube link - then you
    clearly don't need to post them.

    Assume that no one will click on any random webpage link, or even to
    known sites like github, unless there's plenty of information in the
    posts to make it clear why the linked software is relevant.

    You do a lot of interesting programming, have interesting ideas, and are energetic about sharing them and helping people.  That's all great.  But you could do so much better at getting your thoughts across.

    So if you don't mind - please try again.  Tell us what "the chaos lib" is.  Say why it is exciting.  Explain how it might help the OP, or
    anyone else.


    It is a preprocessor library with a lot of interesting fancy macros.
    Iirc, the chaos preprocessor library is used in Boost.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Apr 10 13:48:51 2024
    From Newsgroup: comp.lang.c

    On 4/10/2024 1:40 PM, Chris M. Thomasson wrote:
    On 4/10/2024 12:29 PM, David Brown wrote:
    On 10/04/2024 20:44, Chris M. Thomasson wrote:


    The OP needs a deep read of the chaos lib:

    https://github.com/rofl0r/chaos-pp

    Might help... ? ;^)

    I think more people would respond to your posts if you actually
    included content, rather than just random links and smilies.

    Assume that no one here will ever click on a youtube link - then you
    clearly don't need to post them.

    Assume that no one will click on any random webpage link, or even to
    known sites like github, unless there's plenty of information in the
    posts to make it clear why the linked software is relevant.

    You do a lot of interesting programming, have interesting ideas, and
    are energetic about sharing them and helping people.  That's all
    great.  But you could do so much better at getting your thoughts across.

    So if you don't mind - please try again.  Tell us what "the chaos lib"
    is.  Say why it is exciting.  Explain how it might help the OP, or
    anyone else.


    It is a preprocessor library with a lot of interesting fancy macros.
    Iirc, the chaos preprocessor library is used in Boost.

    Yeah. Sigh. However, you can read some of the docs. A screenshot from my
    end dealing with preprocessor arrays:

    https://i.ibb.co/1rhBjCf/image.png

    Another one dealing with so-called "active arguments":

    https://i.ibb.co/vPTvdnP/image.png

    I think Boost used to use or is based on chaos-pp wrt BOOST_PP_*

    https://i.ibb.co/vPTvdnP/image.png


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Apr 10 13:55:17 2024
    From Newsgroup: comp.lang.c

    On 4/10/2024 12:39 PM, bart wrote:
    On 10/04/2024 20:29, David Brown wrote:
    On 10/04/2024 20:44, Chris M. Thomasson wrote:


    The OP needs a deep read of the chaos lib:

    https://github.com/rofl0r/chaos-pp
    [...]
    I've seen lots of github projects and this is poor. But then, I don't
    know if this was ever meant to be seen like this; maybe it is just data referenced by another project. Or you need special tools to view.

    I accidentally posted this followup to David Brown. Sorry!

    Yeah. Sigh. However, you can read some of the docs. A screenshot from my
    end dealing with preprocessor arrays:

    https://i.ibb.co/1rhBjCf/image.png

    Another one dealing with so-called "active arguments":

    https://i.ibb.co/vPTvdnP/image.png

    I think Boost used to use or is based on chaos-pp wrt BOOST_PP_*

    https://i.ibb.co/vPTvdnP/image.png


    Also, remember this old post Bart?

    https://groups.google.com/g/comp.lang.c/c/LkaB9kxIzTE/m/VypqT2VRBgAJ

    :^)

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Lawrence D'Oliveiro@ldo@nz.invalid to comp.lang.c on Thu Apr 11 00:57:17 2024
    From Newsgroup: comp.lang.c

    On Wed, 10 Apr 2024 02:49:03 -0400, James Kuyper wrote:

    There are, I understand, good reasons based upon how macro expansion
    works why this solution is necessary, but even when I was a lot younger
    I had trouble understanding those reasons.

    String-based macros are like that. That’s why Lisp-style macros are a
    better idea.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Tim Rentsch@tr.17687@z991.linuxsc.com to comp.lang.c on Wed Apr 10 19:56:36 2024
    From Newsgroup: comp.lang.c

    Blue-Maned_Hawk <bluemanedhawk@invalid.invalid> writes:

    This macro doesn't work and i don't know why. I've tried multiple
    different things to try to delay the expansion of _0MAKE_LISTENER
    and none of them have worked. I don't know if there's a more
    idiomatic way to do this. I've tried looking at the output from
    putting it through ?cpp? and that didn't work because it errored
    out before i could see what it expanded to.

    #define MAKE_LISTENER(object_type, ...) static const struct\ object_type##_listener object_type##_listener = { P99_SEQ(\
    _0MAKE_LISTENER, P99_SEQ((object_type), __VA_ARGS__)) }
    #define _0MAKE_LISTENER(x) _1MAKE_LISTENER (x, _2MAKE_LISTENER
    #define _1MAKE_LISTENER _3MAKE_LISTENER
    #define _2MAKE_LISTENER(y) y)
    #define _3MAKE_LISTENER _4MAKE_LISTENER
    #define _4MAKE_LISTENER(object_type, event_name) .event_name =\ callback_##object_type##_##event_name


    After a lot of trial and error, I came up with the code below.
    Probably it could be simplified, but I was happy just to get
    it to work.


    #include "p99.h"

    #define static_const_LISTENER( kind, ... ) \
    static const PLAIN_LISTENER( kind, __VA_ARGS__ )

    #define PLAIN_LISTENER( kind, ... ) \
    struct LISTENER_TAG_NAME( kind ) LISTENER_TAG_NAME( kind ) = { \
    LISTENER_FIELDS( kind, __VA_ARGS__ ) \
    }

    #define LISTENER_TAG_NAME( kind ) JOIN2( kind, _listener )

    #define LISTENER_FIELDS( kind, ... ) \
    P99_SEQ( AS_IS, \
    P99_SEQ( ONE_LISTENER_FIELD_2 AS_IS, \
    P99_SEQ( ONE_LISTENER_FIELD, P99_SEQ( (kind), __VA_ARGS__ ) ) \
    ) \
    )

    #define ONE_LISTENER_FIELD( a ) ONE_LISTENER_FIELDx( a )
    #define ONE_LISTENER_FIELDx( a ) SINGLES_INTO_PAIR( a )

    #define SINGLES_INTO_PAIR( a_b ) ( ONE_COMMA_TWO a_b )
    #define ONE_COMMA_TWO( a ) a, AS_IS

    #define AS_IS( a ) a

    #define ONE_LISTENER_FIELD_2( a, b ) ONE_LISTENER_FIELD_2x( a, b )
    #define ONE_LISTENER_FIELD_2x( kind, field ) \
    .field = callback_ ## kind ## _ ## field

    #define JOIN2( a, b ) JOIN2x( a, b )
    #define JOIN2x( a, b ) a ## b

    static_const_LISTENER( wl_registry, global, global_remove ); static_const_LISTENER(
    xdg_wm_base,
    configure, close, configure_bounds, wm_capabilities
    );
    --- Synchronet 3.20a-Linux NewsLink 1.114