shared/options: convert mode boolean to an enum
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.
This commit is contained in:
+1
-1
@@ -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;
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+12
-3
@@ -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.
|
||||
|
||||
+45
-45
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user