Skip to content

Commit 35c4b2b

Browse files
simarkjgalar
authored andcommitted
lttng: fix argument numbers in add-trigger error messages
Argument numbers in add-trigger argument parsing error messages are wrong. For example: $ ./src/bin/lttng/lttng add-trigger --condition event-rule-matches --foo Error: While parsing argument #1 (`--foo`): Unknown option `--foo` This is due to the fact that multiple separate argpar iterators are created to parse an add-trigger command line. Iterators are created at the top-level, to parse the top-level arguments. Iterators are also created when parsing a condition or an action, to parse the arguments specific to that condition or action. As a result, iterators are passed a subset of the full command line, and the argument indices in the error messages are off. Fix that by passing around an "argc offset", which represents by how much what's being parsed is offset from the full command-line. Use that to adjust the error messages to give indices that make sense to the user: $ ./src/bin/lttng/lttng add-trigger --condition event-rule-matches --foo Error: While parsing argument #4 (`--foo`): Unknown option `--foo` Change-Id: I1d312593d338641d0ec10abe515b640771a1f160 Signed-off-by: Simon Marchi <[email protected]> Signed-off-by: Jérémie Galarneau <[email protected]>
1 parent b1a5fb9 commit 35c4b2b

File tree

6 files changed

+65
-45
lines changed

6 files changed

+65
-45
lines changed

src/bin/lttng/commands/add_trigger.cpp

+40-26
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,8 @@ struct parse_event_rule_res {
649649
};
650650

651651
static
652-
struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
652+
struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv,
653+
int argc_offset)
653654
{
654655
enum lttng_event_rule_type event_rule_type =
655656
LTTNG_EVENT_RULE_TYPE_UNKNOWN;
@@ -695,8 +696,8 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
695696
while (true) {
696697
enum parse_next_item_status status;
697698

698-
status = parse_next_item(argpar_iter, &argpar_item, *argv,
699-
false, NULL);
699+
status = parse_next_item(argpar_iter, &argpar_item,
700+
argc_offset, *argv, false, NULL);
700701
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
701702
goto error;
702703
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
@@ -1347,13 +1348,14 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
13471348
}
13481349

13491350
static
1350-
struct lttng_condition *handle_condition_event(int *argc, const char ***argv)
1351+
struct lttng_condition *handle_condition_event(int *argc, const char ***argv,
1352+
int argc_offset)
13511353
{
13521354
struct parse_event_rule_res res;
13531355
struct lttng_condition *c;
13541356
size_t i;
13551357

1356-
res = parse_event_rule(argc, argv);
1358+
res = parse_event_rule(argc, argv, argc_offset);
13571359
if (!res.er) {
13581360
c = NULL;
13591361
goto error;
@@ -1403,7 +1405,8 @@ struct lttng_condition *handle_condition_event(int *argc, const char ***argv)
14031405

14041406
struct condition_descr {
14051407
const char *name;
1406-
struct lttng_condition *(*handler) (int *argc, const char ***argv);
1408+
struct lttng_condition *(*handler) (int *argc, const char ***argv,
1409+
int argc_offset);
14071410
};
14081411

14091412
static const
@@ -1413,7 +1416,7 @@ struct condition_descr condition_descrs[] = {
14131416

14141417
static
14151418
struct lttng_condition *parse_condition(const char *condition_name, int *argc,
1416-
const char ***argv)
1419+
const char ***argv, int argc_offset)
14171420
{
14181421
int i;
14191422
struct lttng_condition *cond;
@@ -1431,7 +1434,7 @@ struct lttng_condition *parse_condition(const char *condition_name, int *argc,
14311434
goto error;
14321435
}
14331436

1434-
cond = descr->handler(argc, argv);
1437+
cond = descr->handler(argc, argv, argc_offset);
14351438
if (!cond) {
14361439
/* The handler has already printed an error message. */
14371440
goto error;
@@ -1524,7 +1527,8 @@ static const struct argpar_opt_descr notify_action_opt_descrs[] = {
15241527
};
15251528

15261529
static
1527-
struct lttng_action *handle_action_notify(int *argc, const char ***argv)
1530+
struct lttng_action *handle_action_notify(int *argc, const char ***argv,
1531+
int argc_offset)
15281532
{
15291533
struct lttng_action *action = NULL;
15301534
struct argpar_iter *argpar_iter = NULL;
@@ -1540,8 +1544,9 @@ struct lttng_action *handle_action_notify(int *argc, const char ***argv)
15401544
while (true) {
15411545
enum parse_next_item_status status;
15421546

1543-
status = parse_next_item(argpar_iter, &argpar_item, *argv,
1544-
false, "While parsing `notify` action:");
1547+
status = parse_next_item(argpar_iter, &argpar_item,
1548+
argc_offset, *argv, false,
1549+
"While parsing `notify` action:");
15451550
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
15461551
goto error;
15471552
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
@@ -1612,6 +1617,7 @@ struct lttng_action *handle_action_notify(int *argc, const char ***argv)
16121617

16131618
static struct lttng_action *handle_action_simple_session_with_policy(int *argc,
16141619
const char ***argv,
1620+
int argc_offset,
16151621
struct lttng_action *(*create_action_cb)(void),
16161622
enum lttng_action_status (*set_session_name_cb)(
16171623
struct lttng_action *, const char *),
@@ -1644,8 +1650,9 @@ static struct lttng_action *handle_action_simple_session_with_policy(int *argc,
16441650
while (true) {
16451651
enum parse_next_item_status status;
16461652

1647-
status = parse_next_item(argpar_iter, &argpar_item, *argv,
1648-
false, "While parsing `%s` action:", action_name);
1653+
status = parse_next_item(argpar_iter, &argpar_item, argc_offset,
1654+
*argv, false,
1655+
"While parsing `%s` action:", action_name);
16491656
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
16501657
goto error;
16511658
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
@@ -1730,29 +1737,32 @@ static struct lttng_action *handle_action_simple_session_with_policy(int *argc,
17301737

17311738
static
17321739
struct lttng_action *handle_action_start_session(int *argc,
1733-
const char ***argv)
1740+
const char ***argv, int argc_offset)
17341741
{
17351742
return handle_action_simple_session_with_policy(argc, argv,
1743+
argc_offset,
17361744
lttng_action_start_session_create,
17371745
lttng_action_start_session_set_session_name,
17381746
lttng_action_start_session_set_rate_policy, "start");
17391747
}
17401748

17411749
static
17421750
struct lttng_action *handle_action_stop_session(int *argc,
1743-
const char ***argv)
1751+
const char ***argv, int argc_offset)
17441752
{
17451753
return handle_action_simple_session_with_policy(argc, argv,
1754+
argc_offset,
17461755
lttng_action_stop_session_create,
17471756
lttng_action_stop_session_set_session_name,
17481757
lttng_action_stop_session_set_rate_policy, "stop");
17491758
}
17501759

17511760
static
17521761
struct lttng_action *handle_action_rotate_session(int *argc,
1753-
const char ***argv)
1762+
const char ***argv, int argc_offset)
17541763
{
17551764
return handle_action_simple_session_with_policy(argc, argv,
1765+
argc_offset,
17561766
lttng_action_rotate_session_create,
17571767
lttng_action_rotate_session_set_session_name,
17581768
lttng_action_rotate_session_set_rate_policy,
@@ -1772,7 +1782,7 @@ static const struct argpar_opt_descr snapshot_action_opt_descrs[] = {
17721782

17731783
static
17741784
struct lttng_action *handle_action_snapshot_session(int *argc,
1775-
const char ***argv)
1785+
const char ***argv, int argc_offset)
17761786
{
17771787
struct lttng_action *action = NULL;
17781788
struct argpar_iter *argpar_iter = NULL;
@@ -1800,8 +1810,8 @@ struct lttng_action *handle_action_snapshot_session(int *argc,
18001810
while (true) {
18011811
enum parse_next_item_status status;
18021812

1803-
status = parse_next_item(argpar_iter, &argpar_item, *argv,
1804-
false, "While parsing `snapshot` action:");
1813+
status = parse_next_item(argpar_iter, &argpar_item, argc_offset,
1814+
*argv, false, "While parsing `snapshot` action:");
18051815
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
18061816
goto error;
18071817
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
@@ -2072,7 +2082,8 @@ struct lttng_action *handle_action_snapshot_session(int *argc,
20722082

20732083
struct action_descr {
20742084
const char *name;
2075-
struct lttng_action *(*handler) (int *argc, const char ***argv);
2085+
struct lttng_action *(*handler) (int *argc, const char ***argv,
2086+
int argc_offset);
20762087
};
20772088

20782089
static const
@@ -2085,7 +2096,8 @@ struct action_descr action_descrs[] = {
20852096
};
20862097

20872098
static
2088-
struct lttng_action *parse_action(const char *action_name, int *argc, const char ***argv)
2099+
struct lttng_action *parse_action(const char *action_name, int *argc,
2100+
const char ***argv, int argc_offset)
20892101
{
20902102
int i;
20912103
struct lttng_action *action;
@@ -2103,7 +2115,7 @@ struct lttng_action *parse_action(const char *action_name, int *argc, const char
21032115
goto error;
21042116
}
21052117

2106-
action = descr->handler(argc, argv);
2118+
action = descr->handler(argc, argv, argc_offset);
21072119
if (!action) {
21082120
/* The handler has already printed an error message. */
21092121
goto error;
@@ -2194,8 +2206,8 @@ int cmd_add_trigger(int argc, const char **argv)
21942206
goto error;
21952207
}
21962208

2197-
status = parse_next_item(argpar_iter, &argpar_item, my_argv,
2198-
true, NULL);
2209+
status = parse_next_item(argpar_iter, &argpar_item,
2210+
argc - my_argc, my_argv, true, NULL);
21992211
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
22002212
goto error;
22012213
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
@@ -2234,7 +2246,8 @@ int cmd_add_trigger(int argc, const char **argv)
22342246
goto error;
22352247
}
22362248

2237-
condition = parse_condition(arg, &my_argc, &my_argv);
2249+
condition = parse_condition(arg, &my_argc, &my_argv,
2250+
argc - my_argc);
22382251
if (!condition) {
22392252
/*
22402253
* An error message was already printed by
@@ -2247,7 +2260,8 @@ int cmd_add_trigger(int argc, const char **argv)
22472260
}
22482261
case OPT_ACTION:
22492262
{
2250-
action = parse_action(arg, &my_argc, &my_argv);
2263+
action = parse_action(arg, &my_argc, &my_argv,
2264+
argc - my_argc);
22512265
if (!action) {
22522266
/*
22532267
* An error message was already printed by

src/bin/lttng/commands/list_triggers.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,7 @@ int cmd_list_triggers(int argc, const char **argv)
13351335
while (true) {
13361336
enum parse_next_item_status status;
13371337

1338-
status = parse_next_item(argpar_iter, &argpar_item, argv,
1338+
status = parse_next_item(argpar_iter, &argpar_item, 1, argv,
13391339
true, NULL);
13401340
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
13411341
goto error;

src/bin/lttng/commands/remove_trigger.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ int cmd_remove_trigger(int argc, const char **argv)
111111
while (true) {
112112
enum parse_next_item_status status;
113113

114-
status = parse_next_item(argpar_iter, &argpar_item, argv,
114+
status = parse_next_item(argpar_iter, &argpar_item, 1, argv,
115115
true, NULL);
116116
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
117117
goto error;

src/common/argpar-utils/argpar-utils.c

+13-9
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
* `context_fmt`, if non-NULL, is formatted using `args` and prepended to the
2424
* error message.
2525
*
26+
* Add `argc_offset` the the argument index mentioned in the error message.
27+
*
2628
* The returned string must be freed by the caller.
2729
*/
28-
static ATTR_FORMAT_PRINTF(3, 0)
29-
char *format_arg_error_v(const struct argpar_error *error,
30+
static ATTR_FORMAT_PRINTF(4, 0)
31+
char *format_arg_error_v(const struct argpar_error *error, int argc_offset,
3032
const char **argv, const char *context_fmt, va_list args)
3133
{
3234
char *str = NULL;
@@ -59,7 +61,7 @@ char *format_arg_error_v(const struct argpar_error *error,
5961

6062
ret = strutils_appendf(&str,
6163
WHILE_PARSING_ARG_N_ARG_FMT "Missing required argument for option `%s`",
62-
orig_index + 1, arg, arg);
64+
orig_index + 1 + argc_offset, argv[orig_index], arg);
6365
if (ret < 0) {
6466
goto end;
6567
}
@@ -77,11 +79,11 @@ char *format_arg_error_v(const struct argpar_error *error,
7779
if (is_short) {
7880
ret = strutils_appendf(&str,
7981
WHILE_PARSING_ARG_N_ARG_FMT "Unexpected argument for option `-%c`",
80-
orig_index + 1, arg, descr->short_name);
82+
orig_index + 1 + argc_offset, arg, descr->short_name);
8183
} else {
8284
ret = strutils_appendf(&str,
8385
WHILE_PARSING_ARG_N_ARG_FMT "Unexpected argument for option `--%s`",
84-
orig_index + 1, arg, descr->long_name);
86+
orig_index + 1 + argc_offset, arg, descr->long_name);
8587
}
8688

8789
if (ret < 0) {
@@ -97,7 +99,7 @@ char *format_arg_error_v(const struct argpar_error *error,
9799

98100
ret = strutils_appendf(&str,
99101
WHILE_PARSING_ARG_N_ARG_FMT "Unknown option `%s`",
100-
orig_index + 1, argv[orig_index], unknown_opt);
102+
orig_index + 1 + argc_offset, argv[orig_index], unknown_opt);
101103

102104
if (ret < 0) {
103105
goto end;
@@ -118,8 +120,9 @@ char *format_arg_error_v(const struct argpar_error *error,
118120
}
119121

120122
enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
121-
const struct argpar_item **item, const char **argv,
122-
bool unknown_opt_is_error, const char *context_fmt, ...)
123+
const struct argpar_item **item, int argc_offset,
124+
const char **argv, bool unknown_opt_is_error,
125+
const char *context_fmt, ...)
123126
{
124127
enum argpar_iter_next_status status;
125128
const struct argpar_error *error = NULL;
@@ -145,7 +148,8 @@ enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
145148
}
146149

147150
va_start(args, context_fmt);
148-
err_str = format_arg_error_v(error, argv, context_fmt, args);
151+
err_str = format_arg_error_v(error, argc_offset, argv,
152+
context_fmt, args);
149153
va_end(args);
150154

151155
if (err_str) {

src/common/argpar-utils/argpar-utils.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,16 @@ enum parse_next_item_status
3939
* On error, print a descriptive error message and return
4040
* PARSE_NEXT_ITEM_STATUS_ERROR. If `context_fmt` is non-NULL, it is formatted
4141
* using the following arguments and prepended to the error message.
42+
* Add `argc_offset` to the argument index mentioned in the error message.
4243
*
4344
* If `unknown_opt_is_error` is true, an unknown option is considered an error.
4445
* Otherwise, it is considered as the end of the argument list.
4546
*/
46-
ATTR_FORMAT_PRINTF(5, 6)
47+
ATTR_FORMAT_PRINTF(6, 7)
4748
enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
48-
const struct argpar_item **item, const char **argv,
49-
bool unknown_opt_is_error, const char *context_fmt, ...);
49+
const struct argpar_item **item, int argc_offset,
50+
const char **argv, bool unknown_opt_is_error,
51+
const char *context_fmt, ...);
5052

5153
#ifdef __cplusplus
5254
}

tests/regression/tools/trigger/test_add_trigger_cli

+5-5
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ test_success "--action snapshot-session with ctrl/data URIs" "notify-15"\
409409
test_failure "no args" "Error: Missing --condition."
410410

411411
test_failure "unknown option" \
412-
"Error: While parsing argument #1 (\`--hello\`): Unknown option \`--hello\`" \
412+
"Error: While parsing argument #2 (\`--hello\`): Unknown option \`--hello\`" \
413413
--hello
414414

415415
test_failure "missing --action" \
@@ -423,7 +423,7 @@ test_failure "two --condition" \
423423
--action notify
424424

425425
test_failure "missing argument to --name" \
426-
"Error: While parsing argument #1 (\`--name\`): Missing required argument for option \`--name\`" \
426+
"Error: While parsing argument #2 (\`--name\`): Missing required argument for option \`--name\`" \
427427
--name
428428

429429
for cmd in rate-policy=once-after rate-policy=every; do
@@ -450,7 +450,7 @@ test_failure "invalid argument to --rate-policy: unknown policy type" \
450450

451451
# `--condition` failures
452452
test_failure "missing args after --condition" \
453-
"Error: While parsing argument #1 (\`--condition\`): Missing required argument for option \`--condition\`" \
453+
"Error: While parsing argument #2 (\`--condition\`): Missing required argument for option \`--condition\`" \
454454
--condition
455455
test_failure "unknown --condition" \
456456
"Error: Unknown condition name 'zoofest'" \
@@ -502,7 +502,7 @@ test_failure "--exclude-name with non-glob name" \
502502
--action notify
503503

504504
test_failure "--condition event-rule-matches --capture: missing argument (end of arg list)" \
505-
'Error: While parsing argument #2 (`--capture`): Missing required argument for option `--capture`' \
505+
'Error: While parsing argument #7 (`--capture`): Missing required argument for option `--capture`' \
506506
--action notify \
507507
--condition event-rule-matches --type=user --capture
508508

@@ -548,7 +548,7 @@ test_failure "--condition event-rule-matches --capture: missing colon in app-spe
548548

549549
# `--action` failures
550550
test_failure "missing args after --action" \
551-
"Error: While parsing argument #1 (\`--action\`): Missing required argument for option \`--action\`" \
551+
"Error: While parsing argument #5 (\`--action\`): Missing required argument for option \`--action\`" \
552552
--condition event-rule-matches --type=user \
553553
--action
554554

0 commit comments

Comments
 (0)