X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_arg.c;h=0963aa126c8fbec8160158bc8ddad2025f0196f3;hb=63fb8a7f484648c3caa25351c8c94ac2395ec563;hp=f4704787e75cf4583fd2556e578a3869f7b8b922;hpb=bbf85ab5afe150c925b01e126c438784b015230a;p=platform%2Fupstream%2Fisl.git diff --git a/isl_arg.c b/isl_arg.c index f470478..0963aa1 100644 --- 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)) {