1e3e579f5SChengwen Feng /* SPDX-License-Identifier: BSD-3-Clause 2e3e579f5SChengwen Feng * Copyright(c) 2024 HiSilicon Limited 3e3e579f5SChengwen Feng */ 4e3e579f5SChengwen Feng 5e3e579f5SChengwen Feng #ifndef RTE_ARGPARSE_H 6e3e579f5SChengwen Feng #define RTE_ARGPARSE_H 7e3e579f5SChengwen Feng 8e3e579f5SChengwen Feng /** 9e3e579f5SChengwen Feng * @file rte_argparse.h 10e3e579f5SChengwen Feng * 11e3e579f5SChengwen Feng * Argument parsing API. 12e3e579f5SChengwen Feng * 13e3e579f5SChengwen Feng * The argument parsing API makes it easy to write user-friendly command-line 14e3e579f5SChengwen Feng * program. The program defines what arguments it requires, 15e3e579f5SChengwen Feng * and the API will parse those arguments from [argc, argv]. 16e3e579f5SChengwen Feng * 17e3e579f5SChengwen Feng * The API provides the following functions: 18e3e579f5SChengwen Feng * 1) Support parsing optional argument (which could take with no-value, 19e3e579f5SChengwen Feng * required-value and optional-value. 20e3e579f5SChengwen Feng * 2) Support parsing positional argument (which must take with required-value). 21e3e579f5SChengwen Feng * 3) Support automatic generate usage information. 22e3e579f5SChengwen Feng * 4) Support issue errors when provided with invalid arguments. 23e3e579f5SChengwen Feng * 24e3e579f5SChengwen Feng * There are two ways to parse arguments: 25e3e579f5SChengwen Feng * 1) AutoSave: for which known value types, the way can be used. 26e3e579f5SChengwen Feng * 2) Callback: will invoke user callback to parse. 27e3e579f5SChengwen Feng * 28e3e579f5SChengwen Feng */ 29e3e579f5SChengwen Feng 30e3e579f5SChengwen Feng #include <stdbool.h> 31e3e579f5SChengwen Feng #include <stdint.h> 32e3e579f5SChengwen Feng 33e3e579f5SChengwen Feng #include <rte_bitops.h> 34e3e579f5SChengwen Feng #include <rte_compat.h> 35e3e579f5SChengwen Feng 36e3e579f5SChengwen Feng #ifdef __cplusplus 37e3e579f5SChengwen Feng extern "C" { 38e3e579f5SChengwen Feng #endif 39e3e579f5SChengwen Feng 40e3e579f5SChengwen Feng /** 41e3e579f5SChengwen Feng * Flag definition (in bitmask form) for an argument. 42e3e579f5SChengwen Feng */ 43e3e579f5SChengwen Feng enum rte_argparse_flag { 44e3e579f5SChengwen Feng /* 45e3e579f5SChengwen Feng * Bits 0-1: represent the argument whether has value. 46e3e579f5SChengwen Feng */ 47e3e579f5SChengwen Feng 48e3e579f5SChengwen Feng /** The argument has no value. */ 49e3e579f5SChengwen Feng RTE_ARGPARSE_ARG_NO_VALUE = RTE_SHIFT_VAL64(1, 0), 50e3e579f5SChengwen Feng /** The argument must have a value. */ 51e3e579f5SChengwen Feng RTE_ARGPARSE_ARG_REQUIRED_VALUE = RTE_SHIFT_VAL64(2, 0), 52e3e579f5SChengwen Feng /** The argument has optional value. */ 53e3e579f5SChengwen Feng RTE_ARGPARSE_ARG_OPTIONAL_VALUE = RTE_SHIFT_VAL64(3, 0), 54e3e579f5SChengwen Feng 55e3e579f5SChengwen Feng 56e3e579f5SChengwen Feng /* 57e3e579f5SChengwen Feng * Bits 2-9: represent the value type which used when autosave 58e3e579f5SChengwen Feng */ 59e3e579f5SChengwen Feng 60e3e579f5SChengwen Feng /** The argument's value is int type. */ 61e3e579f5SChengwen Feng RTE_ARGPARSE_ARG_VALUE_INT = RTE_SHIFT_VAL64(1, 2), 62e3e579f5SChengwen Feng /** Max value type. */ 63e3e579f5SChengwen Feng RTE_ARGPARSE_ARG_VALUE_MAX = RTE_SHIFT_VAL64(2, 2), 64e3e579f5SChengwen Feng 65e3e579f5SChengwen Feng 66e3e579f5SChengwen Feng /** 67e3e579f5SChengwen Feng * Bit 10: flag for that argument support occur multiple times. 68e3e579f5SChengwen Feng * This flag can be set only when the argument is optional. 69e3e579f5SChengwen Feng * When this flag is set, the callback type must be used for parsing. 70e3e579f5SChengwen Feng */ 71e3e579f5SChengwen Feng RTE_ARGPARSE_ARG_SUPPORT_MULTI = RTE_BIT64(10), 72e3e579f5SChengwen Feng 73e3e579f5SChengwen Feng /** 74e3e579f5SChengwen Feng * Bits 48-63: reserved for this library implementation usage. 75e3e579f5SChengwen Feng */ 76e3e579f5SChengwen Feng RTE_ARGPARSE_ARG_RESERVED_FIELD = RTE_GENMASK64(63, 48), 77e3e579f5SChengwen Feng }; 78e3e579f5SChengwen Feng 79e3e579f5SChengwen Feng /** 80e3e579f5SChengwen Feng * A structure used to hold argument's configuration. 81e3e579f5SChengwen Feng */ 82e3e579f5SChengwen Feng struct rte_argparse_arg { 83e3e579f5SChengwen Feng /** 84e3e579f5SChengwen Feng * Long name of the argument: 85e3e579f5SChengwen Feng * 1) If the argument is optional, it must start with '--'. 86e3e579f5SChengwen Feng * 2) If the argument is positional, it must not start with '-'. 87e3e579f5SChengwen Feng * 3) Other case will be considered as error. 88e3e579f5SChengwen Feng */ 89e3e579f5SChengwen Feng const char *name_long; 90e3e579f5SChengwen Feng /** 91e3e579f5SChengwen Feng * Short name of the argument: 92e3e579f5SChengwen Feng * 1) This field could be set only when name_long is optional, and 93e3e579f5SChengwen Feng * must start with a hyphen (-) followed by an English letter. 94e3e579f5SChengwen Feng * 2) Other case it should be set NULL. 95e3e579f5SChengwen Feng */ 96e3e579f5SChengwen Feng const char *name_short; 97e3e579f5SChengwen Feng 98e3e579f5SChengwen Feng /** Help information of the argument, must not be NULL. */ 99e3e579f5SChengwen Feng const char *help; 100e3e579f5SChengwen Feng 101e3e579f5SChengwen Feng /** 102e3e579f5SChengwen Feng * Saver for the argument's value. 103e3e579f5SChengwen Feng * 1) If the filed is NULL, the callback way is used for parsing 104e3e579f5SChengwen Feng * argument. 105e3e579f5SChengwen Feng * 2) If the field is not NULL, the autosave way is used for parsing 106e3e579f5SChengwen Feng * argument. 107e3e579f5SChengwen Feng */ 108e3e579f5SChengwen Feng void *val_saver; 109e3e579f5SChengwen Feng /** 110e3e579f5SChengwen Feng * If val_saver is NULL, this filed (cast as (uint32_t)val_set) will be 111e3e579f5SChengwen Feng * used as the first parameter to invoke callback. 112e3e579f5SChengwen Feng * 113e3e579f5SChengwen Feng * If val_saver is not NULL, then: 114e3e579f5SChengwen Feng * 1) If argument has no value, *val_saver will be set to val_set. 115e3e579f5SChengwen Feng * 2) If argument has optional value but doesn't take value this 116e3e579f5SChengwen Feng * time, *val_saver will be set to val_set. 117e3e579f5SChengwen Feng * 3) Other case it should be set NULL. 118e3e579f5SChengwen Feng */ 119e3e579f5SChengwen Feng void *val_set; 120e3e579f5SChengwen Feng 121e3e579f5SChengwen Feng /** @see rte_argparse_flag */ 122e3e579f5SChengwen Feng uint64_t flags; 123e3e579f5SChengwen Feng }; 124e3e579f5SChengwen Feng 125e3e579f5SChengwen Feng /** 126e3e579f5SChengwen Feng * Callback prototype used by parsing specified arguments. 127e3e579f5SChengwen Feng * 128e3e579f5SChengwen Feng * @param index 129e3e579f5SChengwen Feng * The argument's index, coming from argument's val_set field. 130e3e579f5SChengwen Feng * @param value 131e3e579f5SChengwen Feng * The value corresponding to the argument, it may be NULL (e.g. the 132e3e579f5SChengwen Feng * argument has no value, or the argument has optional value but doesn't 133e3e579f5SChengwen Feng * provided value). 134e3e579f5SChengwen Feng * @param opaque 135e3e579f5SChengwen Feng * An opaque pointer coming from the caller. 136e3e579f5SChengwen Feng * @return 137e3e579f5SChengwen Feng * 0 on success. Otherwise negative value is returned. 138e3e579f5SChengwen Feng */ 139e3e579f5SChengwen Feng typedef int (*arg_parser_t)(uint32_t index, const char *value, void *opaque); 140e3e579f5SChengwen Feng 141e3e579f5SChengwen Feng /** 142e3e579f5SChengwen Feng * A structure used to hold argparse's configuration. 143e3e579f5SChengwen Feng */ 144e3e579f5SChengwen Feng struct rte_argparse { 145e3e579f5SChengwen Feng /** Program name. Must not be NULL. */ 146e3e579f5SChengwen Feng const char *prog_name; 147e3e579f5SChengwen Feng /** How to use the program. Must not be NULL. */ 148e3e579f5SChengwen Feng const char *usage; 149e3e579f5SChengwen Feng /** Explain what the program does. Could be NULL. */ 150e3e579f5SChengwen Feng const char *descriptor; 151e3e579f5SChengwen Feng /** Text at the bottom of help. Could be NULL. */ 152e3e579f5SChengwen Feng const char *epilog; 153e3e579f5SChengwen Feng /** Whether exit when error. */ 154e3e579f5SChengwen Feng bool exit_on_error; 155e3e579f5SChengwen Feng /** User callback for parsing arguments. */ 156e3e579f5SChengwen Feng arg_parser_t callback; 157e3e579f5SChengwen Feng /** Opaque which used to invoke callback. */ 158e3e579f5SChengwen Feng void *opaque; 159e3e579f5SChengwen Feng /** Reserved field used for future extension. */ 160e3e579f5SChengwen Feng void *reserved[16]; 161e3e579f5SChengwen Feng /** Arguments configuration. Must ended with ARGPARSE_ARG_END(). */ 162e3e579f5SChengwen Feng struct rte_argparse_arg args[]; 163e3e579f5SChengwen Feng }; 164e3e579f5SChengwen Feng 165e3e579f5SChengwen Feng #define ARGPARSE_ARG_END() { NULL } 166e3e579f5SChengwen Feng 167e3e579f5SChengwen Feng /** 168e3e579f5SChengwen Feng * @warning 169e3e579f5SChengwen Feng * @b EXPERIMENTAL: this API may change without prior notice. 170e3e579f5SChengwen Feng * 171e3e579f5SChengwen Feng * Parse parameters. 172e3e579f5SChengwen Feng * 173e3e579f5SChengwen Feng * @param obj 174e3e579f5SChengwen Feng * Parser object. 175e3e579f5SChengwen Feng * @param argc 176e3e579f5SChengwen Feng * Parameters count. 177e3e579f5SChengwen Feng * @param argv 178e3e579f5SChengwen Feng * Array of parameters points. 179e3e579f5SChengwen Feng * 180e3e579f5SChengwen Feng * @return 181e3e579f5SChengwen Feng * 0 on success. Otherwise negative value is returned. 182e3e579f5SChengwen Feng */ 183e3e579f5SChengwen Feng __rte_experimental 184e3e579f5SChengwen Feng int rte_argparse_parse(struct rte_argparse *obj, int argc, char **argv); 185e3e579f5SChengwen Feng 186*9ccd7b27SChengwen Feng /** 187*9ccd7b27SChengwen Feng * @warning 188*9ccd7b27SChengwen Feng * @b EXPERIMENTAL: this API may change without prior notice. 189*9ccd7b27SChengwen Feng * 190*9ccd7b27SChengwen Feng * Parse the value from the input string based on the value type. 191*9ccd7b27SChengwen Feng * 192*9ccd7b27SChengwen Feng * @param str 193*9ccd7b27SChengwen Feng * Input string. 194*9ccd7b27SChengwen Feng * @param val_type 195*9ccd7b27SChengwen Feng * The value type, @see RTE_ARGPARSE_ARG_VALUE_INT or other type. 196*9ccd7b27SChengwen Feng * @param val 197*9ccd7b27SChengwen Feng * Saver for the value. 198*9ccd7b27SChengwen Feng * 199*9ccd7b27SChengwen Feng * @return 200*9ccd7b27SChengwen Feng * 0 on success. Otherwise negative value is returned. 201*9ccd7b27SChengwen Feng */ 202*9ccd7b27SChengwen Feng __rte_experimental 203*9ccd7b27SChengwen Feng int rte_argparse_parse_type(const char *str, uint64_t val_type, void *val); 204*9ccd7b27SChengwen Feng 205e3e579f5SChengwen Feng #ifdef __cplusplus 206e3e579f5SChengwen Feng } 207e3e579f5SChengwen Feng #endif 208e3e579f5SChengwen Feng 209e3e579f5SChengwen Feng #endif /* RTE_ARGPARSE_H */ 210