xref: /dpdk/lib/argparse/rte_argparse.c (revision f48e4eed4aebba5b61565fbf8515fd723b53cd0c)
1e3e579f5SChengwen Feng /* SPDX-License-Identifier: BSD-3-Clause
2e3e579f5SChengwen Feng  * Copyright(c) 2024 HiSilicon Limited
3e3e579f5SChengwen Feng  */
4e3e579f5SChengwen Feng 
56c5c6571SChengwen Feng #include <errno.h>
66c5c6571SChengwen Feng #include <stdlib.h>
76c5c6571SChengwen Feng #include <string.h>
86c5c6571SChengwen Feng 
96c5c6571SChengwen Feng #include <rte_log.h>
106c5c6571SChengwen Feng 
11e3e579f5SChengwen Feng #include "rte_argparse.h"
12e3e579f5SChengwen Feng 
136c5c6571SChengwen Feng RTE_LOG_REGISTER_DEFAULT(rte_argparse_logtype, INFO);
146c5c6571SChengwen Feng #define RTE_LOGTYPE_ARGPARSE rte_argparse_logtype
156c5c6571SChengwen Feng #define ARGPARSE_LOG(level, ...) \
166c5c6571SChengwen Feng 	RTE_LOG_LINE(level, ARGPARSE, "" __VA_ARGS__)
176c5c6571SChengwen Feng 
186c5c6571SChengwen Feng #define ARG_ATTR_FLAG_PARSED_MASK	RTE_BIT64(63)
196c5c6571SChengwen Feng 
206c5c6571SChengwen Feng static inline bool
216c5c6571SChengwen Feng is_arg_optional(const struct rte_argparse_arg *arg)
226c5c6571SChengwen Feng {
236c5c6571SChengwen Feng 	return arg->name_long[0] == '-';
246c5c6571SChengwen Feng }
256c5c6571SChengwen Feng 
266c5c6571SChengwen Feng static inline bool
276c5c6571SChengwen Feng is_arg_positional(const struct rte_argparse_arg *arg)
286c5c6571SChengwen Feng {
296c5c6571SChengwen Feng 	return arg->name_long[0] != '-';
306c5c6571SChengwen Feng }
316c5c6571SChengwen Feng 
326c5c6571SChengwen Feng static inline uint32_t
336c5c6571SChengwen Feng arg_attr_has_val(const struct rte_argparse_arg *arg)
346c5c6571SChengwen Feng {
35*f48e4eedSChengwen Feng 	return RTE_FIELD_GET64(RTE_ARGPARSE_HAS_VAL_BITMASK, arg->flags);
366c5c6571SChengwen Feng }
376c5c6571SChengwen Feng 
386c5c6571SChengwen Feng static inline uint32_t
396c5c6571SChengwen Feng arg_attr_val_type(const struct rte_argparse_arg *arg)
406c5c6571SChengwen Feng {
41*f48e4eedSChengwen Feng 	return RTE_FIELD_GET64(RTE_ARGPARSE_VAL_TYPE_BITMASK, arg->flags);
426c5c6571SChengwen Feng }
436c5c6571SChengwen Feng 
4431ed9f9fSChengwen Feng static inline bool
4531ed9f9fSChengwen Feng arg_attr_flag_multi(const struct rte_argparse_arg *arg)
4631ed9f9fSChengwen Feng {
47*f48e4eedSChengwen Feng 	return RTE_FIELD_GET64(RTE_ARGPARSE_ARG_SUPPORT_MULTI, arg->flags);
4831ed9f9fSChengwen Feng }
4931ed9f9fSChengwen Feng 
50*f48e4eedSChengwen Feng static inline uint64_t
516c5c6571SChengwen Feng arg_attr_unused_bits(const struct rte_argparse_arg *arg)
526c5c6571SChengwen Feng {
53*f48e4eedSChengwen Feng #define USED_BIT_MASK	(RTE_ARGPARSE_HAS_VAL_BITMASK | \
54*f48e4eedSChengwen Feng 			 RTE_ARGPARSE_VAL_TYPE_BITMASK | \
55*f48e4eedSChengwen Feng 			 RTE_ARGPARSE_ARG_SUPPORT_MULTI)
566c5c6571SChengwen Feng 	return arg->flags & ~USED_BIT_MASK;
576c5c6571SChengwen Feng }
586c5c6571SChengwen Feng 
596c5c6571SChengwen Feng static int
606c5c6571SChengwen Feng verify_arg_name(const struct rte_argparse_arg *arg)
616c5c6571SChengwen Feng {
626c5c6571SChengwen Feng 	if (is_arg_optional(arg)) {
636c5c6571SChengwen Feng 		if (strlen(arg->name_long) <= 3) {
646c5c6571SChengwen Feng 			ARGPARSE_LOG(ERR, "optional long name %s too short!", arg->name_long);
656c5c6571SChengwen Feng 			return -EINVAL;
666c5c6571SChengwen Feng 		}
676c5c6571SChengwen Feng 		if (arg->name_long[1] != '-') {
689b8df29bSChengwen Feng 			ARGPARSE_LOG(ERR, "optional long name %s doesn't start with '--'",
696c5c6571SChengwen Feng 				     arg->name_long);
706c5c6571SChengwen Feng 			return -EINVAL;
716c5c6571SChengwen Feng 		}
726c5c6571SChengwen Feng 		if (arg->name_long[2] == '-') {
736c5c6571SChengwen Feng 			ARGPARSE_LOG(ERR, "optional long name %s should not start with '---'",
746c5c6571SChengwen Feng 				     arg->name_long);
756c5c6571SChengwen Feng 			return -EINVAL;
766c5c6571SChengwen Feng 		}
776c5c6571SChengwen Feng 	}
786c5c6571SChengwen Feng 
796c5c6571SChengwen Feng 	if (arg->name_short == NULL)
806c5c6571SChengwen Feng 		return 0;
816c5c6571SChengwen Feng 
826c5c6571SChengwen Feng 	if (!is_arg_optional(arg)) {
836c5c6571SChengwen Feng 		ARGPARSE_LOG(ERR, "short name %s corresponding long name must be optional!",
846c5c6571SChengwen Feng 			     arg->name_short);
856c5c6571SChengwen Feng 		return -EINVAL;
866c5c6571SChengwen Feng 	}
876c5c6571SChengwen Feng 
886c5c6571SChengwen Feng 	if (strlen(arg->name_short) != 2 || arg->name_short[0] != '-' ||
896c5c6571SChengwen Feng 		arg->name_short[1] == '-') {
906c5c6571SChengwen Feng 		ARGPARSE_LOG(ERR, "short name %s must start with a hyphen (-) followed by an English letter",
916c5c6571SChengwen Feng 			     arg->name_short);
926c5c6571SChengwen Feng 		return -EINVAL;
936c5c6571SChengwen Feng 	}
946c5c6571SChengwen Feng 
956c5c6571SChengwen Feng 	return 0;
966c5c6571SChengwen Feng }
976c5c6571SChengwen Feng 
986c5c6571SChengwen Feng static int
996c5c6571SChengwen Feng verify_arg_help(const struct rte_argparse_arg *arg)
1006c5c6571SChengwen Feng {
1016c5c6571SChengwen Feng 	if (arg->help == NULL) {
1029b8df29bSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s doesn't have help info!", arg->name_long);
1036c5c6571SChengwen Feng 		return -EINVAL;
1046c5c6571SChengwen Feng 	}
1056c5c6571SChengwen Feng 
1066c5c6571SChengwen Feng 	return 0;
1076c5c6571SChengwen Feng }
1086c5c6571SChengwen Feng 
1096c5c6571SChengwen Feng static int
1106c5c6571SChengwen Feng verify_arg_has_val(const struct rte_argparse_arg *arg)
1116c5c6571SChengwen Feng {
1126c5c6571SChengwen Feng 	uint32_t has_val = arg_attr_has_val(arg);
1136c5c6571SChengwen Feng 
1146c5c6571SChengwen Feng 	if (is_arg_positional(arg)) {
1156c5c6571SChengwen Feng 		if (has_val == RTE_ARGPARSE_ARG_REQUIRED_VALUE)
1166c5c6571SChengwen Feng 			return 0;
1179b8df29bSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s is positional, must config required-val!",
1186c5c6571SChengwen Feng 			     arg->name_long);
1196c5c6571SChengwen Feng 		return -EINVAL;
1206c5c6571SChengwen Feng 	}
1216c5c6571SChengwen Feng 
1226c5c6571SChengwen Feng 	if (has_val == 0) {
1239b8df29bSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s is optional, has-value config wrong!",
1246c5c6571SChengwen Feng 			     arg->name_long);
1256c5c6571SChengwen Feng 		return -EINVAL;
1266c5c6571SChengwen Feng 	}
1276c5c6571SChengwen Feng 
1286c5c6571SChengwen Feng 	return 0;
1296c5c6571SChengwen Feng }
1306c5c6571SChengwen Feng 
1316c5c6571SChengwen Feng static int
1326c5c6571SChengwen Feng verify_arg_saver(const struct rte_argparse *obj, uint32_t index)
1336c5c6571SChengwen Feng {
134*f48e4eedSChengwen Feng 	uint32_t cmp_max = RTE_FIELD_GET64(RTE_ARGPARSE_VAL_TYPE_BITMASK,
135*f48e4eedSChengwen Feng 					   RTE_ARGPARSE_ARG_VALUE_MAX);
1366c5c6571SChengwen Feng 	const struct rte_argparse_arg *arg = &obj->args[index];
1376c5c6571SChengwen Feng 	uint32_t val_type = arg_attr_val_type(arg);
1386c5c6571SChengwen Feng 	uint32_t has_val = arg_attr_has_val(arg);
1396c5c6571SChengwen Feng 
1406c5c6571SChengwen Feng 	if (arg->val_saver == NULL) {
1416c5c6571SChengwen Feng 		if (val_type != 0) {
1429b8df29bSChengwen Feng 			ARGPARSE_LOG(ERR, "argument %s parsed by callback, value-type should not be set!",
1436c5c6571SChengwen Feng 				     arg->name_long);
1446c5c6571SChengwen Feng 			return -EINVAL;
1456c5c6571SChengwen Feng 		}
1466c5c6571SChengwen Feng 
1476c5c6571SChengwen Feng 		if (obj->callback == NULL) {
1489b8df29bSChengwen Feng 			ARGPARSE_LOG(ERR, "argument %s parsed by callback, but callback is NULL!",
1496c5c6571SChengwen Feng 				     arg->name_long);
1506c5c6571SChengwen Feng 			return -EINVAL;
1516c5c6571SChengwen Feng 		}
1526c5c6571SChengwen Feng 
1536c5c6571SChengwen Feng 		return 0;
1546c5c6571SChengwen Feng 	}
1556c5c6571SChengwen Feng 
1566c5c6571SChengwen Feng 	if (val_type == 0 || val_type >= cmp_max) {
1579b8df29bSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s value-type config wrong!", arg->name_long);
1586c5c6571SChengwen Feng 		return -EINVAL;
1596c5c6571SChengwen Feng 	}
1606c5c6571SChengwen Feng 
1616c5c6571SChengwen Feng 	if (has_val == RTE_ARGPARSE_ARG_REQUIRED_VALUE && arg->val_set != NULL) {
1629b8df29bSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s has required value, value-set should be NULL!",
1636c5c6571SChengwen Feng 			     arg->name_long);
1646c5c6571SChengwen Feng 		return -EINVAL;
1656c5c6571SChengwen Feng 	}
1666c5c6571SChengwen Feng 
1676c5c6571SChengwen Feng 	return 0;
1686c5c6571SChengwen Feng }
1696c5c6571SChengwen Feng 
1706c5c6571SChengwen Feng static int
1716c5c6571SChengwen Feng verify_arg_flags(const struct rte_argparse *obj, uint32_t index)
1726c5c6571SChengwen Feng {
1736c5c6571SChengwen Feng 	const struct rte_argparse_arg *arg = &obj->args[index];
174*f48e4eedSChengwen Feng 	uint64_t unused_bits = arg_attr_unused_bits(arg);
1756c5c6571SChengwen Feng 
1766c5c6571SChengwen Feng 	if (unused_bits != 0) {
1779b8df29bSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s flags unused bits should not be set!",
1789b8df29bSChengwen Feng 			     arg->name_long);
1796c5c6571SChengwen Feng 		return -EINVAL;
1806c5c6571SChengwen Feng 	}
1816c5c6571SChengwen Feng 
1826c5c6571SChengwen Feng 	if (!(arg->flags & RTE_ARGPARSE_ARG_SUPPORT_MULTI))
1836c5c6571SChengwen Feng 		return 0;
1846c5c6571SChengwen Feng 
1856c5c6571SChengwen Feng 	if (is_arg_positional(arg)) {
1866c5c6571SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s is positional, don't support multiple times!",
1876c5c6571SChengwen Feng 			     arg->name_long);
1886c5c6571SChengwen Feng 		return -EINVAL;
1896c5c6571SChengwen Feng 	}
1906c5c6571SChengwen Feng 
1916c5c6571SChengwen Feng 	if (arg->val_saver != NULL) {
1929b8df29bSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s supports multiple times, should use callback to parse!",
1936c5c6571SChengwen Feng 			     arg->name_long);
1946c5c6571SChengwen Feng 		return -EINVAL;
1956c5c6571SChengwen Feng 	}
1966c5c6571SChengwen Feng 
1976c5c6571SChengwen Feng 	return 0;
1986c5c6571SChengwen Feng }
1996c5c6571SChengwen Feng 
2006c5c6571SChengwen Feng static int
2016c5c6571SChengwen Feng verify_arg_repeat(const struct rte_argparse *self, uint32_t index)
2026c5c6571SChengwen Feng {
2036c5c6571SChengwen Feng 	const struct rte_argparse_arg *arg = &self->args[index];
2046c5c6571SChengwen Feng 	uint32_t i;
2056c5c6571SChengwen Feng 
2066c5c6571SChengwen Feng 	for (i = 0; i < index; i++) {
2076c5c6571SChengwen Feng 		if (!strcmp(arg->name_long, self->args[i].name_long)) {
2086c5c6571SChengwen Feng 			ARGPARSE_LOG(ERR, "argument %s repeat!", arg->name_long);
2096c5c6571SChengwen Feng 			return -EINVAL;
2106c5c6571SChengwen Feng 		}
2116c5c6571SChengwen Feng 	}
2126c5c6571SChengwen Feng 
2136c5c6571SChengwen Feng 	if (arg->name_short == NULL)
2146c5c6571SChengwen Feng 		return 0;
2156c5c6571SChengwen Feng 
2166c5c6571SChengwen Feng 	for (i = 0; i < index; i++) {
2176c5c6571SChengwen Feng 		if (self->args[i].name_short == NULL)
2186c5c6571SChengwen Feng 			continue;
2196c5c6571SChengwen Feng 		if (!strcmp(arg->name_short, self->args[i].name_short)) {
2206c5c6571SChengwen Feng 			ARGPARSE_LOG(ERR, "argument %s repeat!", arg->name_short);
2216c5c6571SChengwen Feng 			return -EINVAL;
2226c5c6571SChengwen Feng 		}
2236c5c6571SChengwen Feng 	}
2246c5c6571SChengwen Feng 
2256c5c6571SChengwen Feng 	return 0;
2266c5c6571SChengwen Feng }
2276c5c6571SChengwen Feng 
2286c5c6571SChengwen Feng static int
2296c5c6571SChengwen Feng verify_argparse_arg(const struct rte_argparse *obj, uint32_t index)
2306c5c6571SChengwen Feng {
2316c5c6571SChengwen Feng 	const struct rte_argparse_arg *arg = &obj->args[index];
2326c5c6571SChengwen Feng 	int ret;
2336c5c6571SChengwen Feng 
2346c5c6571SChengwen Feng 	ret = verify_arg_name(arg);
2356c5c6571SChengwen Feng 	if (ret != 0)
2366c5c6571SChengwen Feng 		return ret;
2376c5c6571SChengwen Feng 
2386c5c6571SChengwen Feng 	ret = verify_arg_help(arg);
2396c5c6571SChengwen Feng 	if (ret != 0)
2406c5c6571SChengwen Feng 		return ret;
2416c5c6571SChengwen Feng 
2426c5c6571SChengwen Feng 	ret = verify_arg_has_val(arg);
2436c5c6571SChengwen Feng 	if (ret != 0)
2446c5c6571SChengwen Feng 		return ret;
2456c5c6571SChengwen Feng 
2466c5c6571SChengwen Feng 	ret = verify_arg_saver(obj, index);
2476c5c6571SChengwen Feng 	if (ret != 0)
2486c5c6571SChengwen Feng 		return ret;
2496c5c6571SChengwen Feng 
2506c5c6571SChengwen Feng 	ret = verify_arg_flags(obj, index);
2516c5c6571SChengwen Feng 	if (ret != 0)
2526c5c6571SChengwen Feng 		return ret;
2536c5c6571SChengwen Feng 
2546c5c6571SChengwen Feng 	ret = verify_arg_repeat(obj, index);
2556c5c6571SChengwen Feng 	if (ret != 0)
2566c5c6571SChengwen Feng 		return ret;
2576c5c6571SChengwen Feng 
2586c5c6571SChengwen Feng 	return 0;
2596c5c6571SChengwen Feng }
2606c5c6571SChengwen Feng 
2616c5c6571SChengwen Feng static int
2626c5c6571SChengwen Feng verify_argparse(const struct rte_argparse *obj)
2636c5c6571SChengwen Feng {
2646c5c6571SChengwen Feng 	uint32_t idx;
2656c5c6571SChengwen Feng 	int ret;
2666c5c6571SChengwen Feng 
2676c5c6571SChengwen Feng 	if (obj->prog_name == NULL) {
2686c5c6571SChengwen Feng 		ARGPARSE_LOG(ERR, "program name is NULL!");
2696c5c6571SChengwen Feng 		return -EINVAL;
2706c5c6571SChengwen Feng 	}
2716c5c6571SChengwen Feng 
2726c5c6571SChengwen Feng 	if (obj->usage == NULL) {
2736c5c6571SChengwen Feng 		ARGPARSE_LOG(ERR, "usage is NULL!");
2746c5c6571SChengwen Feng 		return -EINVAL;
2756c5c6571SChengwen Feng 	}
2766c5c6571SChengwen Feng 
2776c5c6571SChengwen Feng 	for (idx = 0; idx < RTE_DIM(obj->reserved); idx++) {
2786c5c6571SChengwen Feng 		if (obj->reserved[idx] != 0) {
2796c5c6571SChengwen Feng 			ARGPARSE_LOG(ERR, "reserved field must be zero!");
2806c5c6571SChengwen Feng 			return -EINVAL;
2816c5c6571SChengwen Feng 		}
2826c5c6571SChengwen Feng 	}
2836c5c6571SChengwen Feng 
2846c5c6571SChengwen Feng 	idx = 0;
2856c5c6571SChengwen Feng 	while (obj->args[idx].name_long != NULL) {
2866c5c6571SChengwen Feng 		ret = verify_argparse_arg(obj, idx);
2876c5c6571SChengwen Feng 		if (ret != 0)
2886c5c6571SChengwen Feng 			return ret;
2896c5c6571SChengwen Feng 		idx++;
2906c5c6571SChengwen Feng 	}
2916c5c6571SChengwen Feng 
2926c5c6571SChengwen Feng 	return 0;
2936c5c6571SChengwen Feng }
2946c5c6571SChengwen Feng 
29531ed9f9fSChengwen Feng static uint32_t
29631ed9f9fSChengwen Feng calc_position_count(const struct rte_argparse *obj)
29731ed9f9fSChengwen Feng {
29831ed9f9fSChengwen Feng 	const struct rte_argparse_arg *arg;
29931ed9f9fSChengwen Feng 	uint32_t count = 0;
30031ed9f9fSChengwen Feng 	uint32_t i;
30131ed9f9fSChengwen Feng 
30231ed9f9fSChengwen Feng 	for (i = 0; /* NULL */; i++) {
30331ed9f9fSChengwen Feng 		arg = &obj->args[i];
30431ed9f9fSChengwen Feng 		if (obj->args[i].name_long == NULL)
30531ed9f9fSChengwen Feng 			break;
30631ed9f9fSChengwen Feng 		if (is_arg_positional(arg))
30731ed9f9fSChengwen Feng 			count++;
30831ed9f9fSChengwen Feng 	}
30931ed9f9fSChengwen Feng 
31031ed9f9fSChengwen Feng 	return count;
31131ed9f9fSChengwen Feng }
31231ed9f9fSChengwen Feng 
31331ed9f9fSChengwen Feng static struct rte_argparse_arg *
31431ed9f9fSChengwen Feng find_position_arg(struct rte_argparse *obj, uint32_t index)
31531ed9f9fSChengwen Feng {
31631ed9f9fSChengwen Feng 	struct rte_argparse_arg *arg;
31731ed9f9fSChengwen Feng 	uint32_t count = 0;
31831ed9f9fSChengwen Feng 	uint32_t i;
31931ed9f9fSChengwen Feng 
32031ed9f9fSChengwen Feng 	for (i = 0; /* NULL */; i++) {
32131ed9f9fSChengwen Feng 		arg = &obj->args[i];
32231ed9f9fSChengwen Feng 		if (arg->name_long == NULL)
32331ed9f9fSChengwen Feng 			break;
32431ed9f9fSChengwen Feng 		if (!is_arg_positional(arg))
32531ed9f9fSChengwen Feng 			continue;
32631ed9f9fSChengwen Feng 		count++;
32731ed9f9fSChengwen Feng 		if (count == index)
32831ed9f9fSChengwen Feng 			return arg;
32931ed9f9fSChengwen Feng 	}
33031ed9f9fSChengwen Feng 
33131ed9f9fSChengwen Feng 	return NULL;
33231ed9f9fSChengwen Feng }
33331ed9f9fSChengwen Feng 
33431ed9f9fSChengwen Feng static bool
33531ed9f9fSChengwen Feng is_arg_match(struct rte_argparse_arg *arg, const char *curr_argv, uint32_t len)
33631ed9f9fSChengwen Feng {
33731ed9f9fSChengwen Feng 	if (strlen(arg->name_long) == len && strncmp(arg->name_long, curr_argv, len) == 0)
33831ed9f9fSChengwen Feng 		return true;
33931ed9f9fSChengwen Feng 
34031ed9f9fSChengwen Feng 	if (arg->name_short == NULL)
34131ed9f9fSChengwen Feng 		return false;
34231ed9f9fSChengwen Feng 
34331ed9f9fSChengwen Feng 	if (strlen(arg->name_short) == len && strncmp(arg->name_short, curr_argv, len) == 0)
34431ed9f9fSChengwen Feng 		return true;
34531ed9f9fSChengwen Feng 
34631ed9f9fSChengwen Feng 	return false;
34731ed9f9fSChengwen Feng }
34831ed9f9fSChengwen Feng 
34931ed9f9fSChengwen Feng static struct rte_argparse_arg *
35031ed9f9fSChengwen Feng find_option_arg(struct rte_argparse *obj, const char *curr_argv, const char *has_equal,
35131ed9f9fSChengwen Feng 		const char **arg_name)
35231ed9f9fSChengwen Feng {
35331ed9f9fSChengwen Feng 	uint32_t len = strlen(curr_argv) - (has_equal != NULL ? strlen(has_equal) : 0);
35431ed9f9fSChengwen Feng 	struct rte_argparse_arg *arg;
35531ed9f9fSChengwen Feng 	uint32_t i;
35631ed9f9fSChengwen Feng 	bool match;
35731ed9f9fSChengwen Feng 
35831ed9f9fSChengwen Feng 	for (i = 0; /* nothing */; i++) {
35931ed9f9fSChengwen Feng 		arg = &obj->args[i];
36031ed9f9fSChengwen Feng 		if (arg->name_long == NULL)
36131ed9f9fSChengwen Feng 			break;
36231ed9f9fSChengwen Feng 		match = is_arg_match(arg, curr_argv, len);
36331ed9f9fSChengwen Feng 		if (match) {
36431ed9f9fSChengwen Feng 			/* Obtains the exact matching name (long or short). */
36531ed9f9fSChengwen Feng 			*arg_name = len > 2 ? arg->name_long : arg->name_short;
36631ed9f9fSChengwen Feng 			return arg;
36731ed9f9fSChengwen Feng 		}
36831ed9f9fSChengwen Feng 	}
36931ed9f9fSChengwen Feng 
37031ed9f9fSChengwen Feng 	return NULL;
37131ed9f9fSChengwen Feng }
37231ed9f9fSChengwen Feng 
37331ed9f9fSChengwen Feng static int
37431ed9f9fSChengwen Feng parse_arg_int(struct rte_argparse_arg *arg, const char *value)
37531ed9f9fSChengwen Feng {
37631ed9f9fSChengwen Feng 	char *s = NULL;
37731ed9f9fSChengwen Feng 
37831ed9f9fSChengwen Feng 	if (value == NULL) {
37931ed9f9fSChengwen Feng 		*(int *)arg->val_saver = (int)(intptr_t)arg->val_set;
38031ed9f9fSChengwen Feng 		return 0;
38131ed9f9fSChengwen Feng 	}
38231ed9f9fSChengwen Feng 
38331ed9f9fSChengwen Feng 	errno = 0;
38431ed9f9fSChengwen Feng 	*(int *)arg->val_saver = strtol(value, &s, 0);
38531ed9f9fSChengwen Feng 	if (errno == ERANGE) {
38631ed9f9fSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
38731ed9f9fSChengwen Feng 		return -EINVAL;
38831ed9f9fSChengwen Feng 	}
38931ed9f9fSChengwen Feng 
39031ed9f9fSChengwen Feng 	if (s[0] != '\0') {
39131ed9f9fSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s expect an integer value!", arg->name_long);
39231ed9f9fSChengwen Feng 		return -EINVAL;
39331ed9f9fSChengwen Feng 	}
39431ed9f9fSChengwen Feng 
39531ed9f9fSChengwen Feng 	return 0;
39631ed9f9fSChengwen Feng }
39731ed9f9fSChengwen Feng 
39831ed9f9fSChengwen Feng static int
3995357c248SChengwen Feng parse_arg_u8(struct rte_argparse_arg *arg, const char *value)
4005357c248SChengwen Feng {
4015357c248SChengwen Feng 	unsigned long val;
4025357c248SChengwen Feng 	char *s = NULL;
4035357c248SChengwen Feng 
4045357c248SChengwen Feng 	if (value == NULL) {
4055357c248SChengwen Feng 		*(uint8_t *)arg->val_saver = (uint8_t)(intptr_t)arg->val_set;
4065357c248SChengwen Feng 		return 0;
4075357c248SChengwen Feng 	}
4085357c248SChengwen Feng 
4095357c248SChengwen Feng 	errno = 0;
4105357c248SChengwen Feng 	val = strtoul(value, &s, 0);
4115357c248SChengwen Feng 	if (errno == ERANGE || val > UINT8_MAX) {
4125357c248SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
4135357c248SChengwen Feng 		return -EINVAL;
4145357c248SChengwen Feng 	}
4155357c248SChengwen Feng 
4165357c248SChengwen Feng 	if (s[0] != '\0') {
4175357c248SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s expect an uint8 value!", arg->name_long);
4185357c248SChengwen Feng 		return -EINVAL;
4195357c248SChengwen Feng 	}
4205357c248SChengwen Feng 
4215357c248SChengwen Feng 	*(uint8_t *)arg->val_saver = val;
4225357c248SChengwen Feng 
4235357c248SChengwen Feng 	return 0;
4245357c248SChengwen Feng }
4255357c248SChengwen Feng 
4265357c248SChengwen Feng static int
4275357c248SChengwen Feng parse_arg_u16(struct rte_argparse_arg *arg, const char *value)
4285357c248SChengwen Feng {
4295357c248SChengwen Feng 	unsigned long val;
4305357c248SChengwen Feng 	char *s = NULL;
4315357c248SChengwen Feng 
4325357c248SChengwen Feng 	if (value == NULL) {
4335357c248SChengwen Feng 		*(uint16_t *)arg->val_saver = (uint16_t)(intptr_t)arg->val_set;
4345357c248SChengwen Feng 		return 0;
4355357c248SChengwen Feng 	}
4365357c248SChengwen Feng 
4375357c248SChengwen Feng 	errno = 0;
4385357c248SChengwen Feng 	val = strtoul(value, &s, 0);
4395357c248SChengwen Feng 	if (errno == ERANGE || val > UINT16_MAX) {
4405357c248SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
4415357c248SChengwen Feng 		return -EINVAL;
4425357c248SChengwen Feng 	}
4435357c248SChengwen Feng 
4445357c248SChengwen Feng 	if (s[0] != '\0') {
4455357c248SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s expect an uint16 value!", arg->name_long);
4465357c248SChengwen Feng 		return -EINVAL;
4475357c248SChengwen Feng 	}
4485357c248SChengwen Feng 
4495357c248SChengwen Feng 	*(uint16_t *)arg->val_saver = val;
4505357c248SChengwen Feng 
4515357c248SChengwen Feng 	return 0;
4525357c248SChengwen Feng }
4535357c248SChengwen Feng 
4545357c248SChengwen Feng static int
4555357c248SChengwen Feng parse_arg_u32(struct rte_argparse_arg *arg, const char *value)
4565357c248SChengwen Feng {
4575357c248SChengwen Feng 	unsigned long val;
4585357c248SChengwen Feng 	char *s = NULL;
4595357c248SChengwen Feng 
4605357c248SChengwen Feng 	if (value == NULL) {
4615357c248SChengwen Feng 		*(uint32_t *)arg->val_saver = (uint32_t)(intptr_t)arg->val_set;
4625357c248SChengwen Feng 		return 0;
4635357c248SChengwen Feng 	}
4645357c248SChengwen Feng 
4655357c248SChengwen Feng 	errno = 0;
4665357c248SChengwen Feng 	val = strtoul(value, &s, 0);
4675357c248SChengwen Feng 	if (errno == ERANGE || val > UINT32_MAX) {
4685357c248SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
4695357c248SChengwen Feng 		return -EINVAL;
4705357c248SChengwen Feng 	}
4715357c248SChengwen Feng 
4725357c248SChengwen Feng 	if (s[0] != '\0') {
4735357c248SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s expect an uint32 value!", arg->name_long);
4745357c248SChengwen Feng 		return -EINVAL;
4755357c248SChengwen Feng 	}
4765357c248SChengwen Feng 
4775357c248SChengwen Feng 	*(uint32_t *)arg->val_saver = val;
4785357c248SChengwen Feng 
4795357c248SChengwen Feng 	return 0;
4805357c248SChengwen Feng }
4815357c248SChengwen Feng 
4825357c248SChengwen Feng static int
4835357c248SChengwen Feng parse_arg_u64(struct rte_argparse_arg *arg, const char *value)
4845357c248SChengwen Feng {
4855357c248SChengwen Feng 	unsigned long val;
4865357c248SChengwen Feng 	char *s = NULL;
4875357c248SChengwen Feng 
4885357c248SChengwen Feng 	if (value == NULL) {
4895357c248SChengwen Feng 		*(uint64_t *)arg->val_saver = (uint64_t)(intptr_t)arg->val_set;
4905357c248SChengwen Feng 		return 0;
4915357c248SChengwen Feng 	}
4925357c248SChengwen Feng 
4935357c248SChengwen Feng 	errno = 0;
4945357c248SChengwen Feng 	val = strtoull(value, &s, 0);
4955357c248SChengwen Feng 	if (errno == ERANGE) {
4965357c248SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s numerical out of range!", arg->name_long);
4975357c248SChengwen Feng 		return -EINVAL;
4985357c248SChengwen Feng 	}
4995357c248SChengwen Feng 
5005357c248SChengwen Feng 	if (s[0] != '\0') {
5015357c248SChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s expect an uint64 value!", arg->name_long);
5025357c248SChengwen Feng 		return -EINVAL;
5035357c248SChengwen Feng 	}
5045357c248SChengwen Feng 
5055357c248SChengwen Feng 	*(uint64_t *)arg->val_saver = val;
5065357c248SChengwen Feng 
5075357c248SChengwen Feng 	return 0;
5085357c248SChengwen Feng }
5095357c248SChengwen Feng 
5105357c248SChengwen Feng static int
51131ed9f9fSChengwen Feng parse_arg_autosave(struct rte_argparse_arg *arg, const char *value)
51231ed9f9fSChengwen Feng {
51331ed9f9fSChengwen Feng 	static struct {
51431ed9f9fSChengwen Feng 		int (*f_parse_type)(struct rte_argparse_arg *arg, const char *value);
51531ed9f9fSChengwen Feng 	} map[] = {
51631ed9f9fSChengwen Feng 		/* Sort by RTE_ARGPARSE_ARG_VALUE_XXX. */
51731ed9f9fSChengwen Feng 		{ NULL          },
51831ed9f9fSChengwen Feng 		{ parse_arg_int },
5195357c248SChengwen Feng 		{ parse_arg_u8  },
5205357c248SChengwen Feng 		{ parse_arg_u16 },
5215357c248SChengwen Feng 		{ parse_arg_u32 },
5225357c248SChengwen Feng 		{ parse_arg_u64 },
52331ed9f9fSChengwen Feng 	};
52431ed9f9fSChengwen Feng 	uint32_t index = arg_attr_val_type(arg);
52531ed9f9fSChengwen Feng 	int ret = -EINVAL;
52631ed9f9fSChengwen Feng 
52731ed9f9fSChengwen Feng 	if (index > 0 && index < RTE_DIM(map))
52831ed9f9fSChengwen Feng 		ret = map[index].f_parse_type(arg, value);
52931ed9f9fSChengwen Feng 
53031ed9f9fSChengwen Feng 	return ret;
53131ed9f9fSChengwen Feng }
53231ed9f9fSChengwen Feng 
5339b8df29bSChengwen Feng /* arg_parse indicates the name entered by the user, which can be long-name or short-name. */
53431ed9f9fSChengwen Feng static int
5359b8df29bSChengwen Feng parse_arg_val(struct rte_argparse *obj, const char *arg_name,
5369b8df29bSChengwen Feng 	      struct rte_argparse_arg *arg, char *value)
537e3e579f5SChengwen Feng {
5386c5c6571SChengwen Feng 	int ret;
5396c5c6571SChengwen Feng 
54031ed9f9fSChengwen Feng 	if (arg->val_saver == NULL)
54131ed9f9fSChengwen Feng 		ret = obj->callback((uint32_t)(uintptr_t)arg->val_set, value, obj->opaque);
54231ed9f9fSChengwen Feng 	else
54331ed9f9fSChengwen Feng 		ret = parse_arg_autosave(arg, value);
54431ed9f9fSChengwen Feng 	if (ret != 0) {
5459b8df29bSChengwen Feng 		ARGPARSE_LOG(ERR, "argument %s parse value fail!", arg_name);
54631ed9f9fSChengwen Feng 		return ret;
54731ed9f9fSChengwen Feng 	}
54831ed9f9fSChengwen Feng 
54931ed9f9fSChengwen Feng 	return 0;
55031ed9f9fSChengwen Feng }
55131ed9f9fSChengwen Feng 
55231ed9f9fSChengwen Feng static bool
55331ed9f9fSChengwen Feng is_help(const char *curr_argv)
55431ed9f9fSChengwen Feng {
55531ed9f9fSChengwen Feng 	return strcmp(curr_argv, "-h") == 0 || strcmp(curr_argv, "--help") == 0;
55631ed9f9fSChengwen Feng }
55731ed9f9fSChengwen Feng 
55831ed9f9fSChengwen Feng static int
55931ed9f9fSChengwen Feng parse_args(struct rte_argparse *obj, int argc, char **argv, bool *show_help)
56031ed9f9fSChengwen Feng {
56131ed9f9fSChengwen Feng 	uint32_t position_count = calc_position_count(obj);
56231ed9f9fSChengwen Feng 	struct rte_argparse_arg *arg;
56331ed9f9fSChengwen Feng 	uint32_t position_index = 0;
56431ed9f9fSChengwen Feng 	const char *arg_name;
56531ed9f9fSChengwen Feng 	char *curr_argv;
56631ed9f9fSChengwen Feng 	char *has_equal;
56731ed9f9fSChengwen Feng 	char *value;
56831ed9f9fSChengwen Feng 	int ret;
56931ed9f9fSChengwen Feng 	int i;
57031ed9f9fSChengwen Feng 
57131ed9f9fSChengwen Feng 	for (i = 1; i < argc; i++) {
57231ed9f9fSChengwen Feng 		curr_argv = argv[i];
57331ed9f9fSChengwen Feng 		if (curr_argv[0] != '-') {
57431ed9f9fSChengwen Feng 			/* process positional parameters. */
57531ed9f9fSChengwen Feng 			position_index++;
57631ed9f9fSChengwen Feng 			if (position_index > position_count) {
57731ed9f9fSChengwen Feng 				ARGPARSE_LOG(ERR, "too much positional argument %s!", curr_argv);
57831ed9f9fSChengwen Feng 				return -EINVAL;
57931ed9f9fSChengwen Feng 			}
58031ed9f9fSChengwen Feng 			arg = find_position_arg(obj, position_index);
5819b8df29bSChengwen Feng 			ret = parse_arg_val(obj, arg->name_long, arg, curr_argv);
58231ed9f9fSChengwen Feng 			if (ret != 0)
58331ed9f9fSChengwen Feng 				return ret;
58431ed9f9fSChengwen Feng 			continue;
58531ed9f9fSChengwen Feng 		}
58631ed9f9fSChengwen Feng 
58731ed9f9fSChengwen Feng 		/* process optional parameters. */
58831ed9f9fSChengwen Feng 		if (is_help(curr_argv)) {
58931ed9f9fSChengwen Feng 			*show_help = true;
59031ed9f9fSChengwen Feng 			continue;
59131ed9f9fSChengwen Feng 		}
59231ed9f9fSChengwen Feng 
59331ed9f9fSChengwen Feng 		has_equal = strchr(curr_argv, '=');
59431ed9f9fSChengwen Feng 		arg_name = NULL;
59531ed9f9fSChengwen Feng 		arg = find_option_arg(obj, curr_argv, has_equal, &arg_name);
59631ed9f9fSChengwen Feng 		if (arg == NULL || arg_name == NULL) {
59731ed9f9fSChengwen Feng 			ARGPARSE_LOG(ERR, "unknown argument %s!", curr_argv);
59831ed9f9fSChengwen Feng 			return -EINVAL;
59931ed9f9fSChengwen Feng 		}
60031ed9f9fSChengwen Feng 
60131ed9f9fSChengwen Feng 		if ((arg->flags & ARG_ATTR_FLAG_PARSED_MASK) && !arg_attr_flag_multi(arg)) {
60231ed9f9fSChengwen Feng 			ARGPARSE_LOG(ERR, "argument %s should not occur multiple!",
60331ed9f9fSChengwen Feng 				     arg_name);
60431ed9f9fSChengwen Feng 			return -EINVAL;
60531ed9f9fSChengwen Feng 		}
60631ed9f9fSChengwen Feng 
60731ed9f9fSChengwen Feng 		value = (has_equal != NULL ? has_equal + 1 : NULL);
60831ed9f9fSChengwen Feng 		if (arg_attr_has_val(arg) == RTE_ARGPARSE_ARG_NO_VALUE) {
60931ed9f9fSChengwen Feng 			if (value != NULL) {
61031ed9f9fSChengwen Feng 				ARGPARSE_LOG(ERR, "argument %s should not take value!",
61131ed9f9fSChengwen Feng 					     arg_name);
61231ed9f9fSChengwen Feng 				return -EINVAL;
61331ed9f9fSChengwen Feng 			}
61431ed9f9fSChengwen Feng 		} else if (arg_attr_has_val(arg) == RTE_ARGPARSE_ARG_REQUIRED_VALUE) {
61531ed9f9fSChengwen Feng 			if (value == NULL) {
61631ed9f9fSChengwen Feng 				if (i >= argc - 1) {
61731ed9f9fSChengwen Feng 					ARGPARSE_LOG(ERR, "argument %s doesn't have value!",
61831ed9f9fSChengwen Feng 						     arg_name);
61931ed9f9fSChengwen Feng 					return -EINVAL;
62031ed9f9fSChengwen Feng 				}
62131ed9f9fSChengwen Feng 				/* Set value and make i move next. */
62231ed9f9fSChengwen Feng 				value = argv[++i];
62331ed9f9fSChengwen Feng 			}
62431ed9f9fSChengwen Feng 		} else {
62531ed9f9fSChengwen Feng 			/* Do nothing, because it's optional value, only support arg=val or arg. */
62631ed9f9fSChengwen Feng 		}
62731ed9f9fSChengwen Feng 
6289b8df29bSChengwen Feng 		ret = parse_arg_val(obj, arg_name, arg, value);
62931ed9f9fSChengwen Feng 		if (ret != 0)
63031ed9f9fSChengwen Feng 			return ret;
63131ed9f9fSChengwen Feng 
63231ed9f9fSChengwen Feng 		/* This argument parsed success! then mark it parsed. */
63331ed9f9fSChengwen Feng 		arg->flags |= ARG_ATTR_FLAG_PARSED_MASK;
63431ed9f9fSChengwen Feng 	}
63531ed9f9fSChengwen Feng 
63631ed9f9fSChengwen Feng 	return 0;
63731ed9f9fSChengwen Feng }
63831ed9f9fSChengwen Feng 
639676ca0d2SChengwen Feng static uint32_t
640676ca0d2SChengwen Feng calc_help_align(const struct rte_argparse *obj)
641676ca0d2SChengwen Feng {
642676ca0d2SChengwen Feng 	const struct rte_argparse_arg *arg;
643676ca0d2SChengwen Feng 	uint32_t width = 12; /* Default "-h, --help  " len. */
644676ca0d2SChengwen Feng 	uint32_t len;
645676ca0d2SChengwen Feng 	uint32_t i;
646676ca0d2SChengwen Feng 
647676ca0d2SChengwen Feng 	for (i = 0; /* NULL */; i++) {
648676ca0d2SChengwen Feng 		arg = &obj->args[i];
649676ca0d2SChengwen Feng 		if (arg->name_long == NULL)
650676ca0d2SChengwen Feng 			break;
651676ca0d2SChengwen Feng 		len = strlen(arg->name_long);
652676ca0d2SChengwen Feng 		if (is_arg_optional(arg) && arg->name_short != NULL) {
653676ca0d2SChengwen Feng 			len += strlen(", ");
654676ca0d2SChengwen Feng 			len += strlen(arg->name_short);
655676ca0d2SChengwen Feng 		}
656676ca0d2SChengwen Feng 		width = RTE_MAX(width, 1 + len + 2); /* start with 1 & end with 2 space. */
657676ca0d2SChengwen Feng 	}
658676ca0d2SChengwen Feng 
659676ca0d2SChengwen Feng 	return width;
660676ca0d2SChengwen Feng }
661676ca0d2SChengwen Feng 
66231ed9f9fSChengwen Feng static void
663676ca0d2SChengwen Feng show_oneline_help(const struct rte_argparse_arg *arg, uint32_t width)
664676ca0d2SChengwen Feng {
665676ca0d2SChengwen Feng 	uint32_t len = 0;
666676ca0d2SChengwen Feng 	uint32_t i;
667676ca0d2SChengwen Feng 
668676ca0d2SChengwen Feng 	if (arg->name_short != NULL)
669676ca0d2SChengwen Feng 		len = printf(" %s,", arg->name_short);
670676ca0d2SChengwen Feng 	len += printf(" %s", arg->name_long);
671676ca0d2SChengwen Feng 
672676ca0d2SChengwen Feng 	for (i = len; i < width; i++)
673676ca0d2SChengwen Feng 		printf(" ");
674676ca0d2SChengwen Feng 
675676ca0d2SChengwen Feng 	printf("%s\n", arg->help);
676676ca0d2SChengwen Feng }
677676ca0d2SChengwen Feng 
678676ca0d2SChengwen Feng static void
679676ca0d2SChengwen Feng show_args_pos_help(const struct rte_argparse *obj, uint32_t align)
68031ed9f9fSChengwen Feng {
68131ed9f9fSChengwen Feng 	uint32_t position_count = calc_position_count(obj);
68231ed9f9fSChengwen Feng 	const struct rte_argparse_arg *arg;
68331ed9f9fSChengwen Feng 	uint32_t i;
68431ed9f9fSChengwen Feng 
68531ed9f9fSChengwen Feng 	if (position_count == 0)
68631ed9f9fSChengwen Feng 		return;
68731ed9f9fSChengwen Feng 
68831ed9f9fSChengwen Feng 	printf("\npositional arguments:\n");
68931ed9f9fSChengwen Feng 	for (i = 0; /* NULL */; i++) {
69031ed9f9fSChengwen Feng 		arg = &obj->args[i];
69131ed9f9fSChengwen Feng 		if (arg->name_long == NULL)
69231ed9f9fSChengwen Feng 			break;
69331ed9f9fSChengwen Feng 		if (!is_arg_positional(arg))
69431ed9f9fSChengwen Feng 			continue;
695676ca0d2SChengwen Feng 		show_oneline_help(arg, align);
69631ed9f9fSChengwen Feng 	}
69731ed9f9fSChengwen Feng }
69831ed9f9fSChengwen Feng 
69931ed9f9fSChengwen Feng static void
700676ca0d2SChengwen Feng show_args_opt_help(const struct rte_argparse *obj, uint32_t align)
70131ed9f9fSChengwen Feng {
702676ca0d2SChengwen Feng 	static const struct rte_argparse_arg help = {
703676ca0d2SChengwen Feng 		.name_long = "--help",
704676ca0d2SChengwen Feng 		.name_short = "-h",
705676ca0d2SChengwen Feng 		.help = "show this help message and exit.",
706676ca0d2SChengwen Feng 	};
70731ed9f9fSChengwen Feng 	const struct rte_argparse_arg *arg;
70831ed9f9fSChengwen Feng 	uint32_t i;
70931ed9f9fSChengwen Feng 
710676ca0d2SChengwen Feng 	printf("\noptions:\n");
711676ca0d2SChengwen Feng 	show_oneline_help(&help, align);
71231ed9f9fSChengwen Feng 	for (i = 0; /* NULL */; i++) {
71331ed9f9fSChengwen Feng 		arg = &obj->args[i];
71431ed9f9fSChengwen Feng 		if (arg->name_long == NULL)
71531ed9f9fSChengwen Feng 			break;
71631ed9f9fSChengwen Feng 		if (!is_arg_optional(arg))
71731ed9f9fSChengwen Feng 			continue;
718676ca0d2SChengwen Feng 		show_oneline_help(arg, align);
71931ed9f9fSChengwen Feng 	}
72031ed9f9fSChengwen Feng }
72131ed9f9fSChengwen Feng 
72231ed9f9fSChengwen Feng static void
72331ed9f9fSChengwen Feng show_args_help(const struct rte_argparse *obj)
72431ed9f9fSChengwen Feng {
725676ca0d2SChengwen Feng 	uint32_t align = calc_help_align(obj);
726676ca0d2SChengwen Feng 
72731ed9f9fSChengwen Feng 	printf("usage: %s %s\n", obj->prog_name, obj->usage);
72831ed9f9fSChengwen Feng 	if (obj->descriptor != NULL)
72931ed9f9fSChengwen Feng 		printf("\ndescriptor: %s\n", obj->descriptor);
73031ed9f9fSChengwen Feng 
731676ca0d2SChengwen Feng 	show_args_pos_help(obj, align);
732676ca0d2SChengwen Feng 	show_args_opt_help(obj, align);
73331ed9f9fSChengwen Feng 
73431ed9f9fSChengwen Feng 	if (obj->epilog != NULL)
73531ed9f9fSChengwen Feng 		printf("\n%s\n", obj->epilog);
736676ca0d2SChengwen Feng 	else
737676ca0d2SChengwen Feng 		printf("\n");
73831ed9f9fSChengwen Feng }
73931ed9f9fSChengwen Feng 
74031ed9f9fSChengwen Feng int
74131ed9f9fSChengwen Feng rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv)
74231ed9f9fSChengwen Feng {
74331ed9f9fSChengwen Feng 	bool show_help = false;
74431ed9f9fSChengwen Feng 	int ret;
7456c5c6571SChengwen Feng 
7466c5c6571SChengwen Feng 	ret = verify_argparse(obj);
7476c5c6571SChengwen Feng 	if (ret != 0)
7486c5c6571SChengwen Feng 		goto error;
7496c5c6571SChengwen Feng 
75031ed9f9fSChengwen Feng 	ret = parse_args(obj, argc, argv, &show_help);
75131ed9f9fSChengwen Feng 	if (ret != 0)
75231ed9f9fSChengwen Feng 		goto error;
75331ed9f9fSChengwen Feng 
75431ed9f9fSChengwen Feng 	if (show_help) {
75531ed9f9fSChengwen Feng 		show_args_help(obj);
75631ed9f9fSChengwen Feng 		exit(0);
75731ed9f9fSChengwen Feng 	}
75831ed9f9fSChengwen Feng 
759e3e579f5SChengwen Feng 	return 0;
7606c5c6571SChengwen Feng 
7616c5c6571SChengwen Feng error:
7626c5c6571SChengwen Feng 	if (obj->exit_on_error)
7636c5c6571SChengwen Feng 		exit(ret);
7646c5c6571SChengwen Feng 	return ret;
765e3e579f5SChengwen Feng }
7669ccd7b27SChengwen Feng 
7679ccd7b27SChengwen Feng int
7689ccd7b27SChengwen Feng rte_argparse_parse_type(const char *str, uint64_t val_type, void *val)
7699ccd7b27SChengwen Feng {
770*f48e4eedSChengwen Feng 	uint32_t cmp_max = RTE_FIELD_GET64(RTE_ARGPARSE_VAL_TYPE_BITMASK,
771*f48e4eedSChengwen Feng 					   RTE_ARGPARSE_ARG_VALUE_MAX);
7729ccd7b27SChengwen Feng 	struct rte_argparse_arg arg = {
7739ccd7b27SChengwen Feng 		.name_long = str,
7749ccd7b27SChengwen Feng 		.name_short = NULL,
7759ccd7b27SChengwen Feng 		.val_saver = val,
7769ccd7b27SChengwen Feng 		.val_set = NULL,
7779ccd7b27SChengwen Feng 		.flags = val_type,
7789ccd7b27SChengwen Feng 	};
7799ccd7b27SChengwen Feng 	uint32_t value_type = arg_attr_val_type(&arg);
7809ccd7b27SChengwen Feng 
7819ccd7b27SChengwen Feng 	if (value_type == 0 || value_type >= cmp_max)
7829ccd7b27SChengwen Feng 		return -EINVAL;
7839ccd7b27SChengwen Feng 
7849ccd7b27SChengwen Feng 	return parse_arg_autosave(&arg, str);
7859ccd7b27SChengwen Feng }
786