summaryrefslogtreecommitdiffstats
path: root/lib/utils/parse_options.c
diff options
context:
space:
mode:
authorNikola Pajkovsky <npajkovs@redhat.com>2010-10-04 16:08:58 +0200
committerNikola Pajkovsky <npajkovs@redhat.com>2010-10-04 16:08:58 +0200
commitaacc4082c747557a04627b304fce07ca7cdae8b2 (patch)
tree9ad3fad4ff72e31f35019c7453aa84a805fb3f83 /lib/utils/parse_options.c
parent1ae327bd0df1eb621fc6a9b4d8b81f10bf7f019d (diff)
parent97ced498a972810547d2e87cbbce932593b1bc40 (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.c130
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);
+}