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