Path: csiph.com!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Help requested with P99-based macro to create Wayland listeners Date: Wed, 10 Apr 2024 19:56:36 -0700 Organization: A noiseless patient Spider Lines: 64 Message-ID: <864jc81uaj.fsf@linuxsc.com> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Date: Thu, 11 Apr 2024 04:56:37 +0200 (CEST) Injection-Info: dont-email.me; posting-host="4fc11677c226a0b0f8fa3f2c2bcf5112"; logging-data="1540443"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Rcy6rPZVjw8TDuLRaDBqgm+d1/crF44U=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:TBlbyMF5WFzpeDO5oJ2KW75kFUk= sha1:DF1s9H9jXqESy/TV6SxwDL3GU0g= Xref: csiph.com comp.lang.c:384279 Blue-Maned_Hawk 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 );