LCOV - code coverage report
Current view: top level - lib/argparse - rte_argparse.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 245 314 78.0 %
Date: 2024-04-01 19:00:53 Functions: 20 25 80.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 170 228 74.6 %

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