From f77e5a5ec7f8b1373eeda0ea56f47137daf40330 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sat, 4 Jan 2025 17:57:28 -0800 Subject: args: Convert nng_opts_parse into a header only library using `nng_args_parse`. The API is identical, except that some names have changed, and this is now a header library in `nng/args.h` - so the core library does not need to carry this code in binaries. Being a header library also means it is not necessary to link against NNG, and it does not include any parts of NNG; it only depends on a standard C99 or C11 environment. --- src/CMakeLists.txt | 3 +- src/core/CMakeLists.txt | 1 + src/core/args_test.c | 342 ++++++++++++++++++++++++++++++++++ src/nng.c | 2 - src/sp/protocol/pipeline0/pull_test.c | 4 +- src/sp/protocol/pubsub0/sub_test.c | 4 +- src/supplemental/CMakeLists.txt | 1 - src/supplemental/util/CMakeLists.txt | 13 -- src/supplemental/util/options.c | 127 ------------- src/supplemental/util/options_test.c | 341 --------------------------------- src/tools/nngcat/nngcat.c | 164 ++++++++-------- src/tools/perf/perf.c | 26 +-- 12 files changed, 444 insertions(+), 584 deletions(-) create mode 100644 src/core/args_test.c delete mode 100644 src/supplemental/util/CMakeLists.txt delete mode 100644 src/supplemental/util/options.c delete mode 100644 src/supplemental/util/options_test.c (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b49048fa..1bdd4b7a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2024 Staysail Systems, Inc. +# Copyright 2025 Staysail Systems, Inc. # Copyright 2018 Capitar IT Group BV # # This software is supplied under the terms of the MIT License, a @@ -9,6 +9,7 @@ # nng_sources(nng.c nng_legacy.c) +nng_headers(nng/args.h) nng_headers(nng/nng.h) target_include_directories(nng PRIVATE ${PROJECT_SOURCE_DIR}/src) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9f5b4a95..a247ed89 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -81,6 +81,7 @@ nng_sources( ) nng_test(aio_test) +nng_test(args_test) nng_test(buf_size_test) nng_test(errors_test) nng_test(id_test) diff --git a/src/core/args_test.c b/src/core/args_test.c new file mode 100644 index 00000000..5139fece --- /dev/null +++ b/src/core/args_test.c @@ -0,0 +1,342 @@ +// +// Copyright 2024 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#include +#include +#include + +static nng_arg_spec case1[] = { + // clang-format off + { "flag", 'f', 1, false }, + { "longflag", 0, 2, false }, + { "value", 'v', 3, true }, + { NULL, 'b', 4, false }, + { NULL, 0, 0, false }, + // clang-format on +}; + +void +test_simple_options(void) +{ + int opti = 1; + char *av[6]; + int ac = 5; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "-f"; + av[2] = "-v"; + av[3] = "123"; + av[4] = "456"; + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(v == 1); + NUTS_NULL(a); + NUTS_TRUE(opti == 2); + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 4); + NUTS_TRUE(v == 3); + NUTS_MATCH(a, "123"); + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); + NUTS_TRUE(opti == 4); + NUTS_MATCH(av[opti], "456"); +} + +void +test_long_options(void) +{ + int opti = 1; + char *av[6]; + int ac = 5; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "--flag"; + av[2] = "--value"; + av[3] = "123"; + av[4] = "456"; + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(v == 1); + NUTS_NULL(a); + NUTS_TRUE(opti == 2); + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 4); + NUTS_TRUE(v == 3); + NUTS_MATCH(a, "123"); + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); + NUTS_TRUE(opti == 4); + NUTS_MATCH(av[opti], "456"); +} + +void +test_attached_short(void) +{ + int opti = 1; + char *av[3]; + int ac = 3; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "-v123"; + av[2] = "456"; + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 2); + NUTS_TRUE(v == 3); + NUTS_MATCH(a, "123"); + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); + NUTS_TRUE(opti == 2); + NUTS_MATCH(av[opti], "456"); +} + +void +test_attached_long_equals(void) +{ + int opti = 1; + char *av[3]; + int ac = 3; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "--value=123"; + av[2] = "456"; + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 2); + NUTS_TRUE(v == 3); + NUTS_MATCH(a, "123"); + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); + NUTS_TRUE(opti == 2); + NUTS_MATCH(av[opti], "456"); +} + +void +test_attached_long_colon(void) +{ + int opti = 1; + char *av[3]; + int ac = 3; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "--value:123"; + av[2] = "456"; + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 2); + NUTS_TRUE(v == 3); + NUTS_MATCH(a, "123"); + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); + NUTS_TRUE(opti == 2); + NUTS_MATCH(av[opti], "456"); +} + +void +test_negative_bad_short(void) +{ + int opti = 1; + char *av[3]; + int ac = 3; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "-Z"; + av[2] = "456"; + NUTS_FAIL(nng_args_parse(ac, av, case1, &v, &a, &opti), NNG_ARG_INVAL); + NUTS_TRUE(opti == 1); +} + +void +test_negative_bad_long(void) +{ + int opti = 1; + char *av[3]; + int ac = 3; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "--something"; + av[2] = "456"; + NUTS_FAIL(nng_args_parse(ac, av, case1, &v, &a, &opti), NNG_ARG_INVAL); + NUTS_TRUE(opti == 1); +} + +void +test_option_separator_flag(void) +{ + int opti = 1; + char *av[5]; + int ac = 5; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "-f"; + av[2] = "-"; + av[3] = "-v"; + av[4] = "456"; + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(v == 1); + NUTS_TRUE(opti == 2); + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); + NUTS_TRUE(opti == 3); +} + +void +test_no_options(void) +{ + int opti = 1; + char *av[1]; + int ac = 1; + int v; + char *a = NULL; + + av[0] = "program"; + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); +} + +void +test_arg_only(void) +{ + int opti = 1; + char *av[2]; + int ac = 2; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "123"; + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); + NUTS_TRUE(opti == 1); +} + +void +test_mixed_long_short(void) +{ + int opti = 1; + char *av[7]; + int ac = 7; + int v; + char *a = NULL; + + av[0] = "program"; + av[1] = "--value=123"; + av[2] = "-f"; + av[3] = "--longflag"; + av[4] = "-b"; + av[5] = "-vxyz"; + av[6] = "456"; + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 2); + NUTS_TRUE(v == 3); + NUTS_MATCH(a, "123"); + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 3); + NUTS_TRUE(v == 1); + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 4); + NUTS_TRUE(v == 2); + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 5); + NUTS_TRUE(v == 4); + NUTS_PASS(nng_args_parse(ac, av, case1, &v, &a, &opti)); + NUTS_TRUE(opti == 6); + NUTS_TRUE(v == 3); + NUTS_MATCH(a, "xyz"); + NUTS_MATCH(av[opti], "456"); + NUTS_TRUE(nng_args_parse(ac, av, case1, &v, &a, &opti) == -1); + NUTS_TRUE(opti == 6); +} + +void +test_ambiguous(void) +{ + int opti = 1; + char *av[2]; + int ac = 2; + int v; + char *a = NULL; + + nng_arg_spec spec[] = { + { "flag", 'f', 1, false }, + { "fluid", 0, 2, false }, + { NULL, 0, 0, false }, + }; + + av[0] = "program"; + av[1] = "--fl"; + NUTS_FAIL(nng_args_parse(ac, av, spec, &v, &a, &opti), NNG_ARG_AMBIG); +} + +void +test_missing_arg(void) +{ + int opti = 1; + char *av[2]; + int ac = 2; + int v; + char *a = NULL; + + nng_arg_spec spec[] = { + { "flag", 'f', 1, true }, + { NULL, 0, 0, false }, + }; + + av[0] = "program"; + av[1] = "--fl"; + NUTS_FAIL( + nng_args_parse(ac, av, spec, &v, &a, &opti), NNG_ARG_MISSING); + av[0] = "program"; + av[1] = "-f"; + opti = 1; + NUTS_FAIL( + nng_args_parse(ac, av, spec, &v, &a, &opti), NNG_ARG_MISSING); +} + +void +test_no_clustering(void) +{ + int opti = 1; + char *av[2]; + int ac = 2; + int v; + char *a = NULL; + + nng_arg_spec spec[] = { + { "flag", 'f', 1, false }, + { "verbose", 'v', 2, false }, + { NULL, 0, 0, false }, + }; + + av[0] = "program"; + av[1] = "-fv"; + NUTS_FAIL(nng_args_parse(ac, av, spec, &v, &a, &opti), NNG_ARG_INVAL); +} + +NUTS_TESTS = { + { "simple options", test_simple_options }, + { "long options", test_long_options }, + { "separator flag", test_option_separator_flag }, + { "no options", test_no_options }, + { "attached short", test_attached_long_equals }, + { "attached long equals", test_attached_long_equals }, + { "attached long colon", test_attached_long_colon }, + { "bad short", test_negative_bad_short }, + { "bad long", test_negative_bad_long }, + { "arg only", test_arg_only }, + { "options mixed long short", test_mixed_long_short }, + { "ambiguous options", test_ambiguous }, + { "missing argument", test_missing_arg }, + { "no clustering", test_no_clustering }, + { NULL, NULL }, +}; diff --git a/src/nng.c b/src/nng.c index 345f47d9..002f29f8 100644 --- a/src/nng.c +++ b/src/nng.c @@ -1266,8 +1266,6 @@ static const struct { { NNG_EWRITEONLY, "Write only resource" }, { NNG_ECRYPTO, "Cryptographic error" }, { NNG_EPEERAUTH, "Peer could not be authenticated" }, - { NNG_ENOARG, "Option requires argument" }, - { NNG_EAMBIGUOUS, "Ambiguous option" }, { NNG_EBADTYPE, "Incorrect type" }, { NNG_ECONNSHUT, "Connection shutdown" }, { NNG_ESTOPPED, "Operation stopped"}, diff --git a/src/sp/protocol/pipeline0/pull_test.c b/src/sp/protocol/pipeline0/pull_test.c index 8ed9cc0e..32134082 100644 --- a/src/sp/protocol/pipeline0/pull_test.c +++ b/src/sp/protocol/pipeline0/pull_test.c @@ -243,10 +243,10 @@ test_pull_recv_abort(void) nng_aio_set_timeout(aio, 1000); nng_socket_recv(s, aio); - nng_aio_abort(aio, NNG_EAMBIGUOUS); + nng_aio_abort(aio, NNG_ESTATE); nng_aio_wait(aio); - NUTS_FAIL(nng_aio_result(aio), NNG_EAMBIGUOUS); + NUTS_FAIL(nng_aio_result(aio), NNG_ESTATE); NUTS_CLOSE(s); nng_aio_free(aio); } diff --git a/src/sp/protocol/pubsub0/sub_test.c b/src/sp/protocol/pubsub0/sub_test.c index 13fc07bf..7f4e4480 100644 --- a/src/sp/protocol/pubsub0/sub_test.c +++ b/src/sp/protocol/pubsub0/sub_test.c @@ -301,10 +301,10 @@ test_sub_ctx_recv_abort(void) nng_aio_set_timeout(aio, 1000); nng_ctx_recv(ctx, aio); - nng_aio_abort(aio, NNG_EAMBIGUOUS); + nng_aio_abort(aio, NNG_EINTERNAL); nng_aio_wait(aio); - NUTS_FAIL(nng_aio_result(aio), NNG_EAMBIGUOUS); + NUTS_FAIL(nng_aio_result(aio), NNG_EINTERNAL); NUTS_CLOSE(sub); nng_aio_free(aio); } diff --git a/src/supplemental/CMakeLists.txt b/src/supplemental/CMakeLists.txt index 9a54beea..fe808c8d 100644 --- a/src/supplemental/CMakeLists.txt +++ b/src/supplemental/CMakeLists.txt @@ -11,5 +11,4 @@ nng_directory(supplemental) add_subdirectory(http) add_subdirectory(tls) -add_subdirectory(util) add_subdirectory(websocket) diff --git a/src/supplemental/util/CMakeLists.txt b/src/supplemental/util/CMakeLists.txt deleted file mode 100644 index d7541363..00000000 --- a/src/supplemental/util/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright 2025 Staysail Systems, Inc. -# -# This software is supplied under the terms of the MIT License, a -# copy of which should be located in the distribution where this -# file was obtained (LICENSE.txt). A copy of the license may also be -# found online at https://opensource.org/licenses/MIT. -# - -nng_sources(options.c) -nng_headers( - nng/supplemental/util/options.h) -nng_test(options_test) diff --git a/src/supplemental/util/options.c b/src/supplemental/util/options.c deleted file mode 100644 index 961e0bb2..00000000 --- a/src/supplemental/util/options.c +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright 2018 Staysail Systems, Inc. -// Copyright 2018 Capitar IT Group BV -// -// This software is supplied under the terms of the MIT License, a -// copy of which should be located in the distribution where this -// file was obtained (LICENSE.txt). A copy of the license may also be -// found online at https://opensource.org/licenses/MIT. -// - -#include -#include - -#include -#include - -#include "core/nng_impl.h" - -// Call with optidx set to 1 to start parsing. -int -nng_opts_parse(int argc, char *const *argv, const nng_optspec *opts, int *val, - char **optarg, int *optidx) -{ - const nng_optspec *opt; - int matches; - bool shortopt; - size_t l; - char * arg; - int i; - - if ((i = *optidx) >= argc) { - return (-1); - } - arg = argv[*optidx]; - - if (arg[0] != '-') { - return (-1); - } - if (arg[1] == '\0') { - *optidx = i + 1; - return (-1); - } - - if ((arg[0] == '-') && (arg[1] == '-')) { - arg += 2; - shortopt = false; - for (l = 0; arg[l] != '\0'; l++) { - if ((arg[l] == '=') || (arg[l] == ':')) { - break; - } - } - } else { - arg++; - shortopt = true; - l = 1; - } - - matches = 0; - opt = NULL; - - for (int x = 0; opts[x].o_val != 0; x++) { - - if (shortopt) { - if (arg[0] == opts[x].o_short) { - matches = 1; - opt = &opts[x]; - break; - } - continue; - } - - if ((opts[x].o_name == NULL) || - (strncmp(arg, opts[x].o_name, l) != 0)) { - continue; - } - matches++; - opt = &opts[x]; - - if (strlen(opts[x].o_name) == l) { - // Perfect match. - matches = 1; - break; - } - } - - switch (matches) { - case 1: - // Exact match - break; - case 0: - // No such option - return (NNG_EINVAL); - break; - default: - // Ambiguous (not match) - return (NNG_EAMBIGUOUS); - break; - } - - if (!opt->o_arg) { - // No option clustering for short options yet. - if (arg[l] != '\0') { - return (NNG_EINVAL); - } - *val = opt->o_val; - *optidx = i + 1; - return (0); - } - - if (arg[l] != '\0') { - if (shortopt) { - *optarg = arg + l; - } else { - *optarg = arg + l + 1; - } - } else { - i++; - if (i >= argc) { - return (NNG_ENOARG); - } - *optarg = argv[i]; - } - *optidx = ++i; - *val = opt->o_val; - - return (0); -} diff --git a/src/supplemental/util/options_test.c b/src/supplemental/util/options_test.c deleted file mode 100644 index 036f2940..00000000 --- a/src/supplemental/util/options_test.c +++ /dev/null @@ -1,341 +0,0 @@ -// -// Copyright 2024 Staysail Systems, Inc. -// Copyright 2018 Capitar IT Group BV -// -// This software is supplied under the terms of the MIT License, a -// copy of which should be located in the distribution where this -// file was obtained (LICENSE.txt). A copy of the license may also be -// found online at https://opensource.org/licenses/MIT. -// - -#include "nng/nng.h" -#include - -#include - -static nng_optspec case1[] = { - // clang-format off - { "flag", 'f', 1, false }, - { "longflag", 0, 2, false }, - { "value", 'v', 3, true }, - { NULL, 'b', 4, false }, - { NULL, 0, 0, false }, - // clang-format on -}; - -void -test_simple_options(void) -{ - int opti = 1; - char *av[6]; - int ac = 5; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "-f"; - av[2] = "-v"; - av[3] = "123"; - av[4] = "456"; - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(v == 1); - NUTS_NULL(a); - NUTS_TRUE(opti == 2); - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 4); - NUTS_TRUE(v == 3); - NUTS_MATCH(a, "123"); - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); - NUTS_TRUE(opti == 4); - NUTS_MATCH(av[opti], "456"); -} - -void -test_long_options(void) -{ - int opti = 1; - char *av[6]; - int ac = 5; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "--flag"; - av[2] = "--value"; - av[3] = "123"; - av[4] = "456"; - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(v == 1); - NUTS_NULL(a); - NUTS_TRUE(opti == 2); - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 4); - NUTS_TRUE(v == 3); - NUTS_MATCH(a, "123"); - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); - NUTS_TRUE(opti == 4); - NUTS_MATCH(av[opti], "456"); -} - -void -test_attached_short(void) -{ - int opti = 1; - char *av[3]; - int ac = 3; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "-v123"; - av[2] = "456"; - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 2); - NUTS_TRUE(v == 3); - NUTS_MATCH(a, "123"); - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); - NUTS_TRUE(opti == 2); - NUTS_MATCH(av[opti], "456"); -} - -void -test_attached_long_equals(void) -{ - int opti = 1; - char *av[3]; - int ac = 3; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "--value=123"; - av[2] = "456"; - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 2); - NUTS_TRUE(v == 3); - NUTS_MATCH(a, "123"); - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); - NUTS_TRUE(opti == 2); - NUTS_MATCH(av[opti], "456"); -} - -void -test_attached_long_colon(void) -{ - int opti = 1; - char *av[3]; - int ac = 3; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "--value:123"; - av[2] = "456"; - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 2); - NUTS_TRUE(v == 3); - NUTS_MATCH(a, "123"); - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); - NUTS_TRUE(opti == 2); - NUTS_MATCH(av[opti], "456"); -} - -void -test_negative_bad_short(void) -{ - int opti = 1; - char *av[3]; - int ac = 3; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "-Z"; - av[2] = "456"; - NUTS_FAIL(nng_opts_parse(ac, av, case1, &v, &a, &opti), NNG_EINVAL); - NUTS_TRUE(opti == 1); -} - -void -test_negative_bad_long(void) -{ - int opti = 1; - char *av[3]; - int ac = 3; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "--something"; - av[2] = "456"; - NUTS_FAIL(nng_opts_parse(ac, av, case1, &v, &a, &opti), NNG_EINVAL); - NUTS_TRUE(opti == 1); -} - -void -test_option_separator_flag(void) -{ - int opti = 1; - char *av[5]; - int ac = 5; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "-f"; - av[2] = "-"; - av[3] = "-v"; - av[4] = "456"; - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(v == 1); - NUTS_TRUE(opti == 2); - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); - NUTS_TRUE(opti == 3); -} - -void -test_no_options(void) -{ - int opti = 1; - char *av[1]; - int ac = 1; - int v; - char *a = NULL; - - av[0] = "program"; - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); -} - -void -test_arg_only(void) -{ - int opti = 1; - char *av[2]; - int ac = 2; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "123"; - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); - NUTS_TRUE(opti == 1); -} - -void -test_mixed_long_short(void) -{ - int opti = 1; - char *av[7]; - int ac = 7; - int v; - char *a = NULL; - - av[0] = "program"; - av[1] = "--value=123"; - av[2] = "-f"; - av[3] = "--longflag"; - av[4] = "-b"; - av[5] = "-vxyz"; - av[6] = "456"; - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 2); - NUTS_TRUE(v == 3); - NUTS_MATCH(a, "123"); - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 3); - NUTS_TRUE(v == 1); - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 4); - NUTS_TRUE(v == 2); - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 5); - NUTS_TRUE(v == 4); - NUTS_PASS(nng_opts_parse(ac, av, case1, &v, &a, &opti)); - NUTS_TRUE(opti == 6); - NUTS_TRUE(v == 3); - NUTS_MATCH(a, "xyz"); - NUTS_MATCH(av[opti], "456"); - NUTS_TRUE(nng_opts_parse(ac, av, case1, &v, &a, &opti) == -1); - NUTS_TRUE(opti == 6); -} - -void -test_ambiguous(void) -{ - int opti = 1; - char *av[2]; - int ac = 2; - int v; - char *a = NULL; - - nng_optspec spec[] = { - { "flag", 'f', 1, false }, - { "fluid", 0, 2, false }, - { NULL, 0, 0, false }, - }; - - av[0] = "program"; - av[1] = "--fl"; - NUTS_FAIL(nng_opts_parse(ac, av, spec, &v, &a, &opti), NNG_EAMBIGUOUS); -} - -void -test_missing_arg(void) -{ - int opti = 1; - char *av[2]; - int ac = 2; - int v; - char *a = NULL; - - nng_optspec spec[] = { - { "flag", 'f', 1, true }, - { NULL, 0, 0, false }, - }; - - av[0] = "program"; - av[1] = "--fl"; - NUTS_FAIL(nng_opts_parse(ac, av, spec, &v, &a, &opti), NNG_ENOARG); - av[0] = "program"; - av[1] = "-f"; - opti = 1; - NUTS_FAIL(nng_opts_parse(ac, av, spec, &v, &a, &opti), NNG_ENOARG); -} - -void -test_no_clustering(void) -{ - int opti = 1; - char *av[2]; - int ac = 2; - int v; - char *a = NULL; - - nng_optspec spec[] = { - { "flag", 'f', 1, false }, - { "verbose", 'v', 2, false }, - { NULL, 0, 0, false }, - }; - - av[0] = "program"; - av[1] = "-fv"; - NUTS_FAIL(nng_opts_parse(ac, av, spec, &v, &a, &opti), NNG_EINVAL); -} - -NUTS_TESTS = { - { "simple options", test_simple_options }, - { "long options", test_long_options }, - { "separator flag", test_option_separator_flag }, - { "no options", test_no_options }, - { "attached short", test_attached_long_equals }, - { "attached long equals", test_attached_long_equals }, - { "attached long colon", test_attached_long_colon }, - { "bad short", test_negative_bad_short }, - { "bad long", test_negative_bad_long }, - { "arg only", test_arg_only }, - { "options mixed long short", test_mixed_long_short }, - { "ambiguous options", test_ambiguous }, - { "missing argument", test_missing_arg }, - { "no clustering", test_no_clustering }, - { NULL, NULL }, -}; diff --git a/src/tools/nngcat/nngcat.c b/src/tools/nngcat/nngcat.c index dc998cf3..26b7c639 100644 --- a/src/tools/nngcat/nngcat.c +++ b/src/tools/nngcat/nngcat.c @@ -1,5 +1,5 @@ // -// Copyright 2024 Staysail Systems, Inc. +// Copyright 2025 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2020 Lager Data, Inc. // @@ -17,8 +17,8 @@ #include #include +#include #include -#include // Globals. We need this to avoid passing around everything. int format = 0; @@ -91,105 +91,105 @@ enum options { OPT_RECVMAXSZ, }; -static nng_optspec opts[] = { - { .o_name = "help", .o_short = 'h', .o_val = OPT_HELP }, - { .o_name = "verbose", .o_short = 'v', .o_val = OPT_VERBOSE }, - { .o_name = "silent", .o_short = 'q', .o_val = OPT_SILENT }, - { .o_name = "req0", .o_val = OPT_REQ0 }, - { .o_name = "rep0", .o_val = OPT_REP0 }, - { .o_name = "push0", .o_val = OPT_PUSH0 }, - { .o_name = "pull0", .o_val = OPT_PULL0 }, - { .o_name = "pub0", .o_val = OPT_PUB0 }, - { .o_name = "sub", .o_val = OPT_SUB0 }, // explicit for alias - { .o_name = "sub0", .o_val = OPT_SUB0 }, - { .o_name = "surveyor0", .o_val = OPT_SURVEY0 }, - { .o_name = "respondent0", .o_val = OPT_RESPOND0 }, - { .o_name = "pair", .o_val = OPT_PAIR }, - { .o_name = "pair0", .o_val = OPT_PAIR0 }, - { .o_name = "pair1", .o_val = OPT_PAIR1 }, - { .o_name = "bus0", .o_val = OPT_BUS0 }, - { .o_name = "dial", .o_val = OPT_DIAL, .o_arg = true }, - { .o_name = "listen", .o_val = OPT_LISTEN, .o_arg = true }, - { .o_name = "data", .o_short = 'D', .o_val = OPT_DATA, .o_arg = true }, - { .o_name = "file", .o_short = 'F', .o_val = OPT_FILE, .o_arg = true }, - { .o_name = "subscribe", .o_val = OPT_SUBSCRIBE, .o_arg = true }, - { .o_name = "format", .o_val = OPT_FORMAT, .o_arg = true }, - { .o_name = "ascii", .o_short = 'A', .o_val = OPT_ASCII }, - { .o_name = "quoted", .o_short = 'Q', .o_val = OPT_QUOTED }, - { .o_name = "raw", .o_val = OPT_RAW }, - { .o_name = "hex", .o_val = OPT_HEX }, - { .o_name = "compat", .o_val = OPT_COMPAT }, - { .o_name = "async", .o_val = OPT_ASYNC }, - { .o_name = "msgpack", .o_val = OPT_MSGPACK }, +static nng_arg_spec opts[] = { + { .a_name = "help", .a_short = 'h', .a_val = OPT_HELP }, + { .a_name = "verbose", .a_short = 'v', .a_val = OPT_VERBOSE }, + { .a_name = "silent", .a_short = 'q', .a_val = OPT_SILENT }, + { .a_name = "req0", .a_val = OPT_REQ0 }, + { .a_name = "rep0", .a_val = OPT_REP0 }, + { .a_name = "push0", .a_val = OPT_PUSH0 }, + { .a_name = "pull0", .a_val = OPT_PULL0 }, + { .a_name = "pub0", .a_val = OPT_PUB0 }, + { .a_name = "sub", .a_val = OPT_SUB0 }, // explicit for alias + { .a_name = "sub0", .a_val = OPT_SUB0 }, + { .a_name = "surveyor0", .a_val = OPT_SURVEY0 }, + { .a_name = "respondent0", .a_val = OPT_RESPOND0 }, + { .a_name = "pair", .a_val = OPT_PAIR }, + { .a_name = "pair0", .a_val = OPT_PAIR0 }, + { .a_name = "pair1", .a_val = OPT_PAIR1 }, + { .a_name = "bus0", .a_val = OPT_BUS0 }, + { .a_name = "dial", .a_val = OPT_DIAL, .a_arg = true }, + { .a_name = "listen", .a_val = OPT_LISTEN, .a_arg = true }, + { .a_name = "data", .a_short = 'D', .a_val = OPT_DATA, .a_arg = true }, + { .a_name = "file", .a_short = 'F', .a_val = OPT_FILE, .a_arg = true }, + { .a_name = "subscribe", .a_val = OPT_SUBSCRIBE, .a_arg = true }, + { .a_name = "format", .a_val = OPT_FORMAT, .a_arg = true }, + { .a_name = "ascii", .a_short = 'A', .a_val = OPT_ASCII }, + { .a_name = "quoted", .a_short = 'Q', .a_val = OPT_QUOTED }, + { .a_name = "raw", .a_val = OPT_RAW }, + { .a_name = "hex", .a_val = OPT_HEX }, + { .a_name = "compat", .a_val = OPT_COMPAT }, + { .a_name = "async", .a_val = OPT_ASYNC }, + { .a_name = "msgpack", .a_val = OPT_MSGPACK }, { - .o_name = "recv-maxsz", - .o_short = 'Z', - .o_val = OPT_RECVMAXSZ, - .o_arg = true, + .a_name = "recv-maxsz", + .a_short = 'Z', + .a_val = OPT_RECVMAXSZ, + .a_arg = true, }, { - .o_name = "count", - .o_short = 'C', - .o_val = OPT_COUNT, - .o_arg = true, + .a_name = "count", + .a_short = 'C', + .a_val = OPT_COUNT, + .a_arg = true, }, { - .o_name = "delay", - .o_short = 'd', - .o_val = OPT_DELAY, - .o_arg = true, + .a_name = "delay", + .a_short = 'd', + .a_val = OPT_DELAY, + .a_arg = true, }, { - .o_name = "interval", - .o_short = 'i', - .o_val = OPT_INTERVAL, - .o_arg = true, + .a_name = "interval", + .a_short = 'i', + .a_val = OPT_INTERVAL, + .a_arg = true, }, - { .o_name = "recv-timeout", .o_val = OPT_RCV_TIMEO, .o_arg = true }, - { .o_name = "send-timeout", .o_val = OPT_SND_TIMEO, .o_arg = true }, - { .o_name = "socket-name", .o_val = OPT_SOCK_NAME, .o_arg = true }, + { .a_name = "recv-timeout", .a_val = OPT_RCV_TIMEO, .a_arg = true }, + { .a_name = "send-timeout", .a_val = OPT_SND_TIMEO, .a_arg = true }, + { .a_name = "socket-name", .a_val = OPT_SOCK_NAME, .a_arg = true }, // Legacy compatibility with nanocat. - { .o_name = "bind", .o_val = OPT_LISTEN, .o_arg = true }, - { .o_name = "connect", .o_val = OPT_DIAL, .o_arg = true }, + { .a_name = "bind", .a_val = OPT_LISTEN, .a_arg = true }, + { .a_name = "connect", .a_val = OPT_DIAL, .a_arg = true }, { - .o_name = "bind-ipc", - .o_short = 'X', - .o_val = OPT_LISTEN_IPC, - .o_arg = true, + .a_name = "bind-ipc", + .a_short = 'X', + .a_val = OPT_LISTEN_IPC, + .a_arg = true, }, { - .o_name = "connect-ipc", - .o_short = 'x', - .o_val = OPT_DIAL_IPC, - .o_arg = true, + .a_name = "connect-ipc", + .a_short = 'x', + .a_val = OPT_DIAL_IPC, + .a_arg = true, }, { - .o_name = "bind-local", - .o_short = 'L', - .o_val = OPT_LISTEN_LOCAL, - .o_arg = true, + .a_name = "bind-local", + .a_short = 'L', + .a_val = OPT_LISTEN_LOCAL, + .a_arg = true, }, { - .o_name = "connect-local", - .o_short = 'l', - .o_val = OPT_DIAL_LOCAL, - .o_arg = true, + .a_name = "connect-local", + .a_short = 'l', + .a_val = OPT_DIAL_LOCAL, + .a_arg = true, }, - { .o_name = "insecure", .o_short = 'k', .o_val = OPT_INSECURE }, - { .o_name = "cacert", .o_val = OPT_CACERT, .o_arg = true }, - { .o_name = "key", .o_val = OPT_KEYFILE, .o_arg = true }, + { .a_name = "insecure", .a_short = 'k', .a_val = OPT_INSECURE }, + { .a_name = "cacert", .a_val = OPT_CACERT, .a_arg = true }, + { .a_name = "key", .a_val = OPT_KEYFILE, .a_arg = true }, { - .o_name = "cert", - .o_short = 'E', - .o_val = OPT_CERTFILE, - .o_arg = true, + .a_name = "cert", + .a_short = 'E', + .a_val = OPT_CERTFILE, + .a_arg = true, }, - { .o_name = "version", .o_short = 'V', .o_val = OPT_VERSION }, + { .a_name = "version", .a_short = 'V', .a_val = OPT_VERSION }, // Sentinel. - { .o_name = NULL, .o_val = 0 }, + { .a_name = NULL, .a_val = 0 }, }; static void @@ -705,7 +705,7 @@ main(int ac, char **av) nng_init(NULL); atexit(nng_fini); - while ((rv = nng_opts_parse(ac, av, opts, &val, &arg, &idx)) == 0) { + while ((rv = nng_args_parse(ac, av, opts, &val, &arg, &idx)) == 0) { switch (val) { case OPT_HELP: help(); @@ -860,13 +860,13 @@ main(int ac, char **av) } } switch (rv) { - case NNG_EINVAL: + case NNG_ARG_INVAL: fatal("Option %s is invalid.", av[idx]); break; - case NNG_EAMBIGUOUS: + case NNG_ARG_AMBIG: fatal("Option %s is ambiguous (specify in full).", av[idx]); break; - case NNG_ENOARG: + case NNG_ARG_MISSING: fatal("Option %s requires argument.", av[idx]); break; default: diff --git a/src/tools/perf/perf.c b/src/tools/perf/perf.c index 5ce99c04..e83c89ff 100644 --- a/src/tools/perf/perf.c +++ b/src/tools/perf/perf.c @@ -1,5 +1,5 @@ // -// Copyright 2024 Staysail Systems, Inc. +// Copyright 2025 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -15,8 +15,8 @@ #include #include +#include #include -#include static void die(const char *, ...); static int @@ -80,15 +80,15 @@ enum options { }; // These are not universally supported by the variants yet. -static nng_optspec opts[] = { - { .o_name = "pair1", .o_val = OPT_PAIR1 }, - { .o_name = "pair0", .o_val = OPT_PAIR0 }, - { .o_name = "reqrep0", .o_val = OPT_REQREP0 }, - { .o_name = "bus0", .o_val = OPT_BUS0 }, - { .o_name = "pubsub0", .o_val = OPT_PUBSUB0 }, - { .o_name = "pipeline0", .o_val = OPT_PIPELINE0 }, - { .o_name = "url", .o_val = OPT_URL, .o_arg = true }, - { .o_name = NULL, .o_val = 0 }, +static nng_arg_spec opts[] = { + { .a_name = "pair1", .a_val = OPT_PAIR1 }, + { .a_name = "pair0", .a_val = OPT_PAIR0 }, + { .a_name = "reqrep0", .a_val = OPT_REQREP0 }, + { .a_name = "bus0", .a_val = OPT_BUS0 }, + { .a_name = "pubsub0", .a_val = OPT_PUBSUB0 }, + { .a_name = "pipeline0", .a_val = OPT_PIPELINE0 }, + { .a_name = "url", .a_val = OPT_URL, .a_arg = true }, + { .a_name = NULL, .a_val = 0 }, }; static void latency_client(const char *, size_t, int); @@ -319,7 +319,7 @@ do_inproc_lat(int argc, char **argv) addr = "inproc://latency_test"; optidx = 0; - while ((rv = nng_opts_parse(argc, argv, opts, &val, &arg, &optidx)) == + while ((rv = nng_args_parse(argc, argv, opts, &val, &arg, &optidx)) == 0) { switch (val) { case OPT_REQREP0: @@ -381,7 +381,7 @@ do_inproc_thr(int argc, char **argv) char *addr = "inproc://throughput-test"; optidx = 0; - while ((rv = nng_opts_parse(argc, argv, opts, &val, &arg, &optidx)) == + while ((rv = nng_args_parse(argc, argv, opts, &val, &arg, &optidx)) == 0) { switch (val) { #if 0 -- cgit v1.2.3-70-g09d2