LCOV - code coverage report
Current view: top level - lib/argparse - rte_argparse.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 247 311 79.4 %
Date: 2025-03-01 20:23:48 Functions: 20 25 80.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 171 226 75.7 %

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

Generated by: LCOV version 1.14