linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
To: Paul Gortmaker <paul.gortmaker@windriver.com>,
	Jiri Slaby <jslaby@suse.cz>, Ingo Molnar <mingo@redhat.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	"H. Peter Anvin" <hpa@zytor.com>, Michal Marek <mmarek@suse.cz>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 1/2] linux/kconfig.h: generalize IS_ENABLED logic
Date: Tue,  6 Oct 2015 23:05:42 +0200	[thread overview]
Message-ID: <1444165543-2209-1-git-send-email-linux@rasmusvillemoes.dk> (raw)
In-Reply-To: <5613F3DE.4010406@suse.cz>

It's not hard to generalize the macro magic used to build the
IS_ENABLED macro and friends to produce a few other potentially useful
macros:

CHOOSE_EXPR(CONFIG_FOO, expr): if CONFIG_FOO is set expands to
expr, otherwise expands to nothing.

CHOOSE_EXPR(CONFIG_FOO, expr1, expr2): if CONFIG_FOO is set,
expands to expr1, otherwise expands to expr2.

While the latter is roughly the same as
__builtin_choose_expr(IS_ENABLED(CONFIG_FOO), expr1, expr2), the macro
version has the advantage that expr1 and expr2 may be string literals,
and they would preserve their ability to be concatenated with other
string literals. For example, this little snippet

#ifdef CONFIG_X86_64
        "     x86-tsc:   TSC cycle counter\n"
#endif

from kernel/trace/trace.c (which is surrounded by other string
literals) could be written as

  CHOOSE_EXPR(CONFIG_X86_64, "     x86-tsc:   TSC cycle counter\n")

We're also not really restricted to expressions in the C sense; the
only limitation I can see is that they cannot contain unparenthesized
commas. (Obviously, if one starts getting too creative, readability
will suffer rather than increase.)

Similarly, we can define helpers for conditional struct members and
their associated initializers. It would probably take some time to get
used to reading, to pick another random example,

struct task_struct {
   ...
   COND_DECLARATION(CONFIG_KASAN, unsigned int kasan_depth)
   ...
}

#define INIT_KASAN(tsk) COND_INITIALIZER(CONFIG_KASAN, .kasan_depth = 1)

[and I'm certainly not proposing any mass conversion], but I think it
might be nice to avoid lots of short #ifdef/#else/#endif sections. The
above would replace 3 and 5 lines, respectively. Also, git grep'ing
for CONFIG_KASAN currently just reveals that _something_ in sched.h
and init_task.h depends on it; with the above, one could at least
deduce that it's guarding a certain member of some struct.

Namewise, I think CHOOSE_EXPR is appropriate because of its similarity
to __builtin_choose_expr, but I'm not sure about the COND_* ones. Feel
free to suggest better names, and/or to flame this idea to death.

Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
---
 include/linux/kconfig.h | 75 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
index b33c7797eb57..ac209814b111 100644
--- a/include/linux/kconfig.h
+++ b/include/linux/kconfig.h
@@ -51,4 +51,79 @@
 #define IS_ENABLED(option) \
 	(IS_BUILTIN(option) || IS_MODULE(option))
 
+/*
+ * CHOOSE_EXPR, COND_DECLARATION and COND_INITIALIZER only work for
+ * boolean config options.
+ *
+ * CHOOSE_EXPR(CONFIG_FOO, expr): if CONFIG_FOO is set expands to
+ * expr, otherwise expands to nothing.
+ *
+ * CHOOSE_EXPR(CONFIG_FOO, expr1, expr2): if CONFIG_FOO is set,
+ * expands to expr1, otherwise expands to expr2.
+ *
+ * COND_DECLARATION(CONFIG_FOO, decl): if CONFIG_FOO is set, expands to
+ *
+ *   decl;
+ *
+ * (a semicolon should not be part of decl), otherwise expands to
+ * nothing.
+ *
+ * COND_INITIALIZER(CONFIG_FOO, init): if CONFIG_FOO is set, expands to
+ *
+ *   init,
+ *
+ * otherwise expands to nothing.
+ *
+ * CHOOSE_EXPR(CONFIG_FOO, expr1, expr2) is roughly equivalent to
+ * __builtin_choose_expr(IS_ENABLED(CONFIG_FOO), expr1,
+ * expr2). However, since the expansion is done by the preprocessor,
+ * expr1 and expr2 can be string literals which can then participate
+ * in string concatenation. Also, we're not really limited to
+ * expressions, and can choose to expand to nothing (this is also used
+ * internally by the COND_* macros). The only limitation is that expr1
+ * and expr2 cannot contain unparenthesized commas.
+ *
+ * COND_DECLARATION can, for example, be used inside a struct
+ * declaration to eliminate a #ifdef/#endif pair. This would look
+ * something like
+ *
+ * struct foo {
+ *     int a;
+ *     COND_DECLARATION(CONFIG_FOO_DEBUG, int b)
+ *     int c;
+ * };
+ *
+ * COND_INITIALIZER is the companion for initializing such
+ * conditionally defined members, again for eliminating the bracketing
+ * #ifdef/#endif pair.
+ *
+ * struct foo f = {
+ *     .a = 1,
+ *     COND_INITIALIZER(CONFIG_FOO_DEBUG, .b = 2)
+ *     .c = 3
+ * };
+ *
+ * This is mostly useful when only a single or a few members would be
+ * protected by the #ifdef/#endif. One advantage of the COND_* macros
+ * is that git grep'ing for CONFIG_FOO_DEBUG reveals more information
+ * (above, we would see that it protects the "b" member of some
+ * struct).
+ */
+
+#define _COMMA ,
+#define _COND_PUNCTUATION_0(p)
+#define _COND_PUNCTUATION_1(p) p
+
+#define CHOOSE_EXPR(cfg, expr, ...) _CHOOSE_EXPR(cfg, expr, ##__VA_ARGS__, /* empty defalt arg */)
+#define _CHOOSE_EXPR(cfg, expr, def, ...) __CHOOSE_EXPR(__ARG_PLACEHOLDER_##cfg, expr, def)
+#define __CHOOSE_EXPR(arg1_or_junk, expr, def) ___CHOOSE_EXPR(arg1_or_junk expr, def)
+#define ___CHOOSE_EXPR(__ignored, expr, ...) expr
+
+#define COND_DECLARATION(cfg, decl) _COND_DECLARATION(cfg, decl, CHOOSE_EXPR(cfg, 1, 0))
+#define _COND_DECLARATION(cfg, decl, sfx) __COND_DECLARATION(cfg, decl, sfx)
+#define __COND_DECLARATION(cfg, decl, sfx) CHOOSE_EXPR(cfg, decl) _COND_PUNCTUATION_##sfx(;)
+#define COND_INITIALIZER(cfg, init) _COND_INITIALIZER(cfg, init, CHOOSE_EXPR(cfg, 1, 0))
+#define _COND_INITIALIZER(cfg, init, sfx) __COND_INITIALIZER(cfg, init, sfx)
+#define __COND_INITIALIZER(cfg, init, sfx) CHOOSE_EXPR(cfg, init) _COND_PUNCTUATION_##sfx(_COMMA)
+
 #endif /* __LINUX_KCONFIG_H */
-- 
2.1.3


  reply	other threads:[~2015-10-06 21:06 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-06 12:29 [PATCH 1/2] x86: dumpstack, use pr_cont Jiri Slaby
2015-10-06 12:29 ` [PATCH 2/2] x86: text_poke, check if text_mutex is held Jiri Slaby
2015-10-06 16:00 ` [PATCH 1/2] x86: dumpstack, use pr_cont Rasmus Villemoes
2015-10-06 16:16   ` Jiri Slaby
2015-10-06 21:05     ` Rasmus Villemoes [this message]
2015-10-06 21:05       ` [PATCH 2/2] x86: dumpstack: eliminate some #ifdefs Rasmus Villemoes
2015-10-07  7:03         ` Ingo Molnar
2016-03-26 20:40         ` [PATCH] x86: dumpstack: combine some printks Rasmus Villemoes
2016-04-01  6:37           ` [tip:x86/debug] x86/dumpstack: Combine some printk()s tip-bot for Rasmus Villemoes
2015-10-07  6:57       ` [PATCH 1/2] linux/kconfig.h: generalize IS_ENABLED logic Ingo Molnar
2015-10-07  8:15       ` Michal Marek
2015-10-07 21:33         ` Rasmus Villemoes
2015-10-08 11:40           ` Michal Marek
2015-11-16  8:00       ` using IS_ENABLED(CONFIG_xyz) effectively Vineet Gupta
2015-11-16  8:28         ` Geert Uytterhoeven
2015-11-16  8:35           ` Vineet Gupta
2015-11-16  8:52             ` Arnd Bergmann
2015-11-16 10:03               ` Vineet Gupta

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1444165543-2209-1-git-send-email-linux@rasmusvillemoes.dk \
    --to=linux@rasmusvillemoes.dk \
    --cc=akpm@linux-foundation.org \
    --cc=hpa@zytor.com \
    --cc=jslaby@suse.cz \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=mmarek@suse.cz \
    --cc=paul.gortmaker@windriver.com \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).