isl_arg_parse: allow options after arguments
[platform/upstream/isl.git] / isl_arg.c
index 9378583..fb7eab7 100644 (file)
--- a/isl_arg.c
+++ b/isl_arg.c
@@ -350,6 +350,12 @@ static void print_bool_help(struct isl_arg *decl, const char *prefix)
        printf("\n");
 }
 
+static int print_argument_name(struct isl_arg *decl, const char *name, int pos)
+{
+       printf("%c<%s>", decl->long_name ? '=' : ' ', name);
+       return pos + 3 + strlen(name);
+}
+
 static void print_long_help(struct isl_arg *decl, const char *prefix)
 {
        int pos;
@@ -383,9 +389,10 @@ static void print_str_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);
-       printf("=%s", a);
-       pos += 1 + strlen(a);
-       print_help_msg(decl, pos);
+       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");
 }
 
@@ -414,8 +421,6 @@ static void print_help(struct isl_arg *arg, const char *prefix)
                        print_str_help(&arg[i], prefix);
                        break;
                case isl_arg_version:
-                       printf("  -V, --version\n");
-                       break;
                case isl_arg_arg:
                case isl_arg_child:
                case isl_arg_user:
@@ -448,6 +453,26 @@ static const char *prog_name(const char *prog)
        return prog;
 }
 
+static int any_version(struct isl_arg *decl)
+{
+       int i;
+
+       for (i = 0; decl[i].type != isl_arg_end; ++i) {
+               switch (decl[i].type) {
+               case isl_arg_version:
+                       return 1;
+               case isl_arg_child:
+                       if (any_version(decl[i].u.child.child))
+                               return 1;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return 0;
+}
+
 static void print_help_and_exit(struct isl_arg *arg, const char *prog)
 {
        int i;
@@ -461,6 +486,10 @@ static void print_help_and_exit(struct isl_arg *arg, const char *prog)
        printf("\n\n");
 
        print_help(arg, NULL);
+       if (any_version(arg)) {
+               printf("\n");
+               printf("  -V, --version\n");
+       }
 
        exit(0);
 }
@@ -792,26 +821,6 @@ static int parse_option(struct isl_arg *decl, char **arg,
        return 0;
 }
 
-static int any_version(struct isl_arg *decl)
-{
-       int i;
-
-       for (i = 0; decl[i].type != isl_arg_end; ++i) {
-               switch (decl[i].type) {
-               case isl_arg_version:
-                       return 1;
-               case isl_arg_child:
-                       if (any_version(decl[i].u.child.child))
-                               return 1;
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       return 0;
-}
-
 static void print_version(struct isl_arg *decl)
 {
        int i;
@@ -857,9 +866,19 @@ static int n_arg(struct isl_arg *arg)
        return n_arg;
 }
 
+static int next_arg(struct isl_arg *arg, int a)
+{
+       for (++a; arg[a].type != isl_arg_end; ++a)
+               if (arg[a].type == isl_arg_arg)
+                       return a;
+
+       return -1;
+}
+
 int isl_arg_parse(struct isl_arg *arg, int argc, char **argv, void *opt,
        unsigned flags)
 {
+       int a = -1;
        int skip = 0;
        int i;
        int n;
@@ -879,8 +898,22 @@ int isl_arg_parse(struct isl_arg *arg, int argc, char **argv, void *opt,
 
        while (argc > 1 + skip) {
                int parsed;
-               if (argv[1 + skip][0] != '-')
-                       break;
+               if (argv[1 + skip][0] != '-') {
+                       a = next_arg(arg, a);
+                       if (a >= 0) {
+                               const char **p;
+                               p = (const char **)(((char *)opt)+arg[a].offset);
+                               *p = strdup(argv[1 + skip]);
+                               argc = drop_argument(argc, argv, 1 + skip, 1);
+                               --n;
+                       } else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
+                               fprintf(stderr, "%s: extra argument: %s\n",
+                                           prog_name(argv[0]), argv[1 + skip]);
+                               exit(-1);
+                       } else
+                               ++skip;
+                       continue;
+               }
                parsed = parse_option(arg, &argv[1 + skip], NULL, opt);
                if (parsed)
                        argc = drop_argument(argc, argv, 1 + skip, parsed);
@@ -892,21 +925,11 @@ int isl_arg_parse(struct isl_arg *arg, int argc, char **argv, void *opt,
                        ++skip;
        }
 
-       if (ISL_FL_ISSET(flags, ISL_ARG_ALL) ? argc != 1 + n
-                                            : argc < 1 + skip + n) {
-               fprintf(stderr, "%s: expecting %d arguments\n",
+       if (n > 0) {
+               fprintf(stderr, "%s: expecting %d more argument(s)\n",
                                prog_name(argv[0]), n);
                exit(-1);
        }
 
-       for (i = 0; arg[i].type != isl_arg_end; ++i) {
-               const char *str;
-               if (arg[i].type != isl_arg_arg)
-                       continue;
-               str = strdup(argv[1 + skip]);
-               *(const char **)(((char *)opt) + arg[i].offset) = str;
-               argc = drop_argument(argc, argv, 1 + skip, 1);
-       }
-
        return argc;
 }