]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/options: convert mode boolean to an enum
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Thu, 16 Apr 2026 07:05:01 +0000 (09:05 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Thu, 16 Apr 2026 07:05:01 +0000 (09:05 +0200)
This will make it easier to add new modes of operation later.
But I'm happy with how this came out — I think the mode setting
is nicer to read then the old bool.

src/journal/cat.c
src/nspawn/nspawn.c
src/shared/options.c
src/shared/options.h
src/test/test-options.c
src/vmspawn/vmspawn.c

index e2419d36ab334d472b599e45d539285769823933..62249663c581b0461544bc5410bbcf31342cd4d3 100644 (file)
@@ -59,7 +59,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) {
         assert(argc >= 0);
         assert(argv);
 
-        OptionParser state = { argc, argv, /* stop_at_first_nonoption= */ true };
+        OptionParser state = { argc, argv, OPTION_PARSER_STOP_AT_FIRST_NONOPTION };
         const char *arg;
         int r;
 
index accf448ea97f2876e8dde76e1473fb93c3b0a6d2..92c0c03177cb1f9ec9943facf9684791e3808b39 100644 (file)
@@ -586,7 +586,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        OptionParser state = { argc, argv, /* stop_at_first_nonoption= */ true };
+        OptionParser state = { argc, argv, OPTION_PARSER_STOP_AT_FIRST_NONOPTION };
         const Option *opt;
         const char *arg;
 
index dc2fb34cf62f2199965d8edef7a1fa5cefc88667..5d4df946b83fb3a010fa5f8370ae8ce9f0236d79 100644 (file)
@@ -75,6 +75,8 @@ int option_parse(
 
         /* Check and initialize */
         if (state->optind == 0) {
+                assert(state->mode >= 0 && state->mode < _OPTION_PARSER_MODE_MAX);
+
                 if (state->argc < 1 || strv_isempty(state->argv))
                         return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "argv cannot be empty");
 
@@ -109,7 +111,7 @@ int option_parse(
                                 /* Looks like we found an option parameter */
                                 break;
 
-                        if (state->stop_at_first_nonoption) {
+                        if (state->mode == OPTION_PARSER_STOP_AT_FIRST_NONOPTION) {
                                 state->parsing_stopped = true;
                                 return 0;
                         }
index 262196c8d95af543bd96c816a2d23f1f4fca0eba..a10f914da266c6eb9aa6ed8aecebb970ac7a1728 100644 (file)
@@ -92,13 +92,22 @@ typedef struct Option {
 extern const Option __start_SYSTEMD_OPTIONS[];
 extern const Option __stop_SYSTEMD_OPTIONS[];
 
+typedef enum OptionParserMode {
+        /* The default mode. This is the implicit default and doesn't have to be specified. */
+        OPTION_PARSER_NORMAL = 0,
+
+        /* Same as "+…" for getopt_long — only parse options before the first positional argument. */
+        OPTION_PARSER_STOP_AT_FIRST_NONOPTION,
+
+        _OPTION_PARSER_MODE_MAX,
+} OptionParserMode;
+
 typedef struct OptionParser {
         /* Those three should stay first so that it's possible to initialize the struct as { argc, argv }
-         * or { argc, argv, true/false }. */
+         * or { argc, argv, mode }. */
         int argc;                     /* The original argc. */
         char **argv;                  /* The argv array, possibly reordered. */
-        bool stop_at_first_nonoption; /* Same as "+…" for getopt_long — only parse options before the first
-                                       * positional argument. */
+        OptionParserMode mode;
 
         bool parsing_stopped;         /* We processed "--" or an option that terminates option parsing. */
         int optind;                   /* Position of the parameter being handled.
index b91ac54884c6bb0d6e6993ec0714b01f420db931..e6b18d7a7eaeb3e4e82daa310bd1ae5ce29ea98f 100644 (file)
@@ -15,7 +15,7 @@ static void test_option_parse_one(
                 const Option options[],
                 const Entry *entries,
                 char **remaining,
-                bool stop_at_first_nonoption) {
+                OptionParserMode mode) {
 
         _cleanup_free_ char *joined = strv_join(argv, ", ");
         log_debug("/* %s(%s) */", __func__, joined);
@@ -32,7 +32,7 @@ static void test_option_parse_one(
         for (const Entry *e = entries; e && (e->long_code || e->short_code != 0); e++)
                 n_entries++;
 
-        OptionParser state = { argc, argv, stop_at_first_nonoption };
+        OptionParser state = { argc, argv, mode };
         const Option *opt;
         const char *arg;
         for (int c; (c = option_parse(options, options + n_options, &state, &opt, &arg)) != 0; ) {
@@ -101,7 +101,7 @@ TEST(option_parse) {
                               options,
                               NULL,
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -114,7 +114,7 @@ TEST(option_parse) {
                                         "string2",
                                         "string3",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "--",
@@ -128,7 +128,7 @@ TEST(option_parse) {
                                         "--help",
                                         "-h",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -142,7 +142,7 @@ TEST(option_parse) {
                                         "string2",
                                         "--",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -156,7 +156,7 @@ TEST(option_parse) {
                                         "string2",
                                         "string3",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "--help"),
@@ -166,7 +166,7 @@ TEST(option_parse) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "--help",
@@ -179,7 +179,7 @@ TEST(option_parse) {
                               },
                               STRV_MAKE("string1",
                                         "--help"),
-                              true);
+                              OPTION_PARSER_STOP_AT_FIRST_NONOPTION);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "-h"),
@@ -189,7 +189,7 @@ TEST(option_parse) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "--help",
@@ -206,7 +206,7 @@ TEST(option_parse) {
                                         "string2",
                                         "string3",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "-h",
@@ -223,7 +223,7 @@ TEST(option_parse) {
                                         "string2",
                                         "string3",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -240,7 +240,7 @@ TEST(option_parse) {
                                         "string2",
                                         "string3",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -257,7 +257,7 @@ TEST(option_parse) {
                                         "string2",
                                         "string3",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -274,7 +274,7 @@ TEST(option_parse) {
                                         "string2",
                                         "string3",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -291,7 +291,7 @@ TEST(option_parse) {
                                         "string2",
                                         "string3",
                                         "string4"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "--required1", "reqarg1"),
@@ -301,7 +301,7 @@ TEST(option_parse) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "-r", "reqarg1"),
@@ -311,7 +311,7 @@ TEST(option_parse) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -324,7 +324,7 @@ TEST(option_parse) {
                               },
                               STRV_MAKE("string1",
                                         "string2"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -335,7 +335,7 @@ TEST(option_parse) {
                               STRV_MAKE("string1",
                                         "string2",
                                         "-r", "reqarg1"),
-                              true);
+                              OPTION_PARSER_STOP_AT_FIRST_NONOPTION);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "--optional1=optarg1"),
@@ -345,7 +345,7 @@ TEST(option_parse) {
                                       {}
                               },
                               NULL,
-                              true);
+                              OPTION_PARSER_STOP_AT_FIRST_NONOPTION);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "--optional1", "string1"),
@@ -355,7 +355,7 @@ TEST(option_parse) {
                                       {}
                               },
                               STRV_MAKE("string1"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "-ooptarg1"),
@@ -365,7 +365,7 @@ TEST(option_parse) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "-o", "string1"),
@@ -375,7 +375,7 @@ TEST(option_parse) {
                                       {}
                               },
                               STRV_MAKE("string1"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         test_option_parse_one(STRV_MAKE("arg0",
                                         "string1",
@@ -445,7 +445,7 @@ TEST(option_parse) {
                                         "--help",
                                         "--required1",
                                         "--optional1"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 }
 
 TEST(option_stops_parsing) {
@@ -469,7 +469,7 @@ TEST(option_stops_parsing) {
                               },
                               STRV_MAKE("--help",
                                         "foo"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Options before --exec are still parsed */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -485,7 +485,7 @@ TEST(option_stops_parsing) {
                               },
                               STRV_MAKE("--version",
                                         "bar"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* --exec with no trailing args */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -496,7 +496,7 @@ TEST(option_stops_parsing) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* --exec after positional args */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -513,7 +513,7 @@ TEST(option_stops_parsing) {
                                         "--help",
                                         "--required",
                                         "val"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* "--" after --exec: "--" is still consumed as end-of-options marker. This is needed for
          * backwards compatibility, systemd-dissect implemented this behaviour. But also, it makes
@@ -529,7 +529,7 @@ TEST(option_stops_parsing) {
                                       {}
                               },
                               STRV_MAKE("--help"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* "--" before --exec: "--" terminates first, --exec is positional */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -540,7 +540,7 @@ TEST(option_stops_parsing) {
                               NULL,
                               STRV_MAKE("--exec",
                                         "--help"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Multiple options then --exec then more option-like args */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -559,7 +559,7 @@ TEST(option_stops_parsing) {
                               STRV_MAKE("-h",
                                         "--required",
                                         "val2"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 }
 
 TEST(option_group_marker) {
@@ -584,7 +584,7 @@ TEST(option_group_marker) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Check that group marker name is ignored */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -597,7 +597,7 @@ TEST(option_group_marker) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Verify that the group marker is not mistaken for an option */
         test_option_invalid_one(STRV_MAKE("arg0",
@@ -625,7 +625,7 @@ TEST(option_group_marker) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Partial match with multiple candidates */
         test_option_invalid_one(STRV_MAKE("arg0",
@@ -649,7 +649,7 @@ TEST(option_optional_arg) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Long option without = does NOT consume the next arg */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -660,7 +660,7 @@ TEST(option_optional_arg) {
                                       {}
                               },
                               STRV_MAKE("foo.txt"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Short option with inline arg */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -671,7 +671,7 @@ TEST(option_optional_arg) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Short option without inline arg does NOT consume the next arg */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -682,7 +682,7 @@ TEST(option_optional_arg) {
                                       {}
                               },
                               STRV_MAKE("foo.txt"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Optional arg option at end of argv */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -693,7 +693,7 @@ TEST(option_optional_arg) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Mixed: optional arg with other options */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -708,7 +708,7 @@ TEST(option_optional_arg) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Short combo: -ho (h then o with no arg) */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -720,7 +720,7 @@ TEST(option_optional_arg) {
                                       {}
                               },
                               STRV_MAKE("pos1"),
-                              false);
+                              OPTION_PARSER_NORMAL);
 
         /* Short combo: -hobar (h then o with inline arg "bar") */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -732,7 +732,7 @@ TEST(option_optional_arg) {
                                       {}
                               },
                               NULL,
-                              false);
+                              OPTION_PARSER_NORMAL);
 }
 
 /* Test the OPTION, OPTION_LONG, OPTION_SHORT, OPTION_FULL, OPTION_GROUP macros
@@ -1110,7 +1110,7 @@ TEST(option_optional_arg_consume) {
                                       {}
                               },
                               NULL,
-                              /* stop_at_first_nonoption= */ false);
+                              OPTION_PARSER_NORMAL);
 
         /* --user without arg: next arg is an option, so no consumption */
         test_option_parse_one(STRV_MAKE("arg0",
@@ -1123,7 +1123,7 @@ TEST(option_optional_arg_consume) {
                                       {}
                               },
                               NULL,
-                              /* stop_at_first_nonoption= */ false);
+                              OPTION_PARSER_NORMAL);
 
         /* --user without arg: next arg is positional (doesn't start with -).
          * The option parser returns NULL for the arg. The caller would then
index c1b913217a7cf77ba38e542f365e03715db805df..d95a2ccf647cd2c2c8cf4123b7fa075ce0e366bc 100644 (file)
@@ -319,7 +319,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        OptionParser state = { argc, argv, /* stop_at_first_nonoption= */ true };
+        OptionParser state = { argc, argv, OPTION_PARSER_STOP_AT_FIRST_NONOPTION };
         const Option *current;
         const char *arg;