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

Generated by: LCOV version 1.14