Re: [ovs-dev] [PATCH v2 2/3] ovn-nbctl: Separate command-line options parsing and interpretation.
On Mon, Aug 06, 2018 at 04:39:13PM -0400, Mark Michelson wrote: > On 08/03/2018 01:54 PM, Ben Pfaff wrote: > >This will allow selected options to be interpreted locally and others to > >be passed to the daemon, when the daemon is in use. > > > >Signed-off-by: Ben Pfaff > >+default: > >+if (allocated_po >= n_po) { > > This if is backwards. It should be: > > if (n_po >= allocated_po) { Good catch. Thanks, I fixed this. ___ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Re: [ovs-dev] [PATCH v2 2/3] ovn-nbctl: Separate command-line options parsing and interpretation.
On 08/03/2018 01:54 PM, Ben Pfaff wrote: This will allow selected options to be interpreted locally and others to be passed to the daemon, when the daemon is in use. Signed-off-by: Ben Pfaff --- lib/command-line.c| 108 ++ lib/command-line.h| 10 + ovn/utilities/ovn-nbctl.c | 39 + 3 files changed, 138 insertions(+), 19 deletions(-) diff --git a/lib/command-line.c b/lib/command-line.c index 81283314d1f3..235e59b25716 100644 --- a/lib/command-line.c +++ b/lib/command-line.c @@ -52,6 +52,114 @@ ovs_cmdl_long_options_to_short_options(const struct option options[]) return xstrdup(short_options); } +static char * OVS_WARN_UNUSED_RESULT +build_short_options(const struct option *long_options) +{ +char *tmp, *short_options; + +tmp = ovs_cmdl_long_options_to_short_options(long_options); +short_options = xasprintf("+:%s", tmp); +free(tmp); + +return short_options; +} + +static const struct option * +find_option_by_value(const struct option *options, int value) +{ +const struct option *o; + +for (o = options; o->name; o++) { +if (o->val == value) { +return o; +} +} +return NULL; +} + +/* Parses the command-line options in 'argc' and 'argv'. The caller specifies + * the supported options in 'options'. On success, stores the parsed options + * in '*pop', the number of options in '*n_pop', and returns NULL. On failure, + * returns an error message and zeros the output arguments. */ +char * OVS_WARN_UNUSED_RESULT +ovs_cmdl_parse_all(int argc, char *argv[], + const struct option *options, + struct ovs_cmdl_parsed_option **pop, size_t *n_pop) +{ +/* Count number of options so we can have better assertions later. */ +size_t n_options OVS_UNUSED = 0; +while (options[n_options].name) { +n_options++; +} + +char *short_options = build_short_options(options); + +struct ovs_cmdl_parsed_option *po = NULL; +size_t allocated_po = 0; +size_t n_po = 0; + +char *error; + +optind = 0; +opterr = 0; +for (;;) { +int idx = -1; +int c = getopt_long(argc, argv, short_options, options, ); +switch (c) { +case -1: +*pop = po; +*n_pop = n_po; +free(short_options); +return NULL; + +case 0: +/* getopt_long() processed the option directly by setting a flag + * variable. This is probably undesirable for use with this + * function. */ +OVS_NOT_REACHED(); + +case '?': +if (optopt && find_option_by_value(options, optopt)) { +error = xasprintf("option '%s' doesn't allow an argument", + argv[optind - 1]); +} else if (optopt) { +error = xasprintf("unrecognized option '%c'", optopt); +} else { +error = xasprintf("unrecognized option '%s'", + argv[optind - 1]); +} +goto error; + +case ':': +error = xasprintf("option '%s' requires an argument", + argv[optind - 1]); +goto error; + +default: +if (allocated_po >= n_po) { This if is backwards. It should be: if (n_po >= allocated_po) { +po = x2nrealloc(po, _po, sizeof *po); +} +if (idx == -1) { +po[n_po].o = find_option_by_value(options, c); +} else { +ovs_assert(idx >= 0 && idx < n_options); +po[n_po].o = [idx]; +} +po[n_po].arg = optarg; +n_po++; +break; +} +} +OVS_NOT_REACHED(); + +error: +free(po); +*pop = NULL; +*n_pop = 0; +free(short_options); +return error; +} + /* Given the 'struct ovs_cmdl_command' array, prints the usage of all commands. */ void ovs_cmdl_print_commands(const struct ovs_cmdl_command commands[]) diff --git a/lib/command-line.h b/lib/command-line.h index 00ace949bad6..9d62dc2501c5 100644 --- a/lib/command-line.h +++ b/lib/command-line.h @@ -45,8 +45,18 @@ struct ovs_cmdl_command { }; char *ovs_cmdl_long_options_to_short_options(const struct option *options); + +struct ovs_cmdl_parsed_option { +const struct option *o; +char *arg; +}; +char *ovs_cmdl_parse_all(int argc, char *argv[], const struct option *, + struct ovs_cmdl_parsed_option **, size_t *) +OVS_WARN_UNUSED_RESULT; + void ovs_cmdl_print_options(const struct option *options); void ovs_cmdl_print_commands(const struct ovs_cmdl_command *commands); + void ovs_cmdl_run_command(struct ovs_cmdl_context *, const struct ovs_cmdl_command[]); void ovs_cmdl_run_command_read_only(struct ovs_cmdl_context *, diff --git
[ovs-dev] [PATCH v2 2/3] ovn-nbctl: Separate command-line options parsing and interpretation.
This will allow selected options to be interpreted locally and others to be passed to the daemon, when the daemon is in use. Signed-off-by: Ben Pfaff --- lib/command-line.c| 108 ++ lib/command-line.h| 10 + ovn/utilities/ovn-nbctl.c | 39 + 3 files changed, 138 insertions(+), 19 deletions(-) diff --git a/lib/command-line.c b/lib/command-line.c index 81283314d1f3..235e59b25716 100644 --- a/lib/command-line.c +++ b/lib/command-line.c @@ -52,6 +52,114 @@ ovs_cmdl_long_options_to_short_options(const struct option options[]) return xstrdup(short_options); } +static char * OVS_WARN_UNUSED_RESULT +build_short_options(const struct option *long_options) +{ +char *tmp, *short_options; + +tmp = ovs_cmdl_long_options_to_short_options(long_options); +short_options = xasprintf("+:%s", tmp); +free(tmp); + +return short_options; +} + +static const struct option * +find_option_by_value(const struct option *options, int value) +{ +const struct option *o; + +for (o = options; o->name; o++) { +if (o->val == value) { +return o; +} +} +return NULL; +} + +/* Parses the command-line options in 'argc' and 'argv'. The caller specifies + * the supported options in 'options'. On success, stores the parsed options + * in '*pop', the number of options in '*n_pop', and returns NULL. On failure, + * returns an error message and zeros the output arguments. */ +char * OVS_WARN_UNUSED_RESULT +ovs_cmdl_parse_all(int argc, char *argv[], + const struct option *options, + struct ovs_cmdl_parsed_option **pop, size_t *n_pop) +{ +/* Count number of options so we can have better assertions later. */ +size_t n_options OVS_UNUSED = 0; +while (options[n_options].name) { +n_options++; +} + +char *short_options = build_short_options(options); + +struct ovs_cmdl_parsed_option *po = NULL; +size_t allocated_po = 0; +size_t n_po = 0; + +char *error; + +optind = 0; +opterr = 0; +for (;;) { +int idx = -1; +int c = getopt_long(argc, argv, short_options, options, ); +switch (c) { +case -1: +*pop = po; +*n_pop = n_po; +free(short_options); +return NULL; + +case 0: +/* getopt_long() processed the option directly by setting a flag + * variable. This is probably undesirable for use with this + * function. */ +OVS_NOT_REACHED(); + +case '?': +if (optopt && find_option_by_value(options, optopt)) { +error = xasprintf("option '%s' doesn't allow an argument", + argv[optind - 1]); +} else if (optopt) { +error = xasprintf("unrecognized option '%c'", optopt); +} else { +error = xasprintf("unrecognized option '%s'", + argv[optind - 1]); +} +goto error; + +case ':': +error = xasprintf("option '%s' requires an argument", + argv[optind - 1]); +goto error; + +default: +if (allocated_po >= n_po) { +po = x2nrealloc(po, _po, sizeof *po); +} +if (idx == -1) { +po[n_po].o = find_option_by_value(options, c); +} else { +ovs_assert(idx >= 0 && idx < n_options); +po[n_po].o = [idx]; +} +po[n_po].arg = optarg; +n_po++; +break; +} +} +OVS_NOT_REACHED(); + +error: +free(po); +*pop = NULL; +*n_pop = 0; +free(short_options); +return error; +} + /* Given the 'struct ovs_cmdl_command' array, prints the usage of all commands. */ void ovs_cmdl_print_commands(const struct ovs_cmdl_command commands[]) diff --git a/lib/command-line.h b/lib/command-line.h index 00ace949bad6..9d62dc2501c5 100644 --- a/lib/command-line.h +++ b/lib/command-line.h @@ -45,8 +45,18 @@ struct ovs_cmdl_command { }; char *ovs_cmdl_long_options_to_short_options(const struct option *options); + +struct ovs_cmdl_parsed_option { +const struct option *o; +char *arg; +}; +char *ovs_cmdl_parse_all(int argc, char *argv[], const struct option *, + struct ovs_cmdl_parsed_option **, size_t *) +OVS_WARN_UNUSED_RESULT; + void ovs_cmdl_print_options(const struct option *options); void ovs_cmdl_print_commands(const struct ovs_cmdl_command *commands); + void ovs_cmdl_run_command(struct ovs_cmdl_context *, const struct ovs_cmdl_command[]); void ovs_cmdl_run_command_read_only(struct ovs_cmdl_context *, diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index c625546bb8c0..0659ced378ef 100644 --- a/ovn/utilities/ovn-nbctl.c +++