From: Quentin Glidic <[email protected]> Long options with argument support two formats: equal ("--long=arg") and space ("--long arg") Short options now support three formats: short ("-sarg"), equal ("-s=arg") and space ("-s value")
Provide a test program Signed-off-by: Quentin Glidic <[email protected]> --- man/weston.man | 4 + shared/option-parser.c | 111 ++++++++++++--- tests/.gitignore | 1 + tests/Makefile.am | 11 +- tests/option-parser-test.c | 342 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 450 insertions(+), 19 deletions(-) create mode 100644 tests/option-parser-test.c diff --git a/man/weston.man b/man/weston.man index 39d854b..79d4588 100644 --- a/man/weston.man +++ b/man/weston.man @@ -92,6 +92,10 @@ and .\" *************************************************************** .SH OPTIONS . +Long options with an argument support two format: equal ("--long=arg") and +space ("--long arg"). Short options with argument support three format: short +("-sarg"), equal ("-s=arg") and space ("-s arg"). +. .SS Weston core options: .TP \fB\-\^B\fR\fIbackend.so\fR, \fB\-\-backend\fR=\fIbackend.so\fR diff --git a/shared/option-parser.c b/shared/option-parser.c index a7e497f..0c5d1af 100644 --- a/shared/option-parser.c +++ b/shared/option-parser.c @@ -28,22 +28,34 @@ #include "config-parser.h" -static void -handle_option(const struct weston_option *option, char *value) +enum state { + OK, + EATEN, + ERROR +}; + +static enum state +handle_option(const struct weston_option *option, const char *value) { switch (option->type) { case WESTON_OPTION_INTEGER: + if (value == NULL || value[0] == '\0') + return ERROR; * (int32_t *) option->data = strtol(value, NULL, 0); - return; + return EATEN; case WESTON_OPTION_UNSIGNED_INTEGER: + if (value == NULL || value[0] == '\0') + return ERROR; * (uint32_t *) option->data = strtoul(value, NULL, 0); - return; + return EATEN; case WESTON_OPTION_STRING: + if (value == NULL) + return ERROR; * (char **) option->data = strdup(value); - return; + return EATEN; case WESTON_OPTION_BOOLEAN: * (int32_t *) option->data = 1; - return; + return OK; default: assert(0); } @@ -54,26 +66,89 @@ parse_options(const struct weston_option *options, int count, int *argc, char *argv[]) { int i, j, k, len = 0; + const char *arg, *value; for (i = 1, j = 1; i < *argc; i++) { - for (k = 0; k < count; k++) { - if (options[k].name) + arg = argv[i]; + value = argv[i+1]; + + if (arg[0] != '-') + { + /* Not an option, just skip it */ + argv[j++] = argv[i]; + continue; + } + ++arg; /* Skip the first dash */ + + /* We have an option, check for which one */ + if (arg[0] == '-') { + /* Long option */ + ++arg; /* Skip the second dash */ + for (k = 0; k < count; k++) { + if (!options[k].name) + /* No long variant for this option */ + continue; + len = strlen(options[k].name); - if (options[k].name && - argv[i][0] == '-' && - argv[i][1] == '-' && - strncmp(options[k].name, &argv[i][2], len) == 0 && - (argv[i][len + 2] == '=' || argv[i][len + 2] == '\0')) { - handle_option(&options[k], &argv[i][len + 3]); + if (strncmp(options[k].name, arg, len) != 0) + /* Not matching */ + continue; + + switch (arg[len]) { + case '=': value = arg + (len+1); + case '\0': break; + default: continue; /* Not fully matching */ + } + + switch (handle_option(&options[k], value)) { + case OK: break; + case EATEN: + if (arg[len] == '\0') + ++i; + break; + case ERROR: return -1; + } + break; - } else if (options[k].short_name && - argv[i][0] == '-' && - options[k].short_name == argv[i][1]) { - handle_option(&options[k], &argv[i][2]); + } + } else { + /* Short option */ + for (k = 0; k < count; k++) { + if (!options[k].short_name) + /* no short variant for this option */ + continue; + + if (options[k].short_name != arg[0]) + /* Not matching */ + continue; + + if (arg[1] != '\0') + value = arg+1; + + switch (arg[1]) { + case '\0': break; + case '=': value = arg + 2; break; + default: value = arg + 1; + } + //fprintf(stderr, "arg = %s, value = '%s'\n", arg, value); + + switch (handle_option(&options[k], value)) { + case OK: + if (arg[1] != '\0') + /* Do not support merged short options */ + return -1; + break; + case EATEN: + if (arg[1] == '\0') + ++i; + break; + case ERROR: return -1; + } break; } } if (k == count) + /* None matched */ argv[j++] = argv[i]; } argv[j] = NULL; diff --git a/tests/.gitignore b/tests/.gitignore index a48ed40..ab85338 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,3 +1,4 @@ +*.test *.weston logs matrix-test diff --git a/tests/Makefile.am b/tests/Makefile.am index 03492d7..2a48c12 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,7 @@ -TESTS = $(module_tests) $(weston_tests) +TESTS = $(shared_tests) $(module_tests) $(weston_tests) + +shared_tests = \ + option-parser.test module_tests = \ surface-test.la \ @@ -35,6 +38,7 @@ check_LTLIBRARIES = \ $(module_tests) check_PROGRAMS = \ + $(shared_tests) \ $(weston_tests) AM_CFLAGS = $(GCC_CFLAGS) @@ -46,6 +50,11 @@ AM_CPPFLAGS = \ $(COMPOSITOR_CFLAGS) AM_LDFLAGS = -module -avoid-version -rpath $(libdir) +option_parser_test_SOURCES = \ + option-parser-test.c \ + $(weston_test_runner_src) +option_parser_test_LDADD = ../shared/libshared.la + surface_global_test_la_SOURCES = surface-global-test.c surface_test_la_SOURCES = surface-test.c diff --git a/tests/option-parser-test.c b/tests/option-parser-test.c new file mode 100644 index 0000000..0329122 --- /dev/null +++ b/tests/option-parser-test.c @@ -0,0 +1,342 @@ +/* + * Copyright ?? 2013 Quentin "Sardem FF7" Glidic + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> +#include "weston-test-runner.h" +#include "config-parser.h" + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +static char *str = NULL; +static int32_t i = 0; +static uint32_t u = 0; +static uint8_t b = 0; + +const struct weston_option test_options[] = { + { WESTON_OPTION_STRING, "string", 's', &str }, + { WESTON_OPTION_INTEGER, "int", 'i', &i }, + { WESTON_OPTION_UNSIGNED_INTEGER, "uint", 'u', &u }, + { WESTON_OPTION_BOOLEAN, "bool", 'b', &b }, +}; + +static void reset(void) { + str = NULL; + i = -1; + u = 0; + b = 0; +} + +TEST(option_parser_test_empty) +{ + reset(); + char *argv[] = { + "test", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 1); + assert(argc == r); +} + +TEST(option_parser_test_extra) +{ + reset(); + char *argv[] = { + "test", + "extra", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 2); + assert(argc == r); +} + +TEST(option_parser_test_long_equal) +{ + reset(); + char *argv[] = { + "test", + "--string=s", + "--int=-10", + "--uint=10", + "--bool", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 1); + assert(argc == r); + assert(strcmp(str, "s") == 0); + assert(i == -10); + assert(u == 10); + assert(b); +} + +TEST(option_parser_test_long_equal_extra) +{ + reset(); + char *argv[] = { + "test", + "--string=s", + "--int=-10", + "--uint=10", + "--bool", + "extra", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 2); + assert(argc == r); + assert(strcmp(str, "s") == 0); + assert(i == -10); + assert(u == 10); + assert(b); +} + +TEST(option_parser_test_long_space) +{ + reset(); + char *argv[] = { + "test", + "--string", "s", + "--int", "-10", + "--uint", "10", + "--bool", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 1); + assert(argc == r); + assert(strcmp(str, "s") == 0); + assert(i == -10); + assert(u == 10); + assert(b); +} + +TEST(option_parser_test_long_space_extra) +{ + reset(); + char *argv[] = { + "test", + "--string", "s", + "--int", "-10", + "--uint", "10", + "--bool", + "extra", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 2); + assert(argc == r); + assert(strcmp(str, "s") == 0); + assert(i == -10); + assert(u == 10); + assert(b); +} + +TEST(option_parser_test_short) +{ + reset(); + char *argv[] = { + "test", + "-ss", + "-i-10", + "-u10", + "-b", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 1); + assert(argc == r); + assert(strcmp(str, "s") == 0); + assert(i == -10); + assert(u == 10); + assert(b); +} + +TEST(option_parser_test_short_equal) +{ + reset(); + char *argv[] = { + "test", + "-s=s", + "-i=-10", + "-u=10", + "-b", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 1); + assert(argc == r); + assert(strcmp(str, "s") == 0); + assert(i == -10); + assert(u == 10); + assert(b); +} + +TEST(option_parser_test_short_space) +{ + reset(); + char *argv[] = { + "test", + "-s", "s", + "-i", "-10", + "-u", "10", + "-b", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 1); + assert(argc == r); + assert(strcmp(str, "s") == 0); + assert(i == -10); + assert(u == 10); + assert(b); +} + +TEST(option_parser_test_long_equal_missing_right) +{ + reset(); + char *argv[] = { + "test", + "--string=", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 1); + assert(argc == r); + assert(strcmp(str, "") == 0); + assert(i == -1); + assert(u == 0); + assert(!b); +} + +TEST(option_parser_test_long_equal_missing_wrong) +{ + reset(); + char *argv[] = { + "test", + "--int=", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == -1); +} + +TEST(option_parser_test_long_space_missing) +{ + reset(); + char *argv[] = { + "test", + "--string", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == -1); +} + +TEST(option_parser_test_short_space_missing) +{ + reset(); + char *argv[] = { + "test", + "-s", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == -1); +} + +TEST(option_parser_test_short_equal_missing_right) +{ + reset(); + char *argv[] = { + "test", + "-s=", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == 1); + assert(argc == r); + assert(strcmp(str, "") == 0); + assert(i == -1); + assert(u == 0); + assert(!b); +} + +TEST(option_parser_test_short_equal_missing_wrong) +{ + reset(); + char *argv[] = { + "test", + "-i=", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == -1); +} + +TEST(option_parser_test_short_concat) +{ + reset(); + char *argv[] = { + "test", + "-bcd", + NULL + }; + int argc = ARRAY_LENGTH(argv) - 1; + + int r = parse_options(test_options, ARRAY_LENGTH(test_options), &argc, argv); + assert(r == -1); +} -- 1.8.2.1
_______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
