diff options
| author | Nikola Pajkovsky <npajkovs@redhat.com> | 2010-10-04 16:08:58 +0200 |
|---|---|---|
| committer | Nikola Pajkovsky <npajkovs@redhat.com> | 2010-10-04 16:08:58 +0200 |
| commit | aacc4082c747557a04627b304fce07ca7cdae8b2 (patch) | |
| tree | 9ad3fad4ff72e31f35019c7453aa84a805fb3f83 /lib/utils/parse_options.c | |
| parent | 1ae327bd0df1eb621fc6a9b4d8b81f10bf7f019d (diff) | |
| parent | 97ced498a972810547d2e87cbbce932593b1bc40 (diff) | |
Merge branch 'new-parser'
* new-parser:
Daemon.cpp: remove getopt and use parse_opts instead
new args parser
xfunc.c: add new funtion xcalloc
Diffstat (limited to 'lib/utils/parse_options.c')
| -rw-r--r-- | lib/utils/parse_options.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/lib/utils/parse_options.c b/lib/utils/parse_options.c new file mode 100644 index 00000000..6928e481 --- /dev/null +++ b/lib/utils/parse_options.c @@ -0,0 +1,130 @@ + +#include <getopt.h> +#include "abrtlib.h" +#include "parse_options.h" + +static int parse_opt_size(const struct options *opt) +{ + unsigned size = 1; + for (; opt->type != OPTION_END; opt++) + size++; + + return size; +} + +#define USAGE_OPTS_WIDTH 24 +#define USAGE_GAP 2 + +void parse_usage_and_die(const char * const * usage, const struct options *opt) +{ + fprintf(stderr, _("usage: %s\n"), *usage++); + + while (*usage && **usage) + fprintf(stderr, _(" or: %s\n"), *usage++); + + fputc('\n', stderr); + + for (; opt->type != OPTION_END; opt++) + { + size_t pos; + int pad; + + pos = fprintf(stderr, " "); + if (opt->short_name) + pos += fprintf(stderr, "-%c", opt->short_name); + + if (opt->short_name && opt->long_name) + pos += fprintf(stderr, ", "); + + if (opt->long_name) + pos += fprintf(stderr, "--%s", opt->long_name); + + if (pos <= USAGE_OPTS_WIDTH) + pad = USAGE_OPTS_WIDTH - pos; + else + { + fputc('\n', stderr); + pad = USAGE_OPTS_WIDTH; + } + fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opt->help); + } + fputc('\n', stderr); + exit(1); +} + +void parse_opts(int argc, char **argv, const struct options *opt, + const char * const usage[]) +{ + int size = parse_opt_size(opt); + + struct strbuf *shortopts = strbuf_new(); + + struct option *longopts = xcalloc(sizeof(struct options), size); + int ii; + for (ii = 0; ii < size - 1; ++ii) + { + longopts[ii].name = opt[ii].long_name; + + switch (opt[ii].type) + { + case OPTION_BOOL: + longopts[ii].has_arg = no_argument; + if (opt[ii].short_name) + strbuf_append_char(shortopts, opt[ii].short_name); + break; + case OPTION_STRING: + longopts[ii].has_arg = required_argument; + if (opt[ii].short_name) + strbuf_append_strf(shortopts, "%c:", opt[ii].short_name); + break; + case OPTION_END: + break; + } + longopts[ii].flag = 0; + longopts[ii].val = opt[ii].short_name; + } + + longopts[ii].name = 0; + longopts[ii].has_arg = 0; + longopts[ii].flag = 0; + longopts[ii].val = 0; + + int option_index = 0; + while (1) + { + int c = getopt_long(argc, argv, shortopts->buf, longopts, &option_index); + + if (c == -1) + break; + + if (c == '?') + { + free(longopts); + strbuf_free(shortopts); + parse_usage_and_die(usage, opt); + } + + for (ii = 0; ii < size - 1; ++ii) + { + if (opt[ii].short_name == c) + { + + switch (opt[ii].type) + { + case OPTION_BOOL: + *(int*)opt[ii].value += 1; + break; + case OPTION_STRING: + if (optarg) + *(char**)opt[ii].value = (char*)optarg; + break; + case OPTION_END: + break; + } + } + } + } + + free(longopts); + strbuf_free(shortopts); +} |
