[PATCH] Fixes to parse_options
Bill Spitzak
spitzak at gmail.com
Wed Jun 25 19:21:05 PDT 2014
- Rejects malformed or missing numbers
- Boolean switches must not have an = sign, others must have =
- Single-letter non-boolean can have optional = sign: -x=foo
- Single-letter boolean switches can be merged: -xyz
- Fixed addressing string[strlen+1]
- new parse_options_or_exit() prints help information for demo programs
- weston-eventdemo had '0' for single-letter switch
- weston-eventdemo log all events if no switches are given
---
clients/eventdemo.c | 23 +++++----
clients/nested.c | 4 +-
clients/subsurfaces.c | 4 +-
clients/wscreensaver.c | 4 +-
shared/config-parser.h | 4 ++
shared/option-parser.c | 126 +++++++++++++++++++++++++++++++++++++-----------
6 files changed, 121 insertions(+), 44 deletions(-)
diff --git a/clients/eventdemo.c b/clients/eventdemo.c
index 5ec6829..cebf6a0 100644
--- a/clients/eventdemo.c
+++ b/clients/eventdemo.c
@@ -373,13 +373,13 @@ static const struct weston_option eventdemo_options[] = {
{ WESTON_OPTION_INTEGER, "max-width", 0, &width_max },
{ WESTON_OPTION_INTEGER, "max-height", 0, &height_max },
{ WESTON_OPTION_BOOLEAN, "no-border", 'b', &noborder },
- { WESTON_OPTION_BOOLEAN, "log-redraw", '0', &log_redraw },
- { WESTON_OPTION_BOOLEAN, "log-resize", '0', &log_resize },
- { WESTON_OPTION_BOOLEAN, "log-focus", '0', &log_focus },
- { WESTON_OPTION_BOOLEAN, "log-key", '0', &log_key },
- { WESTON_OPTION_BOOLEAN, "log-button", '0', &log_button },
- { WESTON_OPTION_BOOLEAN, "log-axis", '0', &log_axis },
- { WESTON_OPTION_BOOLEAN, "log-motion", '0', &log_motion },
+ { WESTON_OPTION_BOOLEAN, "log-redraw", 0, &log_redraw },
+ { WESTON_OPTION_BOOLEAN, "log-resize", 0, &log_resize },
+ { WESTON_OPTION_BOOLEAN, "log-focus", 0, &log_focus },
+ { WESTON_OPTION_BOOLEAN, "log-key", 0, &log_key },
+ { WESTON_OPTION_BOOLEAN, "log-button", 0, &log_button },
+ { WESTON_OPTION_BOOLEAN, "log-axis", 0, &log_axis },
+ { WESTON_OPTION_BOOLEAN, "log-motion", 0, &log_motion },
};
/**
@@ -392,8 +392,13 @@ main(int argc, char *argv[])
struct display *d;
struct eventdemo *e;
- parse_options(eventdemo_options,
- ARRAY_LENGTH(eventdemo_options), &argc, argv);
+ parse_options_or_exit(eventdemo_options,
+ ARRAY_LENGTH(eventdemo_options), &argc, argv);
+
+ if (!log_redraw && !log_resize && !log_focus && !log_key &&
+ !log_button && !log_axis && !log_motion)
+ log_redraw = log_resize = log_focus = log_key =
+ log_button = log_axis = log_motion = 1;
/* Connect to the display and have the arguments parsed */
d = display_create(&argc, argv);
diff --git a/clients/nested.c b/clients/nested.c
index 44389e4..0c5c7e9 100644
--- a/clients/nested.c
+++ b/clients/nested.c
@@ -1122,8 +1122,8 @@ main(int argc, char *argv[])
struct display *display;
struct nested *nested;
- parse_options(nested_options,
- ARRAY_LENGTH(nested_options), &argc, argv);
+ parse_options_or_exit(nested_options,
+ ARRAY_LENGTH(nested_options), &argc, argv);
display = display_create(&argc, argv);
if (display == NULL) {
diff --git a/clients/subsurfaces.c b/clients/subsurfaces.c
index 66a10f2..4ed0b78 100644
--- a/clients/subsurfaces.c
+++ b/clients/subsurfaces.c
@@ -775,8 +775,8 @@ main(int argc, char *argv[])
struct display *display;
struct demoapp *app;
- parse_options(options, ARRAY_LENGTH(options), &argc, argv);
- if (option_help) {
+ if (parse_options(options, ARRAY_LENGTH(options), &argc, argv)
+ || option_help) {
printf(help_text, argv[0]);
return 0;
}
diff --git a/clients/wscreensaver.c b/clients/wscreensaver.c
index 47f6c8a..1de299a 100644
--- a/clients/wscreensaver.c
+++ b/clients/wscreensaver.c
@@ -310,8 +310,8 @@ int main(int argc, char *argv[])
init_frand();
- parse_options(wscreensaver_options,
- ARRAY_LENGTH(wscreensaver_options), &argc, argv);
+ parse_options_or_exit(wscreensaver_options,
+ ARRAY_LENGTH(wscreensaver_options), &argc, argv);
d = display_create(&argc, argv);
if (d == NULL) {
diff --git a/shared/config-parser.h b/shared/config-parser.h
index 745562b..81baf76 100644
--- a/shared/config-parser.h
+++ b/shared/config-parser.h
@@ -65,6 +65,10 @@ int
parse_options(const struct weston_option *options,
int count, int *argc, char *argv[]);
+void
+parse_options_or_exit(const struct weston_option *options,
+ int count, int *argc, char *argv[]);
+
struct weston_config_section;
struct weston_config;
diff --git a/shared/option-parser.c b/shared/option-parser.c
index c00349a..0ca9e52 100644
--- a/shared/option-parser.c
+++ b/shared/option-parser.c
@@ -22,6 +22,7 @@
#include "config.h"
+#include <ctype.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
@@ -30,56 +31,123 @@
#include "config-parser.h"
-static void
+static int
handle_option(const struct weston_option *option, char *value)
{
+ char* p;
switch (option->type) {
case WESTON_OPTION_INTEGER:
- * (int32_t *) option->data = strtol(value, NULL, 0);
- return;
+ * (int32_t *) option->data = strtol(value, &p, 0);
+ return p > value && !*p;
case WESTON_OPTION_UNSIGNED_INTEGER:
- * (uint32_t *) option->data = strtoul(value, NULL, 0);
- return;
+ * (uint32_t *) option->data = strtoul(value, &p, 0);
+ return p > value && !*p;
case WESTON_OPTION_STRING:
* (char **) option->data = strdup(value);
- return;
- case WESTON_OPTION_BOOLEAN:
- * (int32_t *) option->data = 1;
- return;
+ return 1;
default:
assert(0);
}
}
+static int
+handle_long_option(const struct weston_option *options, int count, char* arg)
+{
+ int k, len;
+ for (k = 0; k < count; k++) {
+ if (! options[k].name) continue;
+ len = strlen(options[k].name);
+ if (strncmp(options[k].name, arg+2, len) != 0) continue;
+ if (options[k].type == WESTON_OPTION_BOOLEAN) {
+ if (! arg[len+2]) {
+ * (int32_t *) options[k].data = 1;
+ return 1;
+ }
+ } else if (arg[len+2] == '=') {
+ return handle_option(options+k, arg+len+3);
+ }
+ }
+ return 0;
+}
+
+static int
+handle_short_option(const struct weston_option *options, int count, char* arg)
+{
+ int i, k;
+ for (i = 1; arg[i]; i++) {
+ for (k = 0; ; k++) {
+ if (k >= count) return 0;
+ if (options[k].short_name == arg[i]) break;
+ }
+ if (options[k].type == WESTON_OPTION_BOOLEAN)
+ * (int32_t *) options[k].data = 1;
+ else if (arg[i+1] == '=')
+ return handle_option(options+k, arg+i+2);
+ else
+ return handle_option(options+k, arg+i+1);
+ }
+ return arg[1];
+}
+
+
int
parse_options(const struct weston_option *options,
int count, int *argc, char *argv[])
{
- int i, j, k, len = 0;
+ int i, j;
for (i = 1, j = 1; i < *argc; i++) {
- for (k = 0; k < count; k++) {
- if (options[k].name)
- 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]);
- break;
- } else if (options[k].short_name &&
- argv[i][0] == '-' &&
- options[k].short_name == argv[i][1]) {
- handle_option(&options[k], &argv[i][2]);
- break;
- }
+ if (argv[i][0] == '-') {
+ if (argv[i][1] == '-') {
+ if (handle_long_option(options, count, argv[i]))
+ continue;
+ } else if (handle_short_option(options, count, argv[i]))
+ continue;
}
- if (k == count)
- argv[j++] = argv[i];
+ argv[j++] = argv[i];
}
+
argv[j] = NULL;
*argc = j;
- return j;
+ return j - 1;
+}
+
+
+static void print_upper_case(const struct weston_option* option)
+{
+ const char* p;
+ if (option->name) {
+ for (p = option->name; *p; p++)
+ if (isalpha(*p)) putchar(toupper(*p));
+ } else {
+ putchar(toupper(option->short_name));
+ }
+}
+
+
+void
+parse_options_or_exit(const struct weston_option *options,
+ int count, int *argc, char *argv[])
+{
+ int k;
+ if (!parse_options(options, count, argc, argv)) return;
+ printf("Usage: %s [OPTIONS]\n\n", argv[0]);
+ for (k = 0; k < count; k++) {
+ if (options[k].name) {
+ printf(" --%s", options[k].name);
+ if (options[k].type != WESTON_OPTION_BOOLEAN) {
+ putchar('=');
+ print_upper_case(options+k);
+ }
+ putchar('\n');
+ }
+ if (options[k].short_name) {
+ printf(" -%c", options[k].short_name);
+ if (options[k].type != WESTON_OPTION_BOOLEAN)
+ print_upper_case(options+k);
+ putchar('\n');
+ }
+ }
+ exit(1);
}
--
1.7.9.5
More information about the wayland-devel
mailing list