> Add support for parsing floating point numbers in cmdline library, as well
> as unit tests for the new functionality. The parser supports single and
> double precision floats, and will understand decimal fractions as well as
> scientific notation.

There are standard functions for that: strtod/strtof - can't we simply use 
them?  

> 
> Signed-off-by: Anatoly Burakov <anatoly.bura...@intel.com>
> ---
> 
> Notes:
>     v3 -> v4:
>     - Removed unnecessary check for integer overflow when parsing negative
>       floats (as we convert to double before changing sign)
>     - Make naming of float exponent states more consistent
> 
>     v2 -> v3:
>     - Fixed a bug where a free-standing negative exponent ("1e-") would 
> attempt to be
>       parsed, and added unit tests for this case
>     - Added support for floats in dpdk-cmdline-gen script
>     - Added documentation updates to call out float support
> 
>  app/test/test_cmdline_num.c            | 203 +++++++++++++++++-
>  buildtools/dpdk-cmdline-gen.py         |  24 ++-
>  doc/guides/prog_guide/cmdline.rst      |   3 +
>  doc/guides/rel_notes/release_25_07.rst |   5 +
>  lib/cmdline/cmdline_parse_num.c        | 273 +++++++++++++++++++++++++
>  lib/cmdline/cmdline_parse_num.h        |   4 +-
>  6 files changed, 497 insertions(+), 15 deletions(-)
> 
> diff --git a/app/test/test_cmdline_num.c b/app/test/test_cmdline_num.c
> index 9276de59bd..e4038271c9 100644
> --- a/app/test/test_cmdline_num.c
> +++ b/app/test/test_cmdline_num.c
> @@ -5,6 +5,8 @@
>  #include <stdio.h>
>  #include <string.h>
>  #include <inttypes.h>
> +#include <float.h>
> +#include <math.h>
> 
>  #include <rte_string_fns.h>
> 
> @@ -23,6 +25,11 @@ struct num_signed_str {
>       int64_t result;
>  };
> 
> +struct num_float_str {
> +     const char * str;
> +     double result;
> +};
> +
>  const struct num_unsigned_str num_valid_positive_strs[] = {
>               /* decimal positive */
>               {"0", 0 },
> @@ -141,6 +148,63 @@ const struct num_signed_str num_valid_negative_strs[] = {
>               {"-9223372036854775808", INT64_MIN },
>  };
> 
> +const struct num_float_str num_valid_float_strs[] = {
> +             /* zero */
> +             {"0", 0},
> +             /* parse int as float */
> +             {"1", 1},
> +             {"-1", -1},
> +             /* fractional */
> +             {"1.23", 1.23},
> +             {"-1.23", -1.23},
> +             {"0.123", 0.123},
> +             {"-0.123", -0.123},
> +             {"123.456", 123.456},
> +             {"-123.456", -123.456},
> +             /* positive exponent */
> +             {"1e2", 1e2},
> +             {"-1e2", -1e2},
> +             {"1E2", 1E2},
> +             {"-1E2", -1E2},
> +             {"0.12e3", 0.12e3},
> +             {"-0.12e3", -0.12e3},
> +             {"1.23e4", 1.23e4},
> +             {"-1.23e4", -1.23e4},
> +             {"1.23E4", 1.23E4},
> +             {"-1.23E4", -1.23E4},
> +             {"123.456e7", 123.456e7},
> +             {"-123.456e7", -123.456e7},
> +             {"123.456E7", 123.456E7},
> +             {"-123.456E7", -123.456E7},
> +             /* negative exponent */
> +             {"1e-2", 1e-2},
> +             {"-1e-2", -1e-2},
> +             {"1E-2", 1E-2},
> +             {"-1E-2", -1E-2},
> +             {"0.12e-3", 0.12e-3},
> +             {"-0.12e-3", -0.12e-3},
> +             {"1.23e-4", 1.23e-4},
> +             {"-1.23e-4", -1.23e-4},
> +             {"1.23E-4", 1.23E-4},
> +             {"-1.23E-4", -1.23E-4},
> +             {"123.456e-7", 123.456e-7},
> +             {"-123.456e-7", -123.456e-7},
> +             {"123.456E-7", 123.456E-7},
> +             {"-123.456E-7", -123.456E-7},
> +             /* try overflowing float */
> +             {"2e63", 2e63},
> +             {"-2e63", -2e63},
> +             {"2E63", 2E63},
> +             {"-2E63", -2E63},
> +             {"18446744073709551615", (double) UINT64_MAX},
> +             {"-9223372036854775808", (double) INT64_MIN},
> +             /* try overflowing double */
> +             {"2e308", HUGE_VAL},
> +             {"-2e308", -HUGE_VAL},
> +             {"2E308", HUGE_VAL},
> +             {"-2E308", HUGE_VAL},
> +};
> +
>  const struct num_unsigned_str num_garbage_positive_strs[] = {
>               /* valid strings with garbage on the end, should still be valid 
> */
>               /* decimal */
> @@ -183,6 +247,30 @@ const struct num_signed_str num_garbage_negative_strs[] 
> = {
>               {"-9223372036854775808 garbage", INT64_MIN },
>  };
> 
> +const char *float_invalid_strs[] = {
> +     "0.",
> +     ".1",
> +     "1.1.",
> +     "1.1.1",
> +     "-0.",
> +     "-.1",
> +     "-1.1.",
> +     "-1.1.1",
> +     "e",
> +     "1e",
> +     "-1e",
> +     "0.1e",
> +     "-0.1e",
> +     "1.e",
> +     "-1.e",
> +     "1.23e3.4",
> +     "-1.23e3.4",
> +     "1e1e",
> +     "1e1e1",
> +     "1e-",
> +     "-1e-"
> +};
> +
>  const char * num_invalid_strs[] = {
>               "18446744073709551616", /* out of range unsigned */
>               "-9223372036854775809", /* out of range negative signed */
> @@ -202,7 +290,16 @@ const char * num_invalid_strs[] = {
>               /* too long (128+ chars) */
>               
> ("0b1111000011110000111100001111000011110000111100001111000011110000"
>                 
> "1111000011110000111100001111000011110000111100001111000011110000"),
> +             /* valid float values but should fail to parse as ints */
>               "1E3",
> +             "-1E3",
> +             "1.23",
> +             "-1.23",
> +             "1E-3",
> +             "-1E-3",
> +             "1.23E4",
> +             "-1.23E4",
> +             /* misc invalid values */
>               "0A",
>               "-B",
>               "+4",
> @@ -216,6 +313,47 @@ const char * num_invalid_strs[] = {
>               "\0",
>  };
> 
> +static int
> +float_cmp(double expected, void *actual_p, enum cmdline_numtype type)
> +{
> +     double eps;
> +     double actual_d;
> +
> +     if (type == RTE_FLOAT_SINGLE) {
> +             /* read as float, convert to double */
> +             actual_d = (double)*(float *)actual_p;
> +             /* FLT_EPSILON is too small for some tests */
> +             eps = 1e-5f;
> +     } else {
> +             /* read as double */
> +             actual_d = *(double *)actual_p;
> +             eps = DBL_EPSILON;
> +     }
> +     /* compare using epsilon value */
> +     if (fabs(expected - actual_d) < eps)
> +             return 0;
> +     /* not equal */
> +     return expected < actual_d ? -1 : 1;
> +}
> +
> +static int
> +can_parse_float(double expected_result, enum cmdline_numtype type)
> +{
> +     switch (type) {
> +     case RTE_FLOAT_SINGLE:
> +             if (expected_result > FLT_MAX || expected_result < -FLT_MAX)
> +                     return 0;
> +             break;
> +     case RTE_FLOAT_DOUBLE:
> +             if (expected_result > DBL_MAX || expected_result < -DBL_MAX)
> +                     return 0;
> +             break;
> +     default:
> +             return 1;
> +     }
> +     return 1;
> +}
> +
>  static int
>  can_parse_unsigned(uint64_t expected_result, enum cmdline_numtype type)
>  {
> @@ -371,11 +509,11 @@ test_parse_num_invalid_data(void)
>       int ret = 0;
>       unsigned i;
>       char buf[CMDLINE_TEST_BUFSIZE];
> -     uint64_t result; /* pick largest buffer */
>       cmdline_parse_token_num_t token;
> 
> -     /* cycle through all possible parsed types */
> +     /* cycle through all possible integer types */
>       for (type = RTE_UINT8; type <= RTE_INT64; type++) {
> +             uint64_t result; /* pick largest buffer */
>               token.num_data.type = type;
> 
>               /* test full strings */
> @@ -397,6 +535,31 @@ test_parse_num_invalid_data(void)
>                       }
>               }
>       }
> +
> +     /* cycle through all possible float types */
> +     for (type = RTE_FLOAT_SINGLE; type <= RTE_FLOAT_DOUBLE; type++) {
> +             double result; /* pick largest buffer */
> +             token.num_data.type = type;
> +
> +             /* test full strings */
> +             for (i = 0; i < RTE_DIM(float_invalid_strs); i++) {
> +
> +                     memset(&result, 0, sizeof(double));
> +                     memset(&buf, 0, sizeof(buf));
> +
> +                     ret = 
> cmdline_parse_num((cmdline_parse_token_hdr_t*)&token,
> +                                     float_invalid_strs[i], (void*)&result, 
> sizeof(result));
> +                     if (ret != -1) {
> +                             /* get some info about what we are trying to 
> parse */
> +                             
> cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
> +                                             buf, sizeof(buf));
> +
> +                             printf("Error: parsing %s as %s succeeded!\n",
> +                                             float_invalid_strs[i], buf);
> +                             return -1;
> +                     }
> +             }
> +     }
>       return 0;
>  }
> 
> @@ -408,13 +571,13 @@ test_parse_num_valid(void)
>       enum cmdline_numtype type;
>       unsigned i;
>       char buf[CMDLINE_TEST_BUFSIZE];
> -     uint64_t result;
>       cmdline_parse_token_num_t token;
> 
>       /** valid strings **/
> 
>       /* cycle through all possible parsed types */
>       for (type = RTE_UINT8; type <= RTE_INT64; type++) {
> +             uint64_t result;
>               token.num_data.type = type;
> 
>               /* test positive strings */
> @@ -489,10 +652,44 @@ test_parse_num_valid(void)
>               }
>       }
> 
> +     /* float values */
> +     for (type = RTE_FLOAT_SINGLE; type <= RTE_FLOAT_DOUBLE; type++) {
> +             double result;
> +             token.num_data.type = type;
> +
> +             /* test all valid strings */
> +             for (i = 0; i < RTE_DIM(num_valid_float_strs); i++) {
> +                     result = 0;
> +                     memset(&buf, 0, sizeof(buf));
> +
> +
> +                     cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
> +                                     buf, sizeof(buf));
> +
> +                     ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) 
> &token,
> +                             num_valid_float_strs[i].str,
> +                             (void*)&result, sizeof(result));
> +
> +                     /* if it should have passed but didn't, or if it should 
> have failed but didn't */
> +                     if ((ret < 0) == 
> (can_parse_float(num_valid_float_strs[i].result, type) > 0)) {
> +                             printf("Error: parser behaves unexpectedly when 
> parsing %s as %s!\n",
> +                                             num_valid_float_strs[i].str, 
> buf);
> +                             return -1;
> +                     }
> +                     /* check if result matches */
> +                     if (ret > 0 && 
> float_cmp(num_valid_float_strs[i].result, &result, type) != 0) {
> +                             printf("Error: parsing %s as %s failed: result 
> mismatch!\n",
> +                                             num_valid_float_strs[i].str, 
> buf);
> +                             return -1;
> +                     }
> +             }
> +     }
> +
>       /** garbage strings **/
> 
>       /* cycle through all possible parsed types */
>       for (type = RTE_UINT8; type <= RTE_INT64; type++) {
> +             uint64_t result;
>               token.num_data.type = type;
> 
>               /* test positive garbage strings */
> diff --git a/buildtools/dpdk-cmdline-gen.py b/buildtools/dpdk-cmdline-gen.py
> index 7dadded783..6c76d7116a 100755
> --- a/buildtools/dpdk-cmdline-gen.py
> +++ b/buildtools/dpdk-cmdline-gen.py
> @@ -17,16 +17,18 @@
>      RTE_SET_USED(cl);
>      RTE_SET_USED(data);
>  """
> -NUMERIC_TYPES = [
> -    "UINT8",
> -    "UINT16",
> -    "UINT32",
> -    "UINT64",
> -    "INT8",
> -    "INT16",
> -    "INT32",
> -    "INT64",
> -]
> +NUMERIC_TYPES = {
> +    "UINT8": "uint8_t",
> +    "UINT16": "uint16_t",
> +    "UINT32": "uint32_t",
> +    "UINT64": "uint64_t",
> +    "INT8": "int8_t",
> +    "INT16": "int16_t",
> +    "INT32": "int32_t",
> +    "INT64": "int64_t",
> +    "FLOAT_SINGLE": "float",
> +    "FLOAT_DOUBLE": "double",
> +}
> 
> 
>  def process_command(lineno, tokens, comment):
> @@ -70,7 +72,7 @@ def process_command(lineno, tokens, comment):
>                  f"\tTOKEN_STRING_INITIALIZER(struct cmd_{name}_result, 
> {t_name}, {t_val});"
>              )
>          elif t_type in NUMERIC_TYPES:
> -            result_struct.append(f"\t{t_type.lower()}_t {t_name};")
> +            result_struct.append(f"\t{NUMERIC_TYPES[t_type]} {t_name};")
>              initializers.append(
>                  f"static cmdline_parse_token_num_t cmd_{name}_{t_name}_tok 
> =\n"
>                  f"\tTOKEN_NUM_INITIALIZER(struct cmd_{name}_result, 
> {t_name}, RTE_{t_type});"
> diff --git a/doc/guides/prog_guide/cmdline.rst 
> b/doc/guides/prog_guide/cmdline.rst
> index e20281ceb5..447a90e32e 100644
> --- a/doc/guides/prog_guide/cmdline.rst
> +++ b/doc/guides/prog_guide/cmdline.rst
> @@ -22,6 +22,7 @@ The DPDK command-line library supports the following 
> features:
> 
>     * Strings
>     * Signed/unsigned 16/32/64-bit integers
> +   * Single/double precision floats
>     * IP Addresses
>     * Ethernet Addresses
> 
> @@ -68,6 +69,8 @@ The format of the list file must be:
> 
>    * ``<UINT16>port_id``
> 
> +  * ``<FLOAT_SINGLE>ratio``
> +
>    * ``<IP>src_ip``
> 
>    * ``<IPv4>dst_ip4``
> diff --git a/doc/guides/rel_notes/release_25_07.rst 
> b/doc/guides/rel_notes/release_25_07.rst
> index 093b85d206..54bc545110 100644
> --- a/doc/guides/rel_notes/release_25_07.rst
> +++ b/doc/guides/rel_notes/release_25_07.rst
> @@ -55,6 +55,11 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
> 
> +* **Added floating point numbers support to cmdline library.**
> +
> +  The cmdline library now supports parsing single- and double-precision
> +  floating point numbers in interactive user commands.
> +
> 
>  Removed Items
>  -------------
> diff --git a/lib/cmdline/cmdline_parse_num.c b/lib/cmdline/cmdline_parse_num.c
> index f21796bedb..9e4d559325 100644
> --- a/lib/cmdline/cmdline_parse_num.c
> +++ b/lib/cmdline/cmdline_parse_num.c
> @@ -7,6 +7,8 @@
>  #include <stdio.h>
>  #include <stdint.h>
>  #include <inttypes.h>
> +#include <float.h>
> +#include <math.h>
>  #include <string.h>
>  #include <eal_export.h>
>  #include <rte_string_fns.h>
> @@ -34,6 +36,10 @@ enum num_parse_state_t {
>       DEC_NEG,
>       BIN,
>       HEX,
> +     FLOAT_POS,
> +     FLOAT_NEG,
> +     FLOAT_EXP_POS,
> +     FLOAT_EXP_NEG,
> 
>       ERROR,
> 
> @@ -44,12 +50,27 @@ enum num_parse_state_t {
>       BIN_OK,
>       DEC_NEG_OK,
>       DEC_POS_OK,
> +     FLOAT_POS_OK,
> +     FLOAT_NEG_OK,
> +     FLOAT_EXP_POS_OK,
> +     FLOAT_EXP_NEG_OK,
> +};
> +
> +struct float_parse_state {
> +     uint64_t dec;
> +     uint64_t frac;
> +     uint64_t frac_exp;
> +     uint64_t exp;
> +#define FLOAT_FLAG_NEG_RES     (1 << 0)
> +#define FLOAT_FLAG_NEG_EXP     (1 << 1)
> +     int flags;
>  };
> 
>  /* Keep it sync with enum in .h */
>  static const char * num_help[] = {
>       "UINT8", "UINT16", "UINT32", "UINT64",
>       "INT8", "INT16", "INT32", "INT64",
> +     "SINGLE", "DOUBLE"
>  };
> 
>  static inline int
> @@ -63,6 +84,50 @@ add_to_res(unsigned int c, uint64_t *res, unsigned int 
> base)
>       return 0;
>  }
> 
> +static inline int
> +check_float_result(enum cmdline_numtype res_type, struct float_parse_state 
> *fps,
> +             void *res)
> +{
> +     double dec, frac, exp, result;
> +
> +     /* extract parts */
> +     dec = (double) fps->dec;
> +     frac = (double) fps->frac * pow(10.0, -(double)fps->frac_exp);
> +     exp = (double) fps->exp;
> +
> +     /* exponent might be negative */
> +     if (fps->flags & FLOAT_FLAG_NEG_EXP)
> +             exp = pow(10.0, -exp);
> +     else
> +             exp = pow(10.0, exp);
> +
> +     /* combine decimal, fractional, and exponent parts */
> +     result = (dec + frac) * exp;
> +
> +     /* check for any overflows */
> +     if (isinf(frac) || isinf(exp) || isinf(result))
> +             return -1;
> +
> +     /* result is a valid double */
> +
> +     /* check if result needs to be negative */
> +     if (fps->flags & FLOAT_FLAG_NEG_RES)
> +             result = -result;
> +
> +     if (res_type == RTE_FLOAT_SINGLE) {
> +             /* float can overflow from conversion */
> +             float flt = (float)result;
> +             if (isinf(flt))
> +                     return -1;
> +             if (res) *(float *)res = flt;
> +     } else if (res_type == RTE_FLOAT_DOUBLE) {
> +             if (res) *(double *)res = result;
> +     } else {
> +             return -1;
> +     }
> +     return 0;
> +}
> +
>  static int
>  check_res_size(struct cmdline_token_num_data *nd, unsigned ressize)
>  {
> @@ -87,6 +152,14 @@ check_res_size(struct cmdline_token_num_data *nd, 
> unsigned ressize)
>               if (ressize < sizeof(int64_t))
>                       return -1;
>               break;
> +     case RTE_FLOAT_SINGLE:
> +             if (ressize < sizeof(float))
> +                     return -1;
> +             break;
> +     case RTE_FLOAT_DOUBLE:
> +             if (ressize < sizeof(double))
> +                     return -1;
> +             break;
>       default:
>               return -1;
>       }
> @@ -104,6 +177,7 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const 
> char *srcbuf, void *res,
>       const char * buf;
>       char c;
>       uint64_t res1 = 0;
> +     struct float_parse_state fps = {};
> 
>       if (!tk)
>               return -1;
> @@ -156,6 +230,10 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const 
> char *srcbuf, void *res,
>                               else
>                                       st = OCTAL_OK;
>                       }
> +                     else if (c == '.') {
> +                             st = FLOAT_POS;
> +                             break;
> +                     }
>                       else  {
>                               st = ERROR;
>                       }
> @@ -173,11 +251,80 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const 
> char *srcbuf, void *res,
>                       }
>                       break;
> 
> +             case FLOAT_POS:
> +                     if (c >= '0' && c <= '9') {
> +                             if (add_to_res(c - '0', &res1, 10) < 0)
> +                                     st = ERROR;
> +                             else {
> +                                     st = FLOAT_POS_OK;
> +                                     fps.frac_exp++;
> +                             }
> +                     }
> +                     else {
> +                             st = ERROR;
> +                     }
> +                     break;
> +
> +             case FLOAT_NEG:
> +                     if (c >= '0' && c <= '9') {
> +                             if (add_to_res(c - '0', &res1, 10) < 0)
> +                                     st = ERROR;
> +                             else {
> +                                     st = FLOAT_NEG_OK;
> +                                     fps.frac_exp++;
> +                             }
> +                     }
> +                     else {
> +                             st = ERROR;
> +                     }
> +                     break;
> +
> +             case FLOAT_EXP_POS:
> +                     if (c >= '0' && c <= '9') {
> +                             if (add_to_res(c - '0', &res1, 10) < 0)
> +                                     st = ERROR;
> +                             else
> +                                     st = FLOAT_EXP_POS_OK;
> +                     }
> +                     else if (c == '-') {
> +                             st = FLOAT_EXP_NEG;
> +                             fps.flags |= FLOAT_FLAG_NEG_EXP;
> +                     }
> +                     else {
> +                             st = ERROR;
> +                     }
> +                     break;
> +
> +             case FLOAT_EXP_NEG:
> +                     if (c >= '0' && c <= '9') {
> +                             if (add_to_res(c - '0', &res1, 10) < 0)
> +                                     st = ERROR;
> +                             else
> +                                     st = FLOAT_EXP_NEG_OK;
> +                     }
> +                     else {
> +                             st = ERROR;
> +                     }
> +                     break;
> +
>               case DEC_NEG_OK:
>                       if (c >= '0' && c <= '9') {
>                               if (add_to_res(c - '0', &res1, 10) < 0)
>                                       st = ERROR;
>                       }
> +                     else if (c == '.') {
> +                             fps.dec = res1;
> +                             fps.flags |= FLOAT_FLAG_NEG_RES;
> +                             st = FLOAT_NEG;
> +                             /* erase result */
> +                             res1 = 0;
> +                     } else if (c == 'e' || c == 'E') {
> +                             fps.dec = res1;
> +                             fps.flags |= FLOAT_FLAG_NEG_RES;
> +                             st = FLOAT_EXP_POS;
> +                             /* erase result */
> +                             res1 = 0;
> +                     }
>                       else {
>                               st = ERROR;
>                       }
> @@ -188,11 +335,75 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const 
> char *srcbuf, void *res,
>                               if (add_to_res(c - '0', &res1, 10) < 0)
>                                       st = ERROR;
>                       }
> +                     else if (c == '.') {
> +                             fps.dec = res1;
> +                             st = FLOAT_POS;
> +                             /* erase result */
> +                             res1 = 0;
> +                     }
> +                     else if (c == 'e' || c == 'E') {
> +                             fps.dec = res1;
> +                             st = FLOAT_EXP_POS;
> +                             /* erase result */
> +                             res1 = 0;
> +                     }
>                       else {
>                               st = ERROR;
>                       }
>                       break;
> 
> +             case FLOAT_POS_OK:
> +                     if (c >= '0' && c <= '9') {
> +                             if (add_to_res(c - '0', &res1, 10) < 0)
> +                                     st = ERROR;
> +                             else
> +                                     fps.frac_exp++;
> +                     } else if (c == 'e' || c == 'E') {
> +                             fps.frac = res1;
> +                             st = FLOAT_EXP_POS;
> +                             /* erase result */
> +                             res1 = 0;
> +                     } else {
> +                             st = ERROR;
> +                     }
> +                     break;
> +
> +             case FLOAT_NEG_OK:
> +                     if (c >= '0' && c <= '9') {
> +                             if (add_to_res(c - '0', &res1, 10) < 0)
> +                                     st = ERROR;
> +                             else
> +                                     fps.frac_exp++;
> +                     } else if (c == 'e' || c == 'E') {
> +                             fps.frac = res1;
> +                             st = FLOAT_EXP_POS;
> +                             /* erase result */
> +                             res1 = 0;
> +                     } else {
> +                             st = ERROR;
> +                     }
> +                     break;
> +
> +             case FLOAT_EXP_POS_OK:
> +                     /* exponent is always whole */
> +                     if (c >= '0' && c <= '9') {
> +                             if (add_to_res(c - '0', &res1, 10) < 0)
> +                                     st = ERROR;
> +                     } else {
> +                             st = ERROR;
> +                     }
> +                     break;
> +
> +             case FLOAT_EXP_NEG_OK:
> +                     /* exponent is always whole */
> +                     if (c >= '0' && c <= '9') {
> +                             if (add_to_res(c - '0', &res1, 10) < 0)
> +                                     st = ERROR;
> +                     } else {
> +                             st = ERROR;
> +                     }
> +                     break;
> +
>               case HEX:
>                       st = HEX_OK;
>                       /* fall-through */
> @@ -282,6 +493,12 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const 
> char *srcbuf, void *res,
>               } else if (nd.type == RTE_UINT64) {
>                       if (res) *(uint64_t *)res = res1;
>                       return buf-srcbuf;
> +             } else if (nd.type == RTE_FLOAT_SINGLE || nd.type == 
> RTE_FLOAT_DOUBLE) {
> +                     /* parsed double from integer */
> +                     fps.dec = res1;
> +                     if (check_float_result(nd.type, &fps, res) < 0)
> +                             return -1;
> +                     return buf-srcbuf;
>               } else {
>                       return -1;
>               }
> @@ -304,6 +521,62 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const 
> char *srcbuf, void *res,
>                               res1 <= (uint64_t)INT64_MAX + 1) {
>                       if (res) *(int64_t *)res = (int64_t) (-res1);
>                       return buf-srcbuf;
> +             } else if (nd.type == RTE_FLOAT_SINGLE || nd.type == 
> RTE_FLOAT_DOUBLE) {
> +                     /* parsed double from negative integer */
> +                     fps.dec = res1;
> +                     fps.flags |= FLOAT_FLAG_NEG_RES;
> +                     if (check_float_result(nd.type, &fps, res) < 0)
> +                             return -1;
> +                     return buf-srcbuf;
> +             } else {
> +                     return -1;
> +             }
> +             break;
> +
> +     case FLOAT_POS_OK:
> +             if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) 
> {
> +                     fps.frac = res1;
> +
> +                     if (check_float_result(nd.type, &fps, res) < 0)
> +                             return -1;
> +                     return buf-srcbuf;
> +             } else {
> +                     return -1;
> +             }
> +             break;
> +
> +     case FLOAT_NEG_OK:
> +             if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) 
> {
> +                     fps.frac = res1;
> +
> +                     if (check_float_result(nd.type, &fps, res) < 0)
> +                             return -1;
> +                     return buf-srcbuf;
> +             } else {
> +                     return -1;
> +             }
> +             break;
> +
> +     case FLOAT_EXP_POS_OK:
> +             /* watch for overflow in the exponent */
> +             if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) 
> {
> +                     fps.exp = res1;
> +
> +                     if (check_float_result(nd.type, &fps, res) < 0)
> +                             return -1;
> +                     return buf-srcbuf;
> +             } else {
> +                     return -1;
> +             }
> +             break;
> +
> +     case FLOAT_EXP_NEG_OK:
> +             if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) 
> {
> +                     fps.exp = res1;
> +
> +                     if (check_float_result(nd.type, &fps, res) < 0)
> +                             return -1;
> +                     return buf-srcbuf;
>               } else {
>                       return -1;
>               }
> diff --git a/lib/cmdline/cmdline_parse_num.h b/lib/cmdline/cmdline_parse_num.h
> index bdd0267612..b2792a2d11 100644
> --- a/lib/cmdline/cmdline_parse_num.h
> +++ b/lib/cmdline/cmdline_parse_num.h
> @@ -22,7 +22,9 @@ enum cmdline_numtype {
>       RTE_INT8,
>       RTE_INT16,
>       RTE_INT32,
> -     RTE_INT64
> +     RTE_INT64,
> +     RTE_FLOAT_SINGLE,
> +     RTE_FLOAT_DOUBLE,
>  };
> 
>  struct cmdline_token_num_data {
> --
> 2.47.1

Reply via email to