2 * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
8 #include "argpar-utils.hpp"
12 #include <common/error.hpp>
13 #include <common/string-utils/string-utils.hpp>
16 * Given argpar error status `status` and error `error`, return a formatted
17 * error message describing the error.
19 * `argv` is the argument vector that was being parsed.
21 * `context_fmt`, if non-NULL, is formatted using `args` and prepended to the
24 * Add `argc_offset` the the argument index mentioned in the error message.
26 * The returned string must be freed by the caller.
28 static ATTR_FORMAT_PRINTF(4, 0)
29 char *format_arg_error_v(const struct argpar_error
*error
, int argc_offset
,
30 const char **argv
, const char *context_fmt
, va_list args
)
37 ret
= vasprintf(&str
, context_fmt
, args
);
40 * If vasprintf fails, the content of str is undefined,
41 * and we shouldn't try to free it.
47 ret
= strutils_append_str(&str
, ": ");
53 switch (argpar_error_type(error
))
55 case ARGPAR_ERROR_TYPE_MISSING_OPT_ARG
:
57 const int orig_index
= argpar_error_orig_index(error
);
58 const char *arg
= argv
[orig_index
];
60 ret
= strutils_appendf(&str
,
61 WHILE_PARSING_ARG_N_ARG_FMT
"Missing required argument for option `%s`",
62 orig_index
+ 1 + argc_offset
, argv
[orig_index
], arg
);
69 case ARGPAR_ERROR_TYPE_UNEXPECTED_OPT_ARG
:
72 const struct argpar_opt_descr
*descr
=
73 argpar_error_opt_descr(error
, &is_short
);
74 int orig_index
= argpar_error_orig_index(error
);
75 const char *arg
= argv
[orig_index
];
78 ret
= strutils_appendf(&str
,
79 WHILE_PARSING_ARG_N_ARG_FMT
"Unexpected argument for option `-%c`",
80 orig_index
+ 1 + argc_offset
, arg
, descr
->short_name
);
82 ret
= strutils_appendf(&str
,
83 WHILE_PARSING_ARG_N_ARG_FMT
"Unexpected argument for option `--%s`",
84 orig_index
+ 1 + argc_offset
, arg
, descr
->long_name
);
93 case ARGPAR_ERROR_TYPE_UNKNOWN_OPT
:
95 int orig_index
= argpar_error_orig_index(error
);
96 const char *unknown_opt
= argpar_error_unknown_opt_name(error
);
98 ret
= strutils_appendf(&str
,
99 WHILE_PARSING_ARG_N_ARG_FMT
"Unknown option `%s`",
100 orig_index
+ 1 + argc_offset
, argv
[orig_index
], unknown_opt
);
120 enum parse_next_item_status
parse_next_item(struct argpar_iter
*iter
,
121 const struct argpar_item
**item
, int argc_offset
,
122 const char **argv
, bool unknown_opt_is_error
,
123 const struct argpar_error
**error_out
,
124 const char *context_fmt
, ...)
126 enum argpar_iter_next_status status
;
127 const struct argpar_error
*error
= NULL
;
128 enum parse_next_item_status ret
;
130 ARGPAR_ITEM_DESTROY_AND_RESET(*item
);
131 status
= argpar_iter_next(iter
, item
, &error
);
134 case ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY
:
135 ERR("Failed to get next argpar item.");
136 ret
= PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY
;
138 case ARGPAR_ITER_NEXT_STATUS_ERROR
:
143 if (argpar_error_type(error
) == ARGPAR_ERROR_TYPE_UNKNOWN_OPT
&&
144 !unknown_opt_is_error
) {
145 ret
= PARSE_NEXT_ITEM_STATUS_END
;
149 va_start(args
, context_fmt
);
150 err_str
= format_arg_error_v(error
, argc_offset
, argv
,
158 ERR("%s", "Failed to format argpar error.");
161 ret
= PARSE_NEXT_ITEM_STATUS_ERROR
;
164 case ARGPAR_ITER_NEXT_STATUS_END
:
165 ret
= PARSE_NEXT_ITEM_STATUS_END
;
167 case ARGPAR_ITER_NEXT_STATUS_OK
:
168 ret
= PARSE_NEXT_ITEM_STATUS_OK
;
175 argpar_error_destroy(*error_out
);
180 argpar_error_destroy(error
);