add isl_aff_mod_val
[platform/upstream/isl.git] / isl_arg.c
index f470478..0963aa1 100644 (file)
--- a/isl_arg.c
+++ b/isl_arg.c
@@ -1,7 +1,7 @@
 /*
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  *
- * Use of this software is governed by the GNU LGPLv2.1 license
+ * Use of this software is governed by the MIT license
  *
  * Written by Sven Verdoolaege, K.U.Leuven, Departement
  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
@@ -16,7 +16,6 @@
 
 static struct isl_arg help_arg[] = {
 ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")
-ISL_ARG_END
 };
 
 static void set_default_choice(struct isl_arg *arg, void *opt)
@@ -43,12 +42,12 @@ static void set_default_child(struct isl_arg *arg, void *opt)
        if (arg->offset == (size_t) -1)
                child = opt;
        else {
-               child = calloc(1, arg->u.child.size);
+               child = calloc(1, arg->u.child.child->options_size);
                *(void **)(((char *)opt) + arg->offset) = child;
        }
 
        if (child)
-               isl_arg_set_defaults(arg->u.child.child, child);
+               isl_args_set_defaults(arg->u.child.child, child);
 }
 
 static void set_default_user(struct isl_arg *arg, void *opt)
@@ -79,39 +78,48 @@ static void set_default_str(struct isl_arg *arg, void *opt)
        *(const char **)(((char *)opt) + arg->offset) = str;
 }
 
-void isl_arg_set_defaults(struct isl_arg *arg, void *opt)
+static void set_default_str_list(struct isl_arg *arg, void *opt)
+{
+       *(const char ***)(((char *) opt) + arg->offset) = NULL;
+       *(int *)(((char *) opt) + arg->u.str_list.offset_n) = 0;
+}
+
+void isl_args_set_defaults(struct isl_args *args, void *opt)
 {
        int i;
 
-       for (i = 0; arg[i].type != isl_arg_end; ++i) {
-               switch (arg[i].type) {
+       for (i = 0; args->args[i].type != isl_arg_end; ++i) {
+               switch (args->args[i].type) {
                case isl_arg_choice:
-                       set_default_choice(&arg[i], opt);
+                       set_default_choice(&args->args[i], opt);
                        break;
                case isl_arg_flags:
-                       set_default_flags(&arg[i], opt);
+                       set_default_flags(&args->args[i], opt);
                        break;
                case isl_arg_bool:
-                       set_default_bool(&arg[i], opt);
+                       set_default_bool(&args->args[i], opt);
                        break;
                case isl_arg_child:
-                       set_default_child(&arg[i], opt);
+                       set_default_child(&args->args[i], opt);
                        break;
                case isl_arg_user:
-                       set_default_user(&arg[i], opt);
+                       set_default_user(&args->args[i], opt);
                        break;
                case isl_arg_int:
-                       set_default_int(&arg[i], opt);
+                       set_default_int(&args->args[i], opt);
                        break;
                case isl_arg_long:
-                       set_default_long(&arg[i], opt);
+                       set_default_long(&args->args[i], opt);
                        break;
                case isl_arg_ulong:
-                       set_default_ulong(&arg[i], opt);
+                       set_default_ulong(&args->args[i], opt);
                        break;
                case isl_arg_arg:
                case isl_arg_str:
-                       set_default_str(&arg[i], opt);
+                       set_default_str(&args->args[i], opt);
+                       break;
+               case isl_arg_str_list:
+                       set_default_str_list(&args->args[i], opt);
                        break;
                case isl_arg_alias:
                case isl_arg_footer:
@@ -122,6 +130,34 @@ void isl_arg_set_defaults(struct isl_arg *arg, void *opt)
        }
 }
 
+static void free_args(struct isl_arg *arg, void *opt);
+
+static void free_child(struct isl_arg *arg, void *opt)
+{
+       if (arg->offset == (size_t) -1)
+               free_args(arg->u.child.child->args, opt);
+       else
+               isl_args_free(arg->u.child.child,
+                           *(void **)(((char *)opt) + arg->offset));
+}
+
+static void free_str_list(struct isl_arg *arg, void *opt)
+{
+       int i;
+       int n = *(int *)(((char *) opt) + arg->u.str_list.offset_n);
+       char **list = *(char ***)(((char *) opt) + arg->offset);
+
+       for (i = 0; i < n; ++i)
+               free(list[i]);
+       free(list);
+}
+
+static void free_user(struct isl_arg *arg, void *opt)
+{
+       if (arg->u.user.clear)
+               arg->u.user.clear(((char *)opt) + arg->offset);
+}
+
 static void free_args(struct isl_arg *arg, void *opt)
 {
        int i;
@@ -129,19 +165,17 @@ static void free_args(struct isl_arg *arg, void *opt)
        for (i = 0; arg[i].type != isl_arg_end; ++i) {
                switch (arg[i].type) {
                case isl_arg_child:
-                       if (arg[i].offset == (size_t) -1)
-                               free_args(arg[i].u.child.child, opt);
-                       else
-                               isl_arg_free(arg[i].u.child.child,
-                                   *(void **)(((char *)opt) + arg[i].offset));
+                       free_child(&arg[i], opt);
                        break;
                case isl_arg_arg:
                case isl_arg_str:
                        free(*(char **)(((char *)opt) + arg[i].offset));
                        break;
+               case isl_arg_str_list:
+                       free_str_list(&arg[i], opt);
+                       break;
                case isl_arg_user:
-                       if (arg[i].u.user.clear)
-                               arg[i].u.user.clear(((char *)opt) + arg[i].offset);
+                       free_user(&arg[i], opt);
                        break;
                case isl_arg_alias:
                case isl_arg_bool:
@@ -158,12 +192,12 @@ static void free_args(struct isl_arg *arg, void *opt)
        }
 }
 
-void isl_arg_free(struct isl_arg *arg, void *opt)
+void isl_args_free(struct isl_args *args, void *opt)
 {
        if (!opt)
                return;
 
-       free_args(arg, opt);
+       free_args(args->args, opt);
 
        free(opt);
 }
@@ -283,13 +317,15 @@ static void print_default(struct isl_arg *decl, const char *def, int pos)
        printf("%s%s%s", default_prefix, def, default_suffix);
 }
 
-static void print_default_choice(struct isl_arg *decl, int pos)
+static void print_default_choice(struct isl_arg *decl, void *opt, int pos)
 {
        int i;
        const char *s = "none";
+       unsigned *p;
 
+       p = (unsigned *)(((char *) opt) + decl->offset);
        for (i = 0; decl->u.choice.choice[i].name; ++i)
-               if (decl->u.choice.choice[i].value == decl->u.choice.default_value) {
+               if (decl->u.choice.choice[i].value == *p) {
                        s = decl->u.choice.choice[i].name;
                        break;
                }
@@ -297,7 +333,8 @@ static void print_default_choice(struct isl_arg *decl, int pos)
        print_default(decl, s, pos);
 }
 
-static void print_choice_help(struct isl_arg *decl, const char *prefix)
+static void print_choice_help(struct isl_arg *decl, const char *prefix,
+       void *opt)
 {
        int i;
        int pos;
@@ -316,20 +353,22 @@ static void print_choice_help(struct isl_arg *decl, const char *prefix)
        }
 
        pos = print_help_msg(decl, pos);
-       print_default_choice(decl, pos);
+       print_default_choice(decl, opt, pos);
 
        printf("\n");
 }
 
-static void print_default_flags(struct isl_arg *decl, int pos)
+static void print_default_flags(struct isl_arg *decl, void *opt, int pos)
 {
        int i, first;
        const char *default_prefix = "[default: ";
        const char *default_suffix = "]";
        int len = strlen(default_prefix) + strlen(default_suffix);
+       unsigned *p;
 
+       p = (unsigned *)(((char *) opt) + decl->offset);
        for (i = 0; decl->u.flags.flags[i].name; ++i)
-               if ((decl->u.flags.default_value & decl->u.flags.flags[i].mask) ==
+               if ((*p & decl->u.flags.flags[i].mask) ==
                     decl->u.flags.flags[i].value)
                        len += strlen(decl->u.flags.flags[i].name);
 
@@ -348,7 +387,7 @@ static void print_default_flags(struct isl_arg *decl, int pos)
        printf("%s", default_prefix);
 
        for (first = 1, i = 0; decl->u.flags.flags[i].name; ++i)
-               if ((decl->u.flags.default_value & decl->u.flags.flags[i].mask) ==
+               if ((*p & decl->u.flags.flags[i].mask) ==
                     decl->u.flags.flags[i].value) {
                        if (!first)
                                printf(",");
@@ -359,7 +398,8 @@ static void print_default_flags(struct isl_arg *decl, int pos)
        printf("%s", default_suffix);
 }
 
-static void print_flags_help(struct isl_arg *decl, const char *prefix)
+static void print_flags_help(struct isl_arg *decl, const char *prefix,
+       void *opt)
 {
        int i, j;
        int pos;
@@ -387,15 +427,16 @@ static void print_flags_help(struct isl_arg *decl, const char *prefix)
        }
 
        pos = print_help_msg(decl, pos);
-       print_default_flags(decl, pos);
+       print_default_flags(decl, opt, pos);
 
        printf("\n");
 }
 
-static void print_bool_help(struct isl_arg *decl, const char *prefix)
+static void print_bool_help(struct isl_arg *decl, const char *prefix, void *opt)
 {
        int pos;
-       int no = decl->u.b.default_value == 1;
+       unsigned *p = opt ? (unsigned *)(((char *) opt) + decl->offset) : NULL;
+       int no = p ? *p == 1 : 0;
        pos = print_arg_help(decl, prefix, no);
        pos = print_help_msg(decl, pos);
        if (decl->offset != (size_t) -1)
@@ -409,29 +450,31 @@ static int print_argument_name(struct isl_arg *decl, const char *name, int pos)
        return pos + 3 + strlen(name);
 }
 
-static void print_int_help(struct isl_arg *decl, const char *prefix)
+static void print_int_help(struct isl_arg *decl, const char *prefix, void *opt)
 {
        int pos;
        char val[20];
+       int *p = (int *)(((char *) opt) + decl->offset);
        pos = print_arg_help(decl, prefix, 0);
        pos = print_argument_name(decl, decl->argument_name, pos);
        pos = print_help_msg(decl, pos);
-       snprintf(val, sizeof(val), "%d", decl->u.i.default_value);
+       snprintf(val, sizeof(val), "%d", *p);
        print_default(decl, val, pos);
        printf("\n");
 }
 
-static void print_long_help(struct isl_arg *decl, const char *prefix)
+static void print_long_help(struct isl_arg *decl, const char *prefix, void *opt)
 {
        int pos;
+       long *p = (long *)(((char *) opt) + decl->offset);
        pos = print_arg_help(decl, prefix, 0);
-       if (decl->u.l.default_value != decl->u.l.default_selected) {
+       if (*p != decl->u.l.default_selected) {
                printf("[");
                pos++;
        }
        printf("=long");
        pos += 5;
-       if (decl->u.l.default_value != decl->u.l.default_selected) {
+       if (*p != decl->u.l.default_selected) {
                printf("]");
                pos++;
        }
@@ -449,19 +492,30 @@ static void print_ulong_help(struct isl_arg *decl, const char *prefix)
        printf("\n");
 }
 
-static void print_str_help(struct isl_arg *decl, const char *prefix)
+static void print_str_help(struct isl_arg *decl, const char *prefix, void *opt)
+{
+       int pos;
+       const char *a = decl->argument_name ? decl->argument_name : "string";
+       const char **p = (const char **)(((char *) opt) + decl->offset);
+       pos = print_arg_help(decl, prefix, 0);
+       pos = print_argument_name(decl, a, pos);
+       pos = print_help_msg(decl, pos);
+       if (*p)
+               print_default(decl, *p, pos);
+       printf("\n");
+}
+
+static void print_str_list_help(struct isl_arg *decl, const char *prefix)
 {
        int pos;
        const char *a = decl->argument_name ? decl->argument_name : "string";
        pos = print_arg_help(decl, prefix, 0);
        pos = print_argument_name(decl, a, pos);
        pos = print_help_msg(decl, pos);
-       if (decl->u.str.default_value)
-               print_default(decl, decl->u.str.default_value, pos);
        printf("\n");
 }
 
-static void print_help(struct isl_arg *arg, const char *prefix)
+static void print_help(struct isl_arg *arg, const char *prefix, void *opt)
 {
        int i;
        int any = 0;
@@ -471,23 +525,23 @@ static void print_help(struct isl_arg *arg, const char *prefix)
                        continue;
                switch (arg[i].type) {
                case isl_arg_flags:
-                       print_flags_help(&arg[i], prefix);
+                       print_flags_help(&arg[i], prefix, opt);
                        any = 1;
                        break;
                case isl_arg_choice:
-                       print_choice_help(&arg[i], prefix);
+                       print_choice_help(&arg[i], prefix, opt);
                        any = 1;
                        break;
                case isl_arg_bool:
-                       print_bool_help(&arg[i], prefix);
+                       print_bool_help(&arg[i], prefix, opt);
                        any = 1;
                        break;
                case isl_arg_int:
-                       print_int_help(&arg[i], prefix);
+                       print_int_help(&arg[i], prefix, opt);
                        any = 1;
                        break;
                case isl_arg_long:
-                       print_long_help(&arg[i], prefix);
+                       print_long_help(&arg[i], prefix, opt);
                        any = 1;
                        break;
                case isl_arg_ulong:
@@ -495,7 +549,11 @@ static void print_help(struct isl_arg *arg, const char *prefix)
                        any = 1;
                        break;
                case isl_arg_str:
-                       print_str_help(&arg[i], prefix);
+                       print_str_help(&arg[i], prefix, opt);
+                       any = 1;
+                       break;
+               case isl_arg_str_list:
+                       print_str_list_help(&arg[i], prefix);
                        any = 1;
                        break;
                case isl_arg_alias:
@@ -510,6 +568,8 @@ static void print_help(struct isl_arg *arg, const char *prefix)
        }
 
        for (i = 0; arg[i].type != isl_arg_end; ++i) {
+               void *child;
+
                if (arg[i].type != isl_arg_child)
                        continue;
                if (arg[i].flags & ISL_ARG_HIDDEN)
@@ -519,7 +579,11 @@ static void print_help(struct isl_arg *arg, const char *prefix)
                        printf("\n");
                if (arg[i].help_msg)
                        printf(" %s\n", arg[i].help_msg);
-               print_help(arg[i].u.child.child, arg[i].long_name);
+               if (arg[i].offset == (size_t) -1)
+                       child = opt;
+               else
+                       child = *(void **)(((char *) opt) + arg[i].offset);
+               print_help(arg[i].u.child.child->args, arg[i].long_name, child);
                any = 1;
        }
 }
@@ -546,7 +610,7 @@ static int any_version(struct isl_arg *decl)
                case isl_arg_version:
                        return 1;
                case isl_arg_child:
-                       if (any_version(decl[i].u.child.child))
+                       if (any_version(decl[i].u.child.child->args))
                                return 1;
                        break;
                default:
@@ -557,7 +621,8 @@ static int any_version(struct isl_arg *decl)
        return 0;
 }
 
-static void print_help_and_exit(struct isl_arg *arg, const char *prog)
+static void print_help_and_exit(struct isl_arg *arg, const char *prog,
+       void *opt)
 {
        int i;
 
@@ -569,11 +634,11 @@ static void print_help_and_exit(struct isl_arg *arg, const char *prog)
 
        printf("\n\n");
 
-       print_help(arg, NULL);
+       print_help(arg, NULL, opt);
        printf("\n");
        if (any_version(arg))
                printf("  -V, --version\n");
-       print_bool_help(help_arg, NULL);
+       print_bool_help(help_arg, NULL, NULL);
 
        for (i = 0; arg[i].type != isl_arg_end; ++i) {
                if (arg[i].type != isl_arg_footer)
@@ -661,10 +726,9 @@ static int parse_choice_option(struct isl_arg *decl, char **arg,
 
        if (!has_argument && (!arg[1] || arg[1][0] == '-')) {
                unsigned u = decl->u.choice.default_selected;
+               *(unsigned *)(((char *)opt) + decl->offset) = u;
                if (decl->u.choice.set)
                        decl->u.choice.set(opt, u);
-               else
-                       *(unsigned *)(((char *)opt) + decl->offset) = u;
 
                return 1;
        }
@@ -679,10 +743,9 @@ static int parse_choice_option(struct isl_arg *decl, char **arg,
                        continue;
 
                u = decl->u.choice.choice[i].value;
+               *(unsigned *)(((char *)opt) + decl->offset) = u;
                if (decl->u.choice.set)
                        decl->u.choice.set(opt, u);
-               else
-                       *(unsigned *)(((char *)opt) + decl->offset) = u;
 
                return has_argument ? 1 : 2;
        }
@@ -726,7 +789,7 @@ static int parse_flags_option(struct isl_arg *decl, char **arg,
        if (!has_argument)
                flags = arg[1];
 
-       val = *(unsigned *)(((char *)opt) + decl->offset);
+       val = 0;
 
        while ((comma = strchr(flags, ',')) != NULL) {
                if (!set_flag(decl, &val, flags, comma - flags))
@@ -752,17 +815,17 @@ static int parse_bool_option(struct isl_arg *decl, char **arg,
                        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);
-                               else if (decl->offset != (size_t) -1)
-                                       *p = val;
                                return 2;
                        }
                }
+               if (decl->offset != (size_t) -1)
+                       *p = 1;
                if (decl->u.b.set)
                        decl->u.b.set(opt, 1);
-               else if (decl->offset != (size_t) -1)
-                       *p = 1;
 
                return 1;
        }
@@ -795,10 +858,10 @@ static int parse_bool_option(struct isl_arg *decl, char **arg,
        }
 
        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);
-               else if (decl->offset != (size_t) -1)
-                       *p = 0;
 
                return 1;
        }
@@ -832,6 +895,44 @@ static int parse_str_option(struct isl_arg *decl, char **arg,
        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)
 {
@@ -874,29 +975,26 @@ static int parse_long_option(struct isl_arg *decl, char **arg,
 
        if (has_argument) {
                long l = strtol(val, NULL, 0);
+               *p = l;
                if (decl->u.l.set)
                        decl->u.l.set(opt, l);
-               else
-                       *p = 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);
-                       else
-                               *p = 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);
-               else
-                       *p = decl->u.l.default_selected;
                return 1;
        }
 
@@ -945,7 +1043,7 @@ static int parse_child_option(struct isl_arg *decl, char **arg,
                child = *(void **)(((char *)opt) + decl->offset);
                prefix = decl->long_name;
        }
-       return parse_option(decl->u.child.child, arg, prefix, child);
+       return parse_option(decl->u.child.child->args, arg, prefix, child);
 }
 
 static int parse_option(struct isl_arg *decl, char **arg,
@@ -977,6 +1075,10 @@ static int parse_option(struct isl_arg *decl, char **arg,
                case isl_arg_str:
                        parsed = parse_str_option(&decl[i], arg, prefix, opt);
                        break;
+               case isl_arg_str_list:
+                       parsed = parse_str_list_option(&decl[i], arg, prefix,
+                                                       opt);
+                       break;
                case isl_arg_child:
                        parsed = parse_child_option(&decl[i], arg, prefix, opt);
                        break;
@@ -1005,7 +1107,7 @@ static void print_version(struct isl_arg *decl)
                        decl[i].u.version.print_version();
                        break;
                case isl_arg_child:
-                       print_version(decl[i].u.child.child);
+                       print_version(decl[i].u.child.child->args);
                        break;
                default:
                        break;
@@ -1022,7 +1124,7 @@ static void print_version_and_exit(struct isl_arg *decl)
 
 static int drop_argument(int argc, char **argv, int drop, int n)
 {
-       for (; drop < argc; ++drop)
+       for (; drop + n < argc; ++drop)
                argv[drop] = argv[drop + n];
 
        return argc - n;
@@ -1049,7 +1151,20 @@ static int next_arg(struct isl_arg *arg, int a)
        return -1;
 }
 
-int isl_arg_parse(struct isl_arg *arg, int argc, char **argv, void *opt,
+/* Unless ISL_ARG_SKIP_HELP is set, check if "arg" is
+ * equal to "--help" and if so call print_help_and_exit.
+ */
+static void check_help(struct isl_args *args, char *arg, char *prog, void *opt,
+       unsigned flags)
+{
+       if (ISL_FL_ISSET(flags, ISL_ARG_SKIP_HELP))
+               return;
+
+       if (strcmp(arg, "--help") == 0)
+               print_help_and_exit(args->args, prog, opt);
+}
+
+int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
        unsigned flags)
 {
        int a = -1;
@@ -1057,26 +1172,21 @@ int isl_arg_parse(struct isl_arg *arg, int argc, char **argv, void *opt,
        int i;
        int n;
 
-       n = n_arg(arg);
-
-       for (i = 1; i < argc; ++i) {
-               if (strcmp(argv[i], "--help") == 0)
-                       print_help_and_exit(arg, argv[0]);
-       }
+       n = n_arg(args->args);
 
        for (i = 1; i < argc; ++i) {
                if ((strcmp(argv[i], "--version") == 0 ||
-                    strcmp(argv[i], "-V") == 0) && any_version(arg))
-                       print_version_and_exit(arg);
+                    strcmp(argv[i], "-V") == 0) && any_version(args->args))
+                       print_version_and_exit(args->args);
        }
 
        while (argc > 1 + skip) {
                int parsed;
                if (argv[1 + skip][0] != '-') {
-                       a = next_arg(arg, a);
+                       a = next_arg(args->args, a);
                        if (a >= 0) {
                                char **p;
-                               p = (char **)(((char *)opt)+arg[a].offset);
+                               p = (char **)(((char *)opt)+args->args[a].offset);
                                free(*p);
                                *p = strdup(argv[1 + skip]);
                                argc = drop_argument(argc, argv, 1 + skip, 1);
@@ -1089,7 +1199,8 @@ int isl_arg_parse(struct isl_arg *arg, int argc, char **argv, void *opt,
                                ++skip;
                        continue;
                }
-               parsed = parse_option(arg, &argv[1 + skip], NULL, opt);
+               check_help(args, argv[1 + skip], argv[0], opt, flags);
+               parsed = parse_option(args->args, &argv[1 + skip], NULL, opt);
                if (parsed)
                        argc = drop_argument(argc, argv, 1 + skip, parsed);
                else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {