test both context handling mechanisms of isl_pip
[platform/upstream/isl.git] / isl_arg.c
index b19778a..f4824e6 100644 (file)
--- a/isl_arg.c
+++ b/isl_arg.c
@@ -38,12 +38,17 @@ static void set_default_bool(struct isl_arg *arg, void *opt)
 
 static void set_default_child(struct isl_arg *arg, void *opt)
 {
-       void *child = calloc(1, arg->u.child.size);
+       void *child;
+
+       if (arg->offset == (size_t) -1)
+               child = opt;
+       else {
+               child = calloc(1, arg->u.child.size);
+               *(void **)(((char *)opt) + arg->offset) = child;
+       }
 
        if (child)
                isl_arg_set_defaults(arg->u.child.child, child);
-
-       *(void **)(((char *)opt) + arg->offset) = child;
 }
 
 static void set_default_user(struct isl_arg *arg, void *opt)
@@ -51,6 +56,11 @@ static void set_default_user(struct isl_arg *arg, void *opt)
        arg->u.user.init(((char *)opt) + arg->offset);
 }
 
+static void set_default_int(struct isl_arg *arg, void *opt)
+{
+       *(int *)(((char *)opt) + arg->offset) = arg->u.i.default_value;
+}
+
 static void set_default_long(struct isl_arg *arg, void *opt)
 {
        *(long *)(((char *)opt) + arg->offset) = arg->u.l.default_value;
@@ -90,6 +100,9 @@ void isl_arg_set_defaults(struct isl_arg *arg, void *opt)
                case isl_arg_user:
                        set_default_user(&arg[i], opt);
                        break;
+               case isl_arg_int:
+                       set_default_int(&arg[i], opt);
+                       break;
                case isl_arg_long:
                        set_default_long(&arg[i], opt);
                        break;
@@ -101,6 +114,7 @@ void isl_arg_set_defaults(struct isl_arg *arg, void *opt)
                        set_default_str(&arg[i], opt);
                        break;
                case isl_arg_alias:
+               case isl_arg_footer:
                case isl_arg_version:
                case isl_arg_end:
                        break;
@@ -108,18 +122,18 @@ void isl_arg_set_defaults(struct isl_arg *arg, void *opt)
        }
 }
 
-void isl_arg_free(struct isl_arg *arg, void *opt)
+static void free_args(struct isl_arg *arg, void *opt)
 {
        int i;
 
-       if (!opt)
-               return;
-
        for (i = 0; arg[i].type != isl_arg_end; ++i) {
                switch (arg[i].type) {
                case isl_arg_child:
-                       isl_arg_free(arg[i].u.child.child,
-                               *(void **)(((char *)opt) + arg[i].offset));
+                       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));
                        break;
                case isl_arg_arg:
                case isl_arg_str:
@@ -133,13 +147,23 @@ void isl_arg_free(struct isl_arg *arg, void *opt)
                case isl_arg_bool:
                case isl_arg_choice:
                case isl_arg_flags:
+               case isl_arg_int:
                case isl_arg_long:
                case isl_arg_ulong:
                case isl_arg_version:
+               case isl_arg_footer:
                case isl_arg_end:
                        break;
                }
        }
+}
+
+void isl_arg_free(struct isl_arg *arg, void *opt)
+{
+       if (!opt)
+               return;
+
+       free_args(arg, opt);
 
        free(opt);
 }
@@ -198,40 +222,44 @@ const void *isl_memrchr(const void *s, int c, size_t n)
        return NULL;
 }
 
-static int print_help_msg(struct isl_arg *decl, int pos)
+static int wrap_msg(const char *s, int indent, int pos)
 {
        int len;
-       const char *s;
+       int wrap_len = 75 - indent;
 
-       if (!decl->help_msg)
-               return pos;
-
-       if (pos >= 29)
-               printf("\n%30s", "");
+       if (pos + 1 >= indent)
+               printf("\n%*s", indent, "");
        else
-               printf("%*s", 30 - pos, "");
+               printf("%*s", indent - pos, "");
 
-       s = decl->help_msg;
        len = strlen(s);
-       while (len > 45) {
-               const char *space = isl_memrchr(s, ' ', 45);
+       while (len > wrap_len) {
+               const char *space = isl_memrchr(s, ' ', wrap_len);
                int l;
 
                if (!space)
-                       space = strchr(s + 45, ' ');
+                       space = strchr(s + wrap_len, ' ');
                if (!space)
                        break;
                l = space - s;
                printf("%.*s", l, s);
                s = space + 1;
                len -= l + 1;
-               printf("\n%30s", "");
+               printf("\n%*s", indent, "");
        }
 
        printf("%s", s);
        return len;
 }
 
+static int print_help_msg(struct isl_arg *decl, int pos)
+{
+       if (!decl->help_msg)
+               return pos;
+
+       return wrap_msg(decl->help_msg, 30, pos);
+}
+
 static void print_default(struct isl_arg *decl, const char *def, int pos)
 {
        int i;
@@ -382,6 +410,18 @@ 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)
+{
+       int pos;
+       char val[20];
+       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);
+       print_default(decl, val, pos);
+       printf("\n");
+}
+
 static void print_long_help(struct isl_arg *decl, const char *prefix)
 {
        int pos;
@@ -425,6 +465,7 @@ static void print_str_help(struct isl_arg *decl, const char *prefix)
 static void print_help(struct isl_arg *arg, const char *prefix)
 {
        int i;
+       int any = 0;
 
        for (i = 0; arg[i].type != isl_arg_end; ++i) {
                if (arg[i].flags & ISL_ARG_HIDDEN)
@@ -432,25 +473,36 @@ static void print_help(struct isl_arg *arg, const char *prefix)
                switch (arg[i].type) {
                case isl_arg_flags:
                        print_flags_help(&arg[i], prefix);
+                       any = 1;
                        break;
                case isl_arg_choice:
                        print_choice_help(&arg[i], prefix);
+                       any = 1;
                        break;
                case isl_arg_bool:
                        print_bool_help(&arg[i], prefix);
+                       any = 1;
+                       break;
+               case isl_arg_int:
+                       print_int_help(&arg[i], prefix);
+                       any = 1;
                        break;
                case isl_arg_long:
                        print_long_help(&arg[i], prefix);
+                       any = 1;
                        break;
                case isl_arg_ulong:
                        print_ulong_help(&arg[i], prefix);
+                       any = 1;
                        break;
                case isl_arg_str:
                        print_str_help(&arg[i], prefix);
+                       any = 1;
                        break;
                case isl_arg_alias:
                case isl_arg_version:
                case isl_arg_arg:
+               case isl_arg_footer:
                case isl_arg_child:
                case isl_arg_user:
                case isl_arg_end:
@@ -464,10 +516,12 @@ static void print_help(struct isl_arg *arg, const char *prefix)
                if (arg[i].flags & ISL_ARG_HIDDEN)
                        continue;
 
-               printf("\n");
+               if (any)
+                       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);
+               any = 1;
        }
 }
 
@@ -522,6 +576,13 @@ static void print_help_and_exit(struct isl_arg *arg, const char *prog)
                printf("  -V, --version\n");
        print_bool_help(help_arg, NULL);
 
+       for (i = 0; arg[i].type != isl_arg_end; ++i) {
+               if (arg[i].type != isl_arg_footer)
+                       continue;
+               wrap_msg(arg[i].help_msg, 0, 0);
+               printf("\n");
+       }
+
        exit(0);
 }
 
@@ -772,6 +833,34 @@ static int parse_str_option(struct isl_arg *decl, char **arg,
        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)
 {
@@ -846,10 +935,18 @@ static int parse_ulong_option(struct isl_arg *decl, char **arg,
 static int parse_option(struct isl_arg *decl, char **arg,
        const char *prefix, void *opt);
 
-static int parse_child_option(struct isl_arg *decl, char **arg, void *opt)
+static int parse_child_option(struct isl_arg *decl, char **arg,
+       const char *prefix, void *opt)
 {
-       return parse_option(decl->u.child.child, arg, decl->long_name,
-                               *(void **)(((char *)opt) + decl->offset));
+       void *child;
+
+       if (decl->offset == (size_t) -1)
+               child = opt;
+       else {
+               child = *(void **)(((char *)opt) + decl->offset);
+               prefix = decl->long_name;
+       }
+       return parse_option(decl->u.child.child, arg, prefix, child);
 }
 
 static int parse_option(struct isl_arg *decl, char **arg,
@@ -866,6 +963,9 @@ static int parse_option(struct isl_arg *decl, char **arg,
                case isl_arg_flags:
                        parsed = parse_flags_option(&decl[i], arg, prefix, opt);
                        break;
+               case isl_arg_int:
+                       parsed = parse_int_option(&decl[i], arg, prefix, opt);
+                       break;
                case isl_arg_long:
                        parsed = parse_long_option(&decl[i], arg, prefix, opt);
                        break;
@@ -879,10 +979,11 @@ static int parse_option(struct isl_arg *decl, char **arg,
                        parsed = parse_str_option(&decl[i], arg, prefix, opt);
                        break;
                case isl_arg_child:
-                       parsed = parse_child_option(&decl[i], arg, opt);
+                       parsed = parse_child_option(&decl[i], arg, prefix, opt);
                        break;
                case isl_arg_alias:
                case isl_arg_arg:
+               case isl_arg_footer:
                case isl_arg_user:
                case isl_arg_version:
                case isl_arg_end: