From: Konstantin Ananyev <konstantin.ananyev@huawei.com>
To: Anatoly Burakov <anatoly.burakov@intel.com>,
"dev@dpdk.org" <dev@dpdk.org>
Subject: RE: [PATCH v4 1/2] cmdline: add floating point support
Date: Wed, 7 May 2025 10:35:57 +0000 [thread overview]
Message-ID: <73248ba4775b4b95b117890851b8257e@huawei.com> (raw)
In-Reply-To: <e8234c26b5dd91aaa9e7b1e38887b1d6fdb2d053.1746612074.git.anatoly.burakov@intel.com>
> 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.burakov@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
next prev parent reply other threads:[~2025-05-07 10:36 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-02 12:27 [PATCH v1 1/1] app/testpmd: add sleep command Anatoly Burakov
2025-05-02 12:37 ` Bruce Richardson
2025-05-02 14:35 ` Burakov, Anatoly
2025-05-02 14:43 ` Bruce Richardson
2025-05-02 15:33 ` Morten Brørup
2025-05-02 15:42 ` Stephen Hemminger
2025-05-06 12:36 ` Burakov, Anatoly
2025-05-06 13:08 ` [PATCH v2 1/2] cmdline: add floating point support Anatoly Burakov
2025-05-06 13:08 ` [PATCH v2 2/2] app/testpmd: add sleep command Anatoly Burakov
2025-05-06 13:38 ` [PATCH v2 1/2] cmdline: add floating point support Bruce Richardson
2025-05-07 9:02 ` Burakov, Anatoly
2025-05-07 9:50 ` [PATCH v3 " Anatoly Burakov
2025-05-07 9:50 ` [PATCH v3 2/2] app/testpmd: add sleep command Anatoly Burakov
2025-05-07 9:53 ` [PATCH v3 1/2] cmdline: add floating point support Burakov, Anatoly
2025-05-07 10:01 ` [PATCH v4 " Anatoly Burakov
2025-05-07 10:01 ` [PATCH v4 2/2] app/testpmd: add sleep command Anatoly Burakov
2025-05-07 10:35 ` Konstantin Ananyev [this message]
2025-05-07 11:06 ` [PATCH v4 1/2] cmdline: add floating point support Burakov, Anatoly
2025-05-07 12:24 ` Konstantin Ananyev
2025-05-07 14:06 ` Burakov, Anatoly
2025-05-07 15:22 ` [PATCH v5 1/3] cmdline: use C standard library as number parser Anatoly Burakov
2025-05-07 15:22 ` [PATCH v5 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-07 15:22 ` [PATCH v5 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-08 7:27 ` [PATCH v5 1/3] cmdline: use C standard library as number parser Bruce Richardson
2025-05-08 8:35 ` Burakov, Anatoly
2025-05-08 9:53 ` [PATCH v6 " Anatoly Burakov
2025-05-08 9:53 ` [PATCH v6 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-08 9:53 ` [PATCH v6 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-08 10:01 ` [PATCH v7 1/3] cmdline: use C standard library as number parser Anatoly Burakov
2025-05-08 10:01 ` [PATCH v7 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-08 10:09 ` Burakov, Anatoly
2025-05-08 10:01 ` [PATCH v7 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-08 13:16 ` [PATCH v8 1/3] cmdline: use C standard library as number parser Anatoly Burakov
2025-05-08 13:16 ` [PATCH v8 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-08 13:16 ` [PATCH v8 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-09 13:02 ` [PATCH v8 1/3] cmdline: use C standard library as number parser Burakov, Anatoly
2025-05-09 13:08 ` Burakov, Anatoly
2025-05-09 13:27 ` Burakov, Anatoly
2025-05-09 13:39 ` [PATCH v9 " Anatoly Burakov
2025-05-09 13:39 ` [PATCH v9 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-09 13:39 ` [PATCH v9 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-09 13:42 ` [PATCH v9 1/3] cmdline: use C standard library as number parser Burakov, Anatoly
2025-05-09 14:41 ` [PATCH v10 " Anatoly Burakov
2025-05-09 14:41 ` [PATCH v10 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-09 14:41 ` [PATCH v10 3/3] app/testpmd: add sleep command Anatoly Burakov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=73248ba4775b4b95b117890851b8257e@huawei.com \
--to=konstantin.ananyev@huawei.com \
--cc=anatoly.burakov@intel.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).