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