Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 HiSilicon Limited
3 : : */
4 : :
5 : : #include <errno.h>
6 : : #include <stdlib.h>
7 : : #include <string.h>
8 : :
9 : : #include <rte_log.h>
10 : :
11 : : #include "rte_argparse.h"
12 : :
13 [ - + ]: 252 : RTE_LOG_REGISTER_DEFAULT(rte_argparse_logtype, INFO);
14 : : #define RTE_LOGTYPE_ARGPARSE rte_argparse_logtype
15 : : #define ARGPARSE_LOG(level, ...) \
16 : : RTE_LOG_LINE(level, ARGPARSE, "" __VA_ARGS__)
17 : :
18 : : #define ARG_ATTR_FLAG_PARSED_MASK RTE_BIT64(63)
19 : :
20 : : static inline bool
21 : : is_arg_optional(const struct rte_argparse_arg *arg)
22 : : {
23 : 57 : return arg->name_long[0] == '-';
24 : : }
25 : :
26 : : static inline bool
27 : : is_arg_positional(const struct rte_argparse_arg *arg)
28 : : {
29 : 93 : return arg->name_long[0] != '-';
30 : : }
31 : :
32 : : static inline uint32_t
33 : : arg_attr_has_val(const struct rte_argparse_arg *arg)
34 : : {
35 : 116 : return RTE_FIELD_GET64(RTE_ARGPARSE_HAS_VAL_BITMASK, arg->flags);
36 : : }
37 : :
38 : : static inline uint32_t
39 : : arg_attr_val_type(const struct rte_argparse_arg *arg)
40 : : {
41 : 77 : return RTE_FIELD_GET64(RTE_ARGPARSE_VAL_TYPE_BITMASK, arg->flags);
42 : : }
43 : :
44 : : static inline bool
45 : : arg_attr_flag_multi(const struct rte_argparse_arg *arg)
46 : : {
47 : 0 : return RTE_FIELD_GET64(RTE_ARGPARSE_ARG_SUPPORT_MULTI, arg->flags);
48 : : }
49 : :
50 : : static inline uint64_t
51 : : arg_attr_unused_bits(const struct rte_argparse_arg *arg)
52 : : {
53 : : #define USED_BIT_MASK (RTE_ARGPARSE_HAS_VAL_BITMASK | \
54 : : RTE_ARGPARSE_VAL_TYPE_BITMASK | \
55 : : RTE_ARGPARSE_ARG_SUPPORT_MULTI)
56 : 40 : return arg->flags & ~USED_BIT_MASK;
57 : : }
58 : :
59 : : static int
60 : 57 : verify_arg_name(const struct rte_argparse_arg *arg)
61 : : {
62 [ + + ]: 57 : if (is_arg_optional(arg)) {
63 [ + + ]: 45 : if (strlen(arg->name_long) <= 3) {
64 : 1 : ARGPARSE_LOG(ERR, "optional long name %s too short!", arg->name_long);
65 : 1 : return -EINVAL;
66 : : }
67 [ + + ]: 44 : if (arg->name_long[1] != '-') {
68 : 1 : ARGPARSE_LOG(ERR, "optional long name %s doesn't start with '--'",
69 : : arg->name_long);
70 : 1 : return -EINVAL;
71 : : }
72 [ + + ]: 43 : if (arg->name_long[2] == '-') {
73 : 1 : ARGPARSE_LOG(ERR, "optional long name %s should not start with '---'",
74 : : arg->name_long);
75 : 1 : return -EINVAL;
76 : : }
77 : : }
78 : :
79 [ + + ]: 54 : if (arg->name_short == NULL)
80 : : return 0;
81 : :
82 [ + + ]: 43 : if (!is_arg_optional(arg)) {
83 : 1 : ARGPARSE_LOG(ERR, "short name %s corresponding long name must be optional!",
84 : : arg->name_short);
85 : 1 : return -EINVAL;
86 : : }
87 : :
88 [ + + + + ]: 42 : if (strlen(arg->name_short) != 2 || arg->name_short[0] != '-' ||
89 [ - + ]: 39 : arg->name_short[1] == '-') {
90 : 3 : ARGPARSE_LOG(ERR, "short name %s must start with a hyphen (-) followed by an English letter",
91 : : arg->name_short);
92 : 3 : return -EINVAL;
93 : : }
94 : :
95 : : return 0;
96 : : }
97 : :
98 : : static int
99 : : verify_arg_help(const struct rte_argparse_arg *arg)
100 : : {
101 [ + + ]: 50 : if (arg->help == NULL) {
102 : 1 : ARGPARSE_LOG(ERR, "argument %s doesn't have help info!", arg->name_long);
103 : : return -EINVAL;
104 : : }
105 : :
106 : : return 0;
107 : : }
108 : :
109 : : static int
110 : 49 : verify_arg_has_val(const struct rte_argparse_arg *arg)
111 : : {
112 : : uint32_t has_val = arg_attr_has_val(arg);
113 : :
114 [ + + ]: 49 : if (is_arg_positional(arg)) {
115 [ + + ]: 11 : if (has_val == RTE_ARGPARSE_ARG_REQUIRED_VALUE)
116 : : return 0;
117 : 3 : ARGPARSE_LOG(ERR, "argument %s is positional, must config required-val!",
118 : : arg->name_long);
119 : 3 : return -EINVAL;
120 : : }
121 : :
122 [ + + ]: 38 : if (has_val == 0) {
123 : 1 : ARGPARSE_LOG(ERR, "argument %s is optional, has-value config wrong!",
124 : : arg->name_long);
125 : 1 : return -EINVAL;
126 : : }
127 : :
128 : : return 0;
129 : : }
130 : :
131 : : static int
132 : 45 : verify_arg_saver(const struct rte_argparse *obj, uint32_t index)
133 : : {
134 : : uint32_t cmp_max = RTE_FIELD_GET64(RTE_ARGPARSE_VAL_TYPE_BITMASK,
135 : : RTE_ARGPARSE_ARG_VALUE_MAX);
136 : : const struct rte_argparse_arg *arg = &obj->args[index];
137 : : uint32_t val_type = arg_attr_val_type(arg);
138 : : uint32_t has_val = arg_attr_has_val(arg);
139 : :
140 [ + + ]: 45 : if (arg->val_saver == NULL) {
141 [ + + ]: 17 : if (val_type != 0) {
142 : 1 : ARGPARSE_LOG(ERR, "argument %s parsed by callback, value-type should not be set!",
143 : : arg->name_long);
144 : 1 : return -EINVAL;
145 : : }
146 : :
147 [ + + ]: 16 : if (obj->callback == NULL) {
148 : 1 : ARGPARSE_LOG(ERR, "argument %s parsed by callback, but callback is NULL!",
149 : : arg->name_long);
150 : 1 : return -EINVAL;
151 : : }
152 : :
153 : : return 0;
154 : : }
155 : :
156 [ + + ]: 28 : if (val_type == 0 || val_type >= cmp_max) {
157 : 2 : ARGPARSE_LOG(ERR, "argument %s value-type config wrong!", arg->name_long);
158 : 2 : return -EINVAL;
159 : : }
160 : :
161 [ + + + + ]: 26 : if (has_val == RTE_ARGPARSE_ARG_REQUIRED_VALUE && arg->val_set != NULL) {
162 : 1 : ARGPARSE_LOG(ERR, "argument %s has required value, value-set should be NULL!",
163 : : arg->name_long);
164 : 1 : return -EINVAL;
165 : : }
166 : :
167 : : return 0;
168 : : }
169 : :
170 : : static int
171 : 40 : verify_arg_flags(const struct rte_argparse *obj, uint32_t index)
172 : : {
173 : : const struct rte_argparse_arg *arg = &obj->args[index];
174 : : uint64_t unused_bits = arg_attr_unused_bits(arg);
175 : :
176 [ + + ]: 40 : if (unused_bits != 0) {
177 : 1 : ARGPARSE_LOG(ERR, "argument %s flags unused bits should not be set!",
178 : : arg->name_long);
179 : 1 : return -EINVAL;
180 : : }
181 : :
182 [ + + ]: 39 : if (!(arg->flags & RTE_ARGPARSE_ARG_SUPPORT_MULTI))
183 : : return 0;
184 : :
185 [ + + ]: 2 : if (is_arg_positional(arg)) {
186 : 1 : ARGPARSE_LOG(ERR, "argument %s is positional, don't support multiple times!",
187 : : arg->name_long);
188 : 1 : return -EINVAL;
189 : : }
190 : :
191 [ + - ]: 1 : if (arg->val_saver != NULL) {
192 : 1 : ARGPARSE_LOG(ERR, "argument %s supports multiple times, should use callback to parse!",
193 : : arg->name_long);
194 : 1 : return -EINVAL;
195 : : }
196 : :
197 : : return 0;
198 : : }
199 : :
200 : : static int
201 : 37 : verify_arg_repeat(const struct rte_argparse *self, uint32_t index)
202 : : {
203 : : const struct rte_argparse_arg *arg = &self->args[index];
204 : : uint32_t i;
205 : :
206 [ + + ]: 42 : for (i = 0; i < index; i++) {
207 [ + + ]: 6 : if (!strcmp(arg->name_long, self->args[i].name_long)) {
208 : 1 : ARGPARSE_LOG(ERR, "argument %s repeat!", arg->name_long);
209 : 1 : return -EINVAL;
210 : : }
211 : : }
212 : :
213 [ + + ]: 36 : if (arg->name_short == NULL)
214 : : return 0;
215 : :
216 [ + + ]: 31 : for (i = 0; i < index; i++) {
217 [ - + ]: 3 : if (self->args[i].name_short == NULL)
218 : 0 : continue;
219 [ + + ]: 3 : if (!strcmp(arg->name_short, self->args[i].name_short)) {
220 : 1 : ARGPARSE_LOG(ERR, "argument %s repeat!", arg->name_short);
221 : 1 : return -EINVAL;
222 : : }
223 : : }
224 : :
225 : : return 0;
226 : : }
227 : :
228 : : static int
229 : 57 : verify_argparse_arg(const struct rte_argparse *obj, uint32_t index)
230 : : {
231 : 57 : const struct rte_argparse_arg *arg = &obj->args[index];
232 : : int ret;
233 : :
234 : 57 : ret = verify_arg_name(arg);
235 [ + + ]: 57 : if (ret != 0)
236 : : return ret;
237 : :
238 : : ret = verify_arg_help(arg);
239 : : if (ret != 0)
240 : 1 : return ret;
241 : :
242 : 49 : ret = verify_arg_has_val(arg);
243 [ + + ]: 49 : if (ret != 0)
244 : : return ret;
245 : :
246 : 45 : ret = verify_arg_saver(obj, index);
247 [ + + ]: 45 : if (ret != 0)
248 : : return ret;
249 : :
250 : 40 : ret = verify_arg_flags(obj, index);
251 [ + + ]: 40 : if (ret != 0)
252 : : return ret;
253 : :
254 : 37 : ret = verify_arg_repeat(obj, index);
255 [ + + ]: 37 : if (ret != 0)
256 : 2 : return ret;
257 : :
258 : : return 0;
259 : : }
260 : :
261 : : static int
262 : 53 : verify_argparse(const struct rte_argparse *obj)
263 : : {
264 : : uint32_t idx;
265 : : int ret;
266 : :
267 [ + + ]: 53 : if (obj->prog_name == NULL) {
268 : 1 : ARGPARSE_LOG(ERR, "program name is NULL!");
269 : 1 : return -EINVAL;
270 : : }
271 : :
272 [ + + ]: 52 : if (obj->usage == NULL) {
273 : 1 : ARGPARSE_LOG(ERR, "usage is NULL!");
274 : 1 : return -EINVAL;
275 : : }
276 : :
277 [ + + ]: 867 : for (idx = 0; idx < RTE_DIM(obj->reserved); idx++) {
278 [ - + ]: 816 : if (obj->reserved[idx] != 0) {
279 : 0 : ARGPARSE_LOG(ERR, "reserved field must be zero!");
280 : 0 : return -EINVAL;
281 : : }
282 : : }
283 : :
284 : : idx = 0;
285 [ + + ]: 86 : while (obj->args[idx].name_long != NULL) {
286 : 57 : ret = verify_argparse_arg(obj, idx);
287 [ + + ]: 57 : if (ret != 0)
288 : 22 : return ret;
289 : 35 : idx++;
290 : : }
291 : :
292 : : return 0;
293 : : }
294 : :
295 : : static uint32_t
296 : : calc_position_count(const struct rte_argparse *obj)
297 : : {
298 : : const struct rte_argparse_arg *arg;
299 : : uint32_t count = 0;
300 : : uint32_t i;
301 : :
302 : 33 : for (i = 0; /* NULL */; i++) {
303 : 33 : arg = &obj->args[i];
304 [ - - + + ]: 62 : if (obj->args[i].name_long == NULL)
305 : : break;
306 [ - - + + ]: 33 : if (is_arg_positional(arg))
307 : 7 : count++;
308 : : }
309 : :
310 : : return count;
311 : : }
312 : :
313 : : static struct rte_argparse_arg *
314 : : find_position_arg(struct rte_argparse *obj, uint32_t index)
315 : : {
316 : : struct rte_argparse_arg *arg;
317 : : uint32_t count = 0;
318 : : uint32_t i;
319 : :
320 : 2 : for (i = 0; /* NULL */; i++) {
321 : 9 : arg = &obj->args[i];
322 [ + - ]: 9 : if (arg->name_long == NULL)
323 : : break;
324 [ - + ]: 9 : if (!is_arg_positional(arg))
325 : 0 : continue;
326 : 9 : count++;
327 [ + + ]: 9 : if (count == index)
328 : : return arg;
329 : : }
330 : :
331 : : return NULL;
332 : : }
333 : :
334 : : static bool
335 : 24 : is_arg_match(struct rte_argparse_arg *arg, const char *curr_argv, uint32_t len)
336 : : {
337 [ + + - + ]: 24 : if (strlen(arg->name_long) == len && strncmp(arg->name_long, curr_argv, len) == 0)
338 : : return true;
339 : :
340 [ + - ]: 15 : if (arg->name_short == NULL)
341 : : return false;
342 : :
343 [ + + + - ]: 15 : if (strlen(arg->name_short) == len && strncmp(arg->name_short, curr_argv, len) == 0)
344 : 13 : return true;
345 : :
346 : : return false;
347 : : }
348 : :
349 : : static struct rte_argparse_arg *
350 : 23 : find_option_arg(struct rte_argparse *obj, const char *curr_argv, const char *has_equal,
351 : : const char **arg_name)
352 : : {
353 [ + + ]: 23 : uint32_t len = strlen(curr_argv) - (has_equal != NULL ? strlen(has_equal) : 0);
354 : : struct rte_argparse_arg *arg;
355 : : uint32_t i;
356 : : bool match;
357 : :
358 : 2 : for (i = 0; /* nothing */; i++) {
359 : 25 : arg = &obj->args[i];
360 [ + + ]: 25 : if (arg->name_long == NULL)
361 : : break;
362 : 24 : match = is_arg_match(arg, curr_argv, len);
363 [ + + ]: 24 : if (match) {
364 : : /* Obtains the exact matching name (long or short). */
365 [ + + ]: 22 : *arg_name = len > 2 ? arg->name_long : arg->name_short;
366 : 22 : return arg;
367 : : }
368 : : }
369 : :
370 : : return NULL;
371 : : }
372 : :
373 : : static int
374 : 17 : parse_arg_int(struct rte_argparse_arg *arg, const char *value)
375 : : {
376 : 17 : char *s = NULL;
377 : :
378 [ + + ]: 17 : if (value == NULL) {
379 : 4 : *(int *)arg->val_saver = (int)(intptr_t)arg->val_set;
380 : 4 : return 0;
381 : : }
382 : :
383 : 13 : errno = 0;
384 : 13 : *(int *)arg->val_saver = strtol(value, &s, 0);
385 [ + + ]: 13 : if (errno == ERANGE) {
386 : 1 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
387 : 1 : return -EINVAL;
388 : : }
389 : :
390 [ + + ]: 12 : if (s[0] != '\0') {
391 : 5 : ARGPARSE_LOG(ERR, "argument %s expect an integer value!", arg->name_long);
392 : 5 : return -EINVAL;
393 : : }
394 : :
395 : : return 0;
396 : : }
397 : :
398 : : static int
399 : 4 : parse_arg_u8(struct rte_argparse_arg *arg, const char *value)
400 : : {
401 : : unsigned long val;
402 : 4 : char *s = NULL;
403 : :
404 [ - + ]: 4 : if (value == NULL) {
405 : 0 : *(uint8_t *)arg->val_saver = (uint8_t)(intptr_t)arg->val_set;
406 : 0 : return 0;
407 : : }
408 : :
409 : 4 : errno = 0;
410 : 4 : val = strtoul(value, &s, 0);
411 [ + + + + ]: 4 : if (errno == ERANGE || val > UINT8_MAX) {
412 : 2 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
413 : 2 : return -EINVAL;
414 : : }
415 : :
416 [ + + ]: 2 : if (s[0] != '\0') {
417 : 1 : ARGPARSE_LOG(ERR, "argument %s expect an uint8 value!", arg->name_long);
418 : 1 : return -EINVAL;
419 : : }
420 : :
421 : 1 : *(uint8_t *)arg->val_saver = val;
422 : :
423 : 1 : return 0;
424 : : }
425 : :
426 : : static int
427 : 4 : parse_arg_u16(struct rte_argparse_arg *arg, const char *value)
428 : : {
429 : : unsigned long val;
430 : 4 : char *s = NULL;
431 : :
432 [ - + ]: 4 : if (value == NULL) {
433 : 0 : *(uint16_t *)arg->val_saver = (uint16_t)(intptr_t)arg->val_set;
434 : 0 : return 0;
435 : : }
436 : :
437 : 4 : errno = 0;
438 : 4 : val = strtoul(value, &s, 0);
439 [ + + + + ]: 4 : if (errno == ERANGE || val > UINT16_MAX) {
440 : 2 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
441 : 2 : return -EINVAL;
442 : : }
443 : :
444 [ + + ]: 2 : if (s[0] != '\0') {
445 : 1 : ARGPARSE_LOG(ERR, "argument %s expect an uint16 value!", arg->name_long);
446 : 1 : return -EINVAL;
447 : : }
448 : :
449 : 1 : *(uint16_t *)arg->val_saver = val;
450 : :
451 : 1 : return 0;
452 : : }
453 : :
454 : : static int
455 : 4 : parse_arg_u32(struct rte_argparse_arg *arg, const char *value)
456 : : {
457 : : unsigned long val;
458 : 4 : char *s = NULL;
459 : :
460 [ - + ]: 4 : if (value == NULL) {
461 : 0 : *(uint32_t *)arg->val_saver = (uint32_t)(intptr_t)arg->val_set;
462 : 0 : return 0;
463 : : }
464 : :
465 : 4 : errno = 0;
466 : 4 : val = strtoul(value, &s, 0);
467 [ + + + + ]: 4 : if (errno == ERANGE || val > UINT32_MAX) {
468 : 2 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
469 : 2 : return -EINVAL;
470 : : }
471 : :
472 [ + + ]: 2 : if (s[0] != '\0') {
473 : 1 : ARGPARSE_LOG(ERR, "argument %s expect an uint32 value!", arg->name_long);
474 : 1 : return -EINVAL;
475 : : }
476 : :
477 : 1 : *(uint32_t *)arg->val_saver = val;
478 : :
479 : 1 : return 0;
480 : : }
481 : :
482 : : static int
483 : 3 : parse_arg_u64(struct rte_argparse_arg *arg, const char *value)
484 : : {
485 : : unsigned long val;
486 : 3 : char *s = NULL;
487 : :
488 [ - + ]: 3 : if (value == NULL) {
489 : 0 : *(uint64_t *)arg->val_saver = (uint64_t)(intptr_t)arg->val_set;
490 : 0 : return 0;
491 : : }
492 : :
493 : 3 : errno = 0;
494 : 3 : val = strtoull(value, &s, 0);
495 [ + + ]: 3 : if (errno == ERANGE) {
496 : 1 : ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
497 : 1 : return -EINVAL;
498 : : }
499 : :
500 [ + + ]: 2 : if (s[0] != '\0') {
501 : 1 : ARGPARSE_LOG(ERR, "argument %s expect an uint64 value!", arg->name_long);
502 : 1 : return -EINVAL;
503 : : }
504 : :
505 : 1 : *(uint64_t *)arg->val_saver = val;
506 : :
507 : 1 : return 0;
508 : : }
509 : :
510 : : static int
511 : : parse_arg_autosave(struct rte_argparse_arg *arg, const char *value)
512 : : {
513 : : static struct {
514 : : int (*f_parse_type)(struct rte_argparse_arg *arg, const char *value);
515 : : } map[] = {
516 : : /* Sort by RTE_ARGPARSE_ARG_VALUE_XXX. */
517 : : { NULL },
518 : : { parse_arg_int },
519 : : { parse_arg_u8 },
520 : : { parse_arg_u16 },
521 : : { parse_arg_u32 },
522 : : { parse_arg_u64 },
523 : : };
524 : : uint32_t index = arg_attr_val_type(arg);
525 : : int ret = -EINVAL;
526 : :
527 [ + - ]: 14 : if (index > 0 && index < RTE_DIM(map))
528 : 32 : ret = map[index].f_parse_type(arg, value);
529 : :
530 : : return ret;
531 : : }
532 : :
533 : : /* arg_parse indicates the name entered by the user, which can be long-name or short-name. */
534 : : static int
535 : 28 : parse_arg_val(struct rte_argparse *obj, const char *arg_name,
536 : : struct rte_argparse_arg *arg, char *value)
537 : : {
538 : : int ret;
539 : :
540 [ + + ]: 28 : if (arg->val_saver == NULL)
541 : 14 : ret = obj->callback((uint32_t)(uintptr_t)arg->val_set, value, obj->opaque);
542 : : else
543 : : ret = parse_arg_autosave(arg, value);
544 [ + + ]: 28 : if (ret != 0) {
545 : 7 : ARGPARSE_LOG(ERR, "argument %s parse value fail!", arg_name);
546 : 7 : return ret;
547 : : }
548 : :
549 : : return 0;
550 : : }
551 : :
552 : : static bool
553 : 23 : is_help(const char *curr_argv)
554 : : {
555 [ + - + - ]: 23 : return strcmp(curr_argv, "-h") == 0 || strcmp(curr_argv, "--help") == 0;
556 : : }
557 : :
558 : : static int
559 : 29 : parse_args(struct rte_argparse *obj, int argc, char **argv, bool *show_help)
560 : : {
561 : : uint32_t position_count = calc_position_count(obj);
562 : : struct rte_argparse_arg *arg;
563 : : uint32_t position_index = 0;
564 : : const char *arg_name;
565 : : char *curr_argv;
566 : : char *has_equal;
567 : : char *value;
568 : : int ret;
569 : : int i;
570 : :
571 [ + + ]: 50 : for (i = 1; i < argc; i++) {
572 : 32 : curr_argv = argv[i];
573 [ + + ]: 32 : if (curr_argv[0] != '-') {
574 : : /* process positional parameters. */
575 : 9 : position_index++;
576 [ + + ]: 9 : if (position_index > position_count) {
577 : 2 : ARGPARSE_LOG(ERR, "too much positional argument %s!", curr_argv);
578 : 2 : return -EINVAL;
579 : : }
580 : : arg = find_position_arg(obj, position_index);
581 : 7 : ret = parse_arg_val(obj, arg->name_long, arg, curr_argv);
582 [ + + ]: 7 : if (ret != 0)
583 : 2 : return ret;
584 : 5 : continue;
585 : : }
586 : :
587 : : /* process optional parameters. */
588 [ - + ]: 23 : if (is_help(curr_argv)) {
589 : 0 : *show_help = true;
590 : 0 : continue;
591 : : }
592 : :
593 : 23 : has_equal = strchr(curr_argv, '=');
594 : 23 : arg_name = NULL;
595 : 23 : arg = find_option_arg(obj, curr_argv, has_equal, &arg_name);
596 [ + + - + ]: 23 : if (arg == NULL || arg_name == NULL) {
597 : 1 : ARGPARSE_LOG(ERR, "unknown argument %s!", curr_argv);
598 : 1 : return -EINVAL;
599 : : }
600 : :
601 [ - + - - ]: 22 : if ((arg->flags & ARG_ATTR_FLAG_PARSED_MASK) && !arg_attr_flag_multi(arg)) {
602 : 0 : ARGPARSE_LOG(ERR, "argument %s should not occur multiple!",
603 : : arg_name);
604 : 0 : return -EINVAL;
605 : : }
606 : :
607 [ + + ]: 22 : value = (has_equal != NULL ? has_equal + 1 : NULL);
608 [ + + ]: 22 : if (arg_attr_has_val(arg) == RTE_ARGPARSE_ARG_NO_VALUE) {
609 [ - + ]: 4 : if (value != NULL) {
610 : 0 : ARGPARSE_LOG(ERR, "argument %s should not take value!",
611 : : arg_name);
612 : 0 : return -EINVAL;
613 : : }
614 [ + + ]: 18 : } else if (arg_attr_has_val(arg) == RTE_ARGPARSE_ARG_REQUIRED_VALUE) {
615 [ + - ]: 7 : if (value == NULL) {
616 [ + + ]: 7 : if (i >= argc - 1) {
617 : 1 : ARGPARSE_LOG(ERR, "argument %s doesn't have value!",
618 : : arg_name);
619 : 1 : return -EINVAL;
620 : : }
621 : : /* Set value and make i move next. */
622 : 6 : value = argv[++i];
623 : : }
624 : : } else {
625 : : /* Do nothing, because it's optional value, only support arg=val or arg. */
626 : : }
627 : :
628 : 21 : ret = parse_arg_val(obj, arg_name, arg, value);
629 [ + + ]: 21 : if (ret != 0)
630 : 5 : return ret;
631 : :
632 : : /* This argument parsed success! then mark it parsed. */
633 : 16 : arg->flags |= ARG_ATTR_FLAG_PARSED_MASK;
634 : : }
635 : :
636 : : return 0;
637 : : }
638 : :
639 : : static uint32_t
640 : 0 : calc_help_align(const struct rte_argparse *obj)
641 : : {
642 : : const struct rte_argparse_arg *arg;
643 : : uint32_t width = 12; /* Default "-h, --help " len. */
644 : : uint32_t len;
645 : : uint32_t i;
646 : :
647 : 0 : for (i = 0; /* NULL */; i++) {
648 : 0 : arg = &obj->args[i];
649 [ # # ]: 0 : if (arg->name_long == NULL)
650 : : break;
651 : 0 : len = strlen(arg->name_long);
652 [ # # # # ]: 0 : if (is_arg_optional(arg) && arg->name_short != NULL) {
653 : 0 : len += strlen(", ");
654 : 0 : len += strlen(arg->name_short);
655 : : }
656 : 0 : width = RTE_MAX(width, 1 + len + 2); /* start with 1 & end with 2 space. */
657 : : }
658 : :
659 : 0 : return width;
660 : : }
661 : :
662 : : static void
663 : 0 : show_oneline_help(const struct rte_argparse_arg *arg, uint32_t width)
664 : : {
665 : : uint32_t len = 0;
666 : : uint32_t i;
667 : :
668 [ # # ]: 0 : if (arg->name_short != NULL)
669 : 0 : len = printf(" %s,", arg->name_short);
670 : 0 : len += printf(" %s", arg->name_long);
671 : :
672 [ # # ]: 0 : for (i = len; i < width; i++)
673 : : printf(" ");
674 : :
675 : 0 : printf("%s\n", arg->help);
676 : 0 : }
677 : :
678 : : static void
679 : 0 : show_args_pos_help(const struct rte_argparse *obj, uint32_t align)
680 : : {
681 : : uint32_t position_count = calc_position_count(obj);
682 : : const struct rte_argparse_arg *arg;
683 : : uint32_t i;
684 : :
685 [ # # ]: 0 : if (position_count == 0)
686 : : return;
687 : :
688 : : printf("\npositional arguments:\n");
689 : 0 : for (i = 0; /* NULL */; i++) {
690 : 0 : arg = &obj->args[i];
691 [ # # ]: 0 : if (arg->name_long == NULL)
692 : : break;
693 [ # # ]: 0 : if (!is_arg_positional(arg))
694 : 0 : continue;
695 : 0 : show_oneline_help(arg, align);
696 : : }
697 : : }
698 : :
699 : : static void
700 : 0 : show_args_opt_help(const struct rte_argparse *obj, uint32_t align)
701 : : {
702 : : static const struct rte_argparse_arg help = {
703 : : .name_long = "--help",
704 : : .name_short = "-h",
705 : : .help = "show this help message and exit.",
706 : : };
707 : : const struct rte_argparse_arg *arg;
708 : : uint32_t i;
709 : :
710 : : printf("\noptions:\n");
711 : 0 : show_oneline_help(&help, align);
712 : 0 : for (i = 0; /* NULL */; i++) {
713 : 0 : arg = &obj->args[i];
714 [ # # ]: 0 : if (arg->name_long == NULL)
715 : : break;
716 [ # # ]: 0 : if (!is_arg_optional(arg))
717 : 0 : continue;
718 : 0 : show_oneline_help(arg, align);
719 : : }
720 : 0 : }
721 : :
722 : : static void
723 : 0 : show_args_help(const struct rte_argparse *obj)
724 : : {
725 : 0 : uint32_t align = calc_help_align(obj);
726 : :
727 : 0 : printf("usage: %s %s\n", obj->prog_name, obj->usage);
728 [ # # ]: 0 : if (obj->descriptor != NULL)
729 : : printf("\ndescriptor: %s\n", obj->descriptor);
730 : :
731 : 0 : show_args_pos_help(obj, align);
732 : 0 : show_args_opt_help(obj, align);
733 : :
734 [ # # ]: 0 : if (obj->epilog != NULL)
735 : : printf("\n%s\n", obj->epilog);
736 : : else
737 : : printf("\n");
738 : 0 : }
739 : :
740 : : int
741 : 53 : rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv)
742 : : {
743 : 53 : bool show_help = false;
744 : : int ret;
745 : :
746 : 53 : ret = verify_argparse(obj);
747 [ + + ]: 53 : if (ret != 0)
748 : 24 : goto error;
749 : :
750 : 29 : ret = parse_args(obj, argc, argv, &show_help);
751 [ + + ]: 29 : if (ret != 0)
752 : 11 : goto error;
753 : :
754 [ - + ]: 18 : if (show_help) {
755 : 0 : show_args_help(obj);
756 : 0 : exit(0);
757 : : }
758 : :
759 : : return 0;
760 : :
761 : 35 : error:
762 [ - + ]: 35 : if (obj->exit_on_error)
763 : 0 : exit(ret);
764 : : return ret;
765 : : }
766 : :
767 : : int
768 : 18 : rte_argparse_parse_type(const char *str, uint64_t val_type, void *val)
769 : : {
770 : : uint32_t cmp_max = RTE_FIELD_GET64(RTE_ARGPARSE_VAL_TYPE_BITMASK,
771 : : RTE_ARGPARSE_ARG_VALUE_MAX);
772 : 18 : struct rte_argparse_arg arg = {
773 : : .name_long = str,
774 : : .name_short = NULL,
775 : : .val_saver = val,
776 : : .val_set = NULL,
777 : : .flags = val_type,
778 : : };
779 : : uint32_t value_type = arg_attr_val_type(&arg);
780 : :
781 [ + - ]: 18 : if (value_type == 0 || value_type >= cmp_max)
782 : : return -EINVAL;
783 : :
784 : 18 : return parse_arg_autosave(&arg, str);
785 : : }
|