LCOV - code coverage report
Current view: top level - lib/argparse - rte_argparse.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 267 357 74.8 %
Date: 2025-07-01 21:32:37 Functions: 22 27 81.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 184 251 73.3 %

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

Generated by: LCOV version 1.14