+static int parse_flags_option(struct isl_arg *decl, char **arg,
+ const char *prefix, void *opt)
+{
+ int has_argument;
+ const char *flags;
+ const char *comma;
+ unsigned val;
+
+ flags = skip_name(decl, arg[0], prefix, 0, &has_argument);
+ if (!flags)
+ return 0;
+
+ if (!has_argument && !arg[1])
+ return 0;
+
+ if (!has_argument)
+ flags = arg[1];
+
+ val = 0;
+
+ while ((comma = strchr(flags, ',')) != NULL) {
+ if (!set_flag(decl, &val, flags, comma - flags))
+ return 0;
+ flags = comma + 1;
+ }
+ if (!set_flag(decl, &val, flags, strlen(flags)))
+ return 0;
+
+ *(unsigned *)(((char *)opt) + decl->offset) = val;
+
+ return has_argument ? 1 : 2;
+}
+
+static int parse_bool_option(struct isl_arg *decl, char **arg,
+ const char *prefix, void *opt)
+{
+ const char *name;
+ unsigned *p = (unsigned *)(((char *)opt) + decl->offset);
+
+ if (skip_name(decl, arg[0], prefix, 0, NULL)) {
+ if ((decl->flags & ISL_ARG_BOOL_ARG) && arg[1]) {
+ char *endptr;
+ int val = strtol(arg[1], &endptr, 0);
+ if (*endptr == '\0' && (val == 0 || val == 1)) {
+ if (decl->offset != (size_t) -1)
+ *p = val;
+ if (decl->u.b.set)
+ decl->u.b.set(opt, val);
+ return 2;
+ }
+ }
+ if (decl->offset != (size_t) -1)
+ *p = 1;
+ if (decl->u.b.set)
+ decl->u.b.set(opt, 1);
+
+ return 1;
+ }
+
+ if (!decl->long_name)
+ return 0;
+
+ name = skip_dash_dash(decl, arg[0]);
+ if (!name)
+ return 0;
+
+ if (prefix) {
+ size_t prefix_len = strlen(prefix);
+ if (strncmp(name, prefix, prefix_len) == 0 &&
+ name[prefix_len] == '-') {
+ name += prefix_len + 1;
+ prefix = NULL;
+ }
+ }
+
+ if (strncmp(name, "no-", 3))
+ return 0;
+ name += 3;
+
+ if (prefix) {
+ size_t prefix_len = strlen(prefix);
+ if (strncmp(name, prefix, prefix_len) == 0 &&
+ name[prefix_len] == '-')
+ name += prefix_len + 1;
+ }
+
+ if (match_long_name(decl, name, name + strlen(name))) {
+ if (decl->offset != (size_t) -1)
+ *p = 0;
+ if (decl->u.b.set)
+ decl->u.b.set(opt, 0);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_str_option(struct isl_arg *decl, char **arg,
+ const char *prefix, void *opt)
+{
+ int has_argument;
+ const char *s;
+ char **p = (char **)(((char *)opt) + decl->offset);
+
+ s = skip_name(decl, arg[0], prefix, 0, &has_argument);
+ if (!s)
+ return 0;
+
+ if (has_argument) {
+ free(*p);
+ *p = strdup(s);
+ return 1;
+ }
+
+ if (arg[1]) {
+ free(*p);
+ *p = strdup(arg[1]);
+ return 2;
+ }
+
+ return 0;
+}
+
+static int isl_arg_str_list_append(struct isl_arg *decl, void *opt,
+ const char *s)
+{
+ int *n = (int *)(((char *) opt) + decl->u.str_list.offset_n);
+ char **list = *(char ***)(((char *) opt) + decl->offset);
+
+ list = realloc(list, (*n + 1) * sizeof(char *));
+ if (!list)
+ return -1;
+ *(char ***)(((char *) opt) + decl->offset) = list;
+ list[*n] = strdup(s);
+ (*n)++;
+ return 0;
+}
+
+static int parse_str_list_option(struct isl_arg *decl, char **arg,
+ const char *prefix, void *opt)
+{
+ int has_argument;
+ const char *s;
+
+ s = skip_name(decl, arg[0], prefix, 0, &has_argument);
+ if (!s)
+ return 0;
+
+ if (has_argument) {
+ isl_arg_str_list_append(decl, opt, s);
+ return 1;
+ }
+
+ if (arg[1]) {
+ isl_arg_str_list_append(decl, opt, arg[1]);
+ return 2;
+ }
+
+ return 0;
+}
+
+static int parse_int_option(struct isl_arg *decl, char **arg,
+ const char *prefix, void *opt)
+{
+ int has_argument;
+ const char *val;
+ char *endptr;
+ int *p = (int *)(((char *)opt) + decl->offset);
+
+ val = skip_name(decl, arg[0], prefix, 0, &has_argument);
+ if (!val)
+ return 0;
+
+ if (has_argument) {
+ *p = atoi(val);
+ return 1;
+ }
+
+ if (arg[1]) {
+ int i = strtol(arg[1], &endptr, 0);
+ if (*endptr == '\0') {
+ *p = i;
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+static int parse_long_option(struct isl_arg *decl, char **arg,
+ const char *prefix, void *opt)
+{
+ int has_argument;
+ const char *val;
+ char *endptr;
+ long *p = (long *)(((char *)opt) + decl->offset);
+
+ val = skip_name(decl, arg[0], prefix, 0, &has_argument);
+ if (!val)
+ return 0;
+
+ if (has_argument) {
+ long l = strtol(val, NULL, 0);
+ *p = l;
+ if (decl->u.l.set)
+ decl->u.l.set(opt, l);
+ return 1;
+ }
+
+ if (arg[1]) {
+ long l = strtol(arg[1], &endptr, 0);
+ if (*endptr == '\0') {
+ *p = l;
+ if (decl->u.l.set)
+ decl->u.l.set(opt, l);
+ return 2;
+ }
+ }
+
+ if (decl->u.l.default_value != decl->u.l.default_selected) {
+ *p = decl->u.l.default_selected;
+ if (decl->u.l.set)
+ decl->u.l.set(opt, decl->u.l.default_selected);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_ulong_option(struct isl_arg *decl, char **arg,
+ const char *prefix, void *opt)
+{
+ int has_argument;
+ const char *val;
+ char *endptr;
+ unsigned long *p = (unsigned long *)(((char *)opt) + decl->offset);
+
+ val = skip_name(decl, arg[0], prefix, 0, &has_argument);
+ if (!val)
+ return 0;
+
+ if (has_argument) {
+ *p = strtoul(val, NULL, 0);
+ return 1;
+ }
+
+ if (arg[1]) {
+ unsigned long ul = strtoul(arg[1], &endptr, 0);
+ if (*endptr == '\0') {
+ *p = ul;
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+static int parse_option(struct isl_arg *decl, char **arg,