This looks good to me, especially with all the automatic tests added.

Quentin Glidic wrote:

-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);

Since you already checked for a zero-length string, you can detect non-numbers with:

                const char* p;
                ... option->data = strtol(value, 0, &p);
                if (*p) return ERROR;

-               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;

Good idea, leave this possibility open without deciding on it now.

+                                       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;
_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to