X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_arg.c;h=533eface4479ead119f9157264bd7ddb817eb6e8;hb=94c0050dc211a6c95203d96943d66a100446a0b7;hp=17c67ffd1a911f5e167b7c41ea3e4b2bf823e4a8;hpb=c1dbabe09b2ea06c17f5dbbcb615d0ab5a3143d0;p=platform%2Fupstream%2Fisl.git diff --git a/isl_arg.c b/isl_arg.c index 17c67ff..533efac 100644 --- a/isl_arg.c +++ b/isl_arg.c @@ -11,8 +11,13 @@ #include #include -#include "isl_arg.h" -#include +#include +#include + +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) { @@ -26,6 +31,8 @@ static void set_default_flags(struct isl_arg *arg, void *opt) static void set_default_bool(struct isl_arg *arg, void *opt) { + if (arg->offset == (size_t) -1) + return; *(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value; } @@ -93,6 +100,7 @@ void isl_arg_set_defaults(struct isl_arg *arg, void *opt) case isl_arg_str: set_default_str(&arg[i], opt); break; + case isl_arg_alias: case isl_arg_version: case isl_arg_end: break; @@ -121,6 +129,7 @@ void isl_arg_free(struct isl_arg *arg, void *opt) if (arg[i].u.user.clear) arg[i].u.user.clear(((char *)opt) + arg[i].offset); break; + case isl_arg_alias: case isl_arg_bool: case isl_arg_choice: case isl_arg_flags: @@ -144,11 +153,16 @@ static int print_arg_help(struct isl_arg *decl, const char *prefix, int no) return 4; } - if (decl->short_name) + if (decl->short_name) { printf(" -%c, --", decl->short_name); - else + len += 8; + } else if (decl->flags & ISL_ARG_SINGLE_DASH) { + printf(" -"); + len += 3; + } else { printf(" --"); - len += 8; + len += 8; + } if (prefix) { printf("%s-", prefix); @@ -161,6 +175,17 @@ static int print_arg_help(struct isl_arg *decl, const char *prefix, int no) printf("%s", decl->long_name); len += strlen(decl->long_name); + while ((++decl)->type == isl_arg_alias) { + printf(", --"); + len += 4; + if (no) { + printf("no-"); + len += 3; + } + printf("%s", decl->long_name); + len += strlen(decl->long_name); + } + return len; } @@ -207,20 +232,14 @@ static int print_help_msg(struct isl_arg *decl, int pos) return len; } -static void print_default_choice(struct isl_arg *decl, int pos) +static void print_default(struct isl_arg *decl, const char *def, int pos) { int i; const char *default_prefix = "[default: "; const char *default_suffix = "]"; - const char *s = "none"; int len; - for (i = 0; decl->u.choice.choice[i].name; ++i) - if (decl->u.choice.choice[i].value == decl->u.choice.default_value) { - s = decl->u.choice.choice[i].name; - break; - } - len = strlen(default_prefix) + strlen(s) + strlen(default_suffix); + len = strlen(default_prefix) + strlen(def) + strlen(default_suffix); if (!decl->help_msg) { if (pos >= 29) @@ -234,7 +253,21 @@ static void print_default_choice(struct isl_arg *decl, int pos) else printf(" "); } - printf("%s%s%s", default_prefix, s, default_suffix); + printf("%s%s%s", default_prefix, def, default_suffix); +} + +static void print_default_choice(struct isl_arg *decl, int pos) +{ + int i; + const char *s = "none"; + + for (i = 0; decl->u.choice.choice[i].name; ++i) + if (decl->u.choice.choice[i].value == decl->u.choice.default_value) { + s = decl->u.choice.choice[i].name; + break; + } + + print_default(decl, s, pos); } static void print_choice_help(struct isl_arg *decl, const char *prefix) @@ -337,10 +370,18 @@ static void print_bool_help(struct isl_arg *decl, const char *prefix) int pos; int no = decl->u.b.default_value == 1; pos = print_arg_help(decl, prefix, no); - print_help_msg(decl, pos); + pos = print_help_msg(decl, pos); + if (decl->offset != (size_t) -1) + print_default(decl, no ? "yes" : "no", pos); 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; @@ -374,9 +415,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"); } @@ -404,9 +446,8 @@ static void print_help(struct isl_arg *arg, const char *prefix) case isl_arg_str: print_str_help(&arg[i], prefix); break; + case isl_arg_alias: case isl_arg_version: - printf(" -V, --version\n"); - break; case isl_arg_arg: case isl_arg_child: case isl_arg_user: @@ -439,6 +480,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; @@ -452,10 +513,35 @@ static void print_help_and_exit(struct isl_arg *arg, const char *prog) printf("\n\n"); print_help(arg, NULL); + printf("\n"); + if (any_version(arg)) + printf(" -V, --version\n"); + print_bool_help(help_arg, NULL); exit(0); } +static int match_long_name(struct isl_arg *decl, + const char *start, const char *end) +{ + do { + if (end - start == strlen(decl->long_name) && + !strncmp(start, decl->long_name, end - start)) + return 1; + } while ((++decl)->type == isl_arg_alias); + + return 0; +} + +static const char *skip_dash_dash(struct isl_arg *decl, const char *arg) +{ + if (!strncmp(arg, "--", 2)) + return arg + 2; + if ((decl->flags & ISL_ARG_SINGLE_DASH) && arg[0] == '-') + return arg + 1; + return NULL; +} + static const char *skip_name(struct isl_arg *decl, const char *arg, const char *prefix, int need_argument, int *has_argument) { @@ -470,11 +556,13 @@ static const char *skip_name(struct isl_arg *decl, const char *arg, *has_argument = arg[2] != '\0'; return arg + 2; } + if (!decl->long_name) + return NULL; - if (strncmp(arg, "--", 2)) + name = skip_dash_dash(decl, arg); + if (!name) return NULL; - name = arg + 2; equal = strchr(name, '='); if (need_argument && !equal) return NULL; @@ -490,8 +578,7 @@ static const char *skip_name(struct isl_arg *decl, const char *arg, name += prefix_len + 1; } - if (end - name != strlen(decl->long_name) || - strncmp(name, decl->long_name, end - name)) + if (!match_long_name(decl, name, end)) return NULL; return equal ? equal + 1 : end; @@ -590,28 +677,64 @@ static int parse_flags_option(struct isl_arg *decl, char **arg, return has_argument ? 1 : 2; } -static int parse_bool_option(struct isl_arg *decl, const char *arg, +static int parse_bool_option(struct isl_arg *decl, char **arg, const char *prefix, void *opt) { - if (skip_name(decl, arg, prefix, 0, NULL)) { - *(unsigned *)(((char *)opt) + decl->offset) = 1; + 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->u.b.set) + decl->u.b.set(opt, val); + else if (decl->offset != (size_t) -1) + *p = val; + return 2; + } + } + if (decl->u.b.set) + decl->u.b.set(opt, 1); + else if (decl->offset != (size_t) -1) + *p = 1; return 1; } - if (strncmp(arg, "--no-", 5)) + 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; - arg += 5; + name += 3; if (prefix) { size_t prefix_len = strlen(prefix); - if (strncmp(arg, prefix, prefix_len) == 0 && - arg[prefix_len] == '-') - arg += prefix_len + 1; + if (strncmp(name, prefix, prefix_len) == 0 && + name[prefix_len] == '-') + name += prefix_len + 1; } - if (!strcmp(arg, decl->long_name)) { - *(unsigned *)(((char *)opt) + decl->offset) = 0; + if (match_long_name(decl, name, name + strlen(name))) { + if (decl->u.b.set) + decl->u.b.set(opt, 0); + else if (decl->offset != (size_t) -1) + *p = 0; return 1; } @@ -631,11 +754,13 @@ static int parse_str_option(struct isl_arg *decl, char **arg, return 0; if (has_argument) { + free(*p); *p = strdup(s); return 1; } if (arg[1]) { + free(*p); *p = strdup(arg[1]); return 2; } @@ -744,7 +869,7 @@ static int parse_option(struct isl_arg *decl, char **arg, parsed = parse_ulong_option(&decl[i], arg, prefix, opt); break; case isl_arg_bool: - parsed = parse_bool_option(&decl[i], *arg, prefix, opt); + parsed = parse_bool_option(&decl[i], arg, prefix, opt); break; case isl_arg_str: parsed = parse_str_option(&decl[i], arg, prefix, opt); @@ -752,6 +877,7 @@ static int parse_option(struct isl_arg *decl, char **arg, case isl_arg_child: parsed = parse_child_option(&decl[i], arg, opt); break; + case isl_arg_alias: case isl_arg_arg: case isl_arg_user: case isl_arg_version: @@ -765,26 +891,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; @@ -830,9 +936,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; @@ -852,8 +968,23 @@ 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) { + char **p; + p = (char **)(((char *)opt)+arg[a].offset); + free(*p); + *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); @@ -865,21 +996,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; }