]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/options: add a 'data' parameter to options
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Thu, 23 Apr 2026 08:10:31 +0000 (10:10 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Thu, 23 Apr 2026 09:13:07 +0000 (11:13 +0200)
This mirrors a similar field in Verb. In some cases it convenient
to pass a fixed value to the parser.

src/shared/options.h
src/test/test-options.c

index cd9f64fd4949af655367a5356d9edf9ad426f97e..974c21d16a692473b7b6c739d738952364decb35 100644 (file)
@@ -19,10 +19,11 @@ typedef struct Option {
         char short_code;
         const char *long_code;
         const char *metavar;
+        uintptr_t data;
         const char *help;
 } Option;
 
-#define _OPTION(counter, fl, sc, lc, mv, h)                             \
+#define _OPTION(counter, fl, sc, lc, mv, d, h)                          \
         _section_("SYSTEMD_OPTIONS")                                    \
         _alignptr_                                                      \
         _used_                                                          \
@@ -35,6 +36,7 @@ typedef struct Option {
                 .short_code = sc,                                       \
                 .long_code = lc,                                        \
                 .metavar = mv,                                          \
+                .data = d,                                              \
                 .help = h,                                              \
         };                                                              \
         case (0x100 + counter)
@@ -43,14 +45,17 @@ typedef struct Option {
  * The define is structured as 'case' so that it can be followed by ':' and indented appropriately.
  */
 #define OPTION_GROUP(gr)                                                \
-        _OPTION(__COUNTER__, OPTION_GROUP_MARKER, /* sc= */ 0, /* lc= */ gr, /* mv= */ NULL, /* h= */ NULL)
+        _OPTION(__COUNTER__, OPTION_GROUP_MARKER, /* sc= */ 0, /* lc= */ gr, /* mv= */ NULL, /* d= */ 0u, /* h= */ NULL)
 
-#define OPTION_FULL(fl, sc, lc, mv, h) _OPTION(__COUNTER__, fl, sc, lc, mv, h)
+#define OPTION_FULL_DATA(fl, sc, lc, mv, d, h) _OPTION(__COUNTER__, fl, sc, lc, mv, d, h)
+#define OPTION_FULL(fl, sc, lc, mv, h) OPTION_FULL_DATA(fl, sc, lc, mv, /* d= */ 0u, h)
 #define OPTION(sc, lc, mv, h) OPTION_FULL(/* fl= */ 0, sc, lc, mv, h)
 #define OPTION_LONG(lc, mv, h) OPTION(/* sc= */ 0, lc, mv, h)
 #define OPTION_LONG_FLAGS(fl, lc, mv, h) OPTION_FULL(fl, /* sc= */ 0, lc, mv, h)
+#define OPTION_LONG_DATA(lc, mv, d, h) OPTION_FULL_DATA(/* fl= */ 0, /* sc= */ 0, lc, mv, d, h)
 #define OPTION_SHORT(sc, mv, h) OPTION(sc, /* lc= */ NULL, mv, h)
 #define OPTION_SHORT_FLAGS(fl, sc, mv, h) OPTION_FULL(fl, sc, /* lc= */ NULL, mv, h)
+#define OPTION_SHORT_DATA(sc, mv, d, h) OPTION_FULL_DATA(/* fl= */ 0, sc, /* lc= */ NULL, mv, d, h)
 #define OPTION_POSITIONAL OPTION_FULL(OPTION_POSITIONAL_ENTRY, /* sc= */ 0, "(positional)", /* mv= */ NULL, /* h= */ NULL)
 #define OPTION_HELP_VERBATIM(lc, h) OPTION_FULL(OPTION_HELP_ENTRY_VERBATIM, /* sc= */ 0, lc, /* mv= */ NULL, h)
 
index 05fd4bcbe0761c0b45322ead85a985678897fd9b..687bafd4a2b9b671365f6b2be11fb4524fe24acd 100644 (file)
@@ -772,6 +772,12 @@ static void test_macros_parse_one(
                 if (entries[i].short_code != 0)
                         ASSERT_EQ(opt->short_code, entries[i].short_code);
                 ASSERT_TRUE(streq_ptr(arg, entries[i].argument));
+
+                if (streq_ptr(entries[i].long_code, "optional2"))
+                        ASSERT_EQ(opt->data, 666u);
+                else
+                        ASSERT_EQ(opt->data, 0u);
+
                 i++;
 
                 switch (c) {
@@ -796,6 +802,10 @@ static void test_macros_parse_one(
                 OPTION_FULL(OPTION_OPTIONAL_ARG, 'o', "optional", "ARG", "Optional arg option"):
                         break;
 
+                /* OPTION_FULL_DATA: optional arg */
+                OPTION_FULL_DATA(OPTION_OPTIONAL_ARG, 'O', "optional2", "ARG", 666, "Optional arg option"):
+                        break;
+
                 /* OPTION_FULL: stops parsing */
                 OPTION_FULL(OPTION_STOPS_PARSING, 0, "exec", NULL, "Stop parsing after this"):
                         break;
@@ -1015,6 +1025,7 @@ TEST(option_macros) {
                                         "-v",
                                         "--required=rval",
                                         "--optional=oval",
+                                        "--optional2=oval",
                                         "--debug",
                                         "pos2",
                                         "-o",
@@ -1025,6 +1036,7 @@ TEST(option_macros) {
                                       { .short_code = 'v' },
                                       { "required", "rval" },
                                       { "optional", "oval" },
+                                      { "optional2", "oval" },
                                       { "debug" },
                                       { "optional", NULL },
                                       { "help" },