[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