On 04/07/11 13:47, Prasad Joshi wrote: > - parse-options.[ch] has argument processing code. > > - types.h: Additional types for argument processing. > > - strbuf.[ch]: Added a function prefixcmp to compare string prefix Rather than copy perf code, how about a tools/lib? David > > Signed-off-by: Prasad Joshi <prasadjoshi124@xxxxxxxxx> > --- > tools/kvm/include/kvm/parse-options.h | 161 ++++++++++ > tools/kvm/include/kvm/strbuf.h | 6 + > tools/kvm/include/kvm/util.h | 8 + > tools/kvm/include/linux/types.h | 12 + > tools/kvm/util/parse-options.c | 560 +++++++++++++++++++++++++++++++++ > tools/kvm/util/strbuf.c | 13 + > 6 files changed, 760 insertions(+), 0 deletions(-) > create mode 100644 tools/kvm/include/kvm/parse-options.h > create mode 100644 tools/kvm/include/kvm/strbuf.h > create mode 100644 tools/kvm/util/parse-options.c > create mode 100644 tools/kvm/util/strbuf.c > > diff --git a/tools/kvm/include/kvm/parse-options.h b/tools/kvm/include/kvm/parse-options.h > new file mode 100644 > index 0000000..b59220d > --- /dev/null > +++ b/tools/kvm/include/kvm/parse-options.h > @@ -0,0 +1,161 @@ > +#ifndef __PARSE_OPTIONS_H__ > +#define __PARSE_OPTIONS_H__ > + > +enum parse_opt_type { > + /* special types */ > + OPTION_END, > + OPTION_ARGUMENT, > + OPTION_GROUP, > + /* options with no arguments */ > + OPTION_BIT, > + OPTION_BOOLEAN, > + OPTION_INCR, > + OPTION_SET_UINT, > + OPTION_SET_PTR, > + /* options with arguments (usually) */ > + OPTION_STRING, > + OPTION_INTEGER, > + OPTION_LONG, > + OPTION_CALLBACK, > + OPTION_U64, > + OPTION_UINTEGER, > +}; > + > +enum parse_opt_flags { > + PARSE_OPT_KEEP_DASHDASH = 1, > + PARSE_OPT_STOP_AT_NON_OPTION = 2, > + PARSE_OPT_KEEP_ARGV0 = 4, > + PARSE_OPT_KEEP_UNKNOWN = 8, > + PARSE_OPT_NO_INTERNAL_HELP = 16, > +}; > + > +enum parse_opt_option_flags { > + PARSE_OPT_OPTARG = 1, > + PARSE_OPT_NOARG = 2, > + PARSE_OPT_NONEG = 4, > + PARSE_OPT_HIDDEN = 8, > + PARSE_OPT_LASTARG_DEFAULT = 16, > +}; > + > +struct option; > +typedef int parse_opt_cb(const struct option *, const char *arg, int unset); > +/* > + * `type`:: > + * holds the type of the option, you must have an OPTION_END last in your > + * array. > + * > + * `short_name`:: > + * the character to use as a short option name, '\0' if none. > + * > + * `long_name`:: > + * the long option name, without the leading dashes, NULL if none. > + * > + * `value`:: > + * stores pointers to the values to be filled. > + * > + * `argh`:: > + * token to explain the kind of argument this option wants. Keep it > + * homogenous across the repository. > + * > + * `help`:: > + * the short help associated to what the option does. > + * Must never be NULL (except for OPTION_END). > + * OPTION_GROUP uses this pointer to store the group header. > + * > + * `flags`:: > + * mask of parse_opt_option_flags. > + * PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs) > + * PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs > + * PARSE_OPT_NONEG: says that this option cannot be negated > + * PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in > + * the long one. > + * > + * `callback`:: > + * pointer to the callback to use for OPTION_CALLBACK. > + * > + * `defval`:: > + * default value to fill (*->value) with for PARSE_OPT_OPTARG. > + * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in > + * the value when met. > + * CALLBACKS can use it like they want. > + */ > +struct option { > +enum parse_opt_type type; > +int short_name; > +const char *long_name; > +void *value; > +const char *argh; > +const char *help; > + > +int flags; > +parse_opt_cb *callback; > +intptr_t defval; > +}; > + > +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) > +#define check_vtype(v, type) \ > + (BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v) > + > +#define OPT_INTEGER(s, l, v, h) \ > +{ \ > + .type = OPTION_INTEGER, \ > + .short_name = (s), \ > + .long_name = (l), \ > + .value = check_vtype(v, int *), \ > + .help = (h) \ > +} > + > +#define OPT_U64(s, l, v, h) \ > +{ \ > + .type = OPTION_U64, \ > + .short_name = (s), \ > + .long_name = (l), \ > + .value = check_vtype(v, u64 *), \ > + .help = (h) \ > +} > + > +#define OPT_STRING(s, l, v, a, h) \ > +{ \ > + .type = OPTION_STRING, \ > + .short_name = (s), \ > + .long_name = (l), \ > + .value = check_vtype(v, const char **), (a), \ > + .help = (h) \ > +} > + > +#define OPT_BOOLEAN(s, l, v, h) \ > +{ \ > + .type = OPTION_BOOLEAN, \ > + .short_name = (s), \ > + .long_name = (l), \ > + .value = check_vtype(v, bool *), \ > + .help = (h) \ > +} > + > +#define OPT_END() { .type = OPTION_END } > + > +enum { > + PARSE_OPT_HELP = -1, > + PARSE_OPT_DONE, > + PARSE_OPT_UNKNOWN, > +}; > + > +/* > + * It's okay for the caller to consume argv/argc in the usual way. > + * Other fields of that structure are private to parse-options and should not > + * be modified in any way. > + **/ > +struct parse_opt_ctx_t { > + const char **argv; > + const char **out; > + int argc, cpidx; > + const char *opt; > + int flags; > +}; > + > +/* global functions */ > +void usage_with_options(const char * const *usagestr, > + const struct option *opts); > +int parse_options(int argc, const char **argv, const struct option *options, > + const char * const usagestr[], int flags); > +#endif > diff --git a/tools/kvm/include/kvm/strbuf.h b/tools/kvm/include/kvm/strbuf.h > new file mode 100644 > index 0000000..e67ca20 > --- /dev/null > +++ b/tools/kvm/include/kvm/strbuf.h > @@ -0,0 +1,6 @@ > +#ifndef __STRBUF_H__ > +#define __STRBUF_H__ > + > +int prefixcmp(const char *str, const char *prefix); > + > +#endif > diff --git a/tools/kvm/include/kvm/util.h b/tools/kvm/include/kvm/util.h > index 8c80777..ae033cc 100644 > --- a/tools/kvm/include/kvm/util.h > +++ b/tools/kvm/include/kvm/util.h > @@ -48,4 +48,12 @@ do { \ > > extern size_t strlcat(char *dest, const char *src, size_t count); > > +/* some inline functions */ > + > +static inline const char *skip_prefix(const char *str, const char *prefix) > +{ > + size_t len = strlen(prefix); > + return strncmp(str, prefix, len) ? NULL : str + len; > +} > + > #endif /* KVM__UTIL_H */ > diff --git a/tools/kvm/include/linux/types.h b/tools/kvm/include/linux/types.h > index 70e2546..b989d2a 100644 > --- a/tools/kvm/include/linux/types.h > +++ b/tools/kvm/include/linux/types.h > @@ -15,4 +15,16 @@ > #define __s64 int64_t > #define __u64 uint64_t > > +typedef __u64 u64; > +typedef __s64 s64; > + > +typedef __u32 u32; > +typedef __s32 s32; > + > +typedef __u16 u16; > +typedef __s16 s16; > + > +typedef __u8 u8; > +typedef __s8 s8; > + > #endif /* LINUX_TYPES_H */ > diff --git a/tools/kvm/util/parse-options.c b/tools/kvm/util/parse-options.c > new file mode 100644 > index 0000000..3065c50 > --- /dev/null > +++ b/tools/kvm/util/parse-options.c > @@ -0,0 +1,560 @@ > +#include <stdio.h> > +#include <string.h> > +#include <unistd.h> > +#include <stdint.h> > + > +#include <stdbool.h> > + > +/* user defined includes */ > +#include <linux/types.h> > +#include <kvm/util.h> > +#include <kvm/parse-options.h> > +#include <kvm/strbuf.h> > + > +#define OPT_SHORT 1 > +#define OPT_UNSET 2 > + > +static int opterror(const struct option *opt, const char *reason, int flags) > +{ > + if (flags & OPT_SHORT) > + return error("switch `%c' %s", opt->short_name, reason); > + if (flags & OPT_UNSET) > + return error("option `no-%s' %s", opt->long_name, reason); > + return error("option `%s' %s", opt->long_name, reason); > +} > + > +static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, > + int flags, const char **arg) > +{ > + if (p->opt) { > + *arg = p->opt; > + p->opt = NULL; > + } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 || > + **(p->argv + 1) == '-')) { > + *arg = (const char *)opt->defval; > + } else if (p->argc > 1) { > + p->argc--; > + *arg = *++p->argv; > + } else > + return opterror(opt, "requires a value", flags); > + return 0; > +} > + > +static int get_value(struct parse_opt_ctx_t *p, > + const struct option *opt, int flags) > +{ > + const char *s, *arg = NULL; > + const int unset = flags & OPT_UNSET; > + > + if (unset && p->opt) > + return opterror(opt, "takes no value", flags); > + if (unset && (opt->flags & PARSE_OPT_NONEG)) > + return opterror(opt, "isn't available", flags); > + > + if (!(flags & OPT_SHORT) && p->opt) { > + switch (opt->type) { > + case OPTION_CALLBACK: > + if (!(opt->flags & PARSE_OPT_NOARG)) > + break; > + /* FALLTHROUGH */ > + case OPTION_BOOLEAN: > + case OPTION_INCR: > + case OPTION_BIT: > + case OPTION_SET_UINT: > + case OPTION_SET_PTR: > + return opterror(opt, "takes no value", flags); > + case OPTION_END: > + case OPTION_ARGUMENT: > + case OPTION_GROUP: > + case OPTION_STRING: > + case OPTION_INTEGER: > + case OPTION_UINTEGER: > + case OPTION_LONG: > + case OPTION_U64: > + default: > + break; > + } > + } > + > + switch (opt->type) { > + case OPTION_BIT: > + if (unset) > + *(int *)opt->value &= ~opt->defval; > + else > + *(int *)opt->value |= opt->defval; > + return 0; > + > + case OPTION_BOOLEAN: > + *(bool *)opt->value = unset ? false : true; > + return 0; > + > + case OPTION_INCR: > + *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; > + return 0; > + > + case OPTION_SET_UINT: > + *(unsigned int *)opt->value = unset ? 0 : opt->defval; > + return 0; > + > + case OPTION_SET_PTR: > + *(void **)opt->value = unset ? NULL : (void *)opt->defval; > + return 0; > + > + case OPTION_STRING: > + if (unset) > + *(const char **)opt->value = NULL; > + else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) > + *(const char **)opt->value = (const char *)opt->defval; > + else > + return get_arg(p, opt, flags, (const char **)opt->value); > + return 0; > + > + case OPTION_CALLBACK: > + if (unset) > + return (*opt->callback)(opt, NULL, 1) ? (-1) : 0; > + if (opt->flags & PARSE_OPT_NOARG) > + return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; > + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) > + return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; > + if (get_arg(p, opt, flags, &arg)) > + return -1; > + return (*opt->callback)(opt, arg, 0) ? (-1) : 0; > + > + case OPTION_INTEGER: > + if (unset) { > + *(int *)opt->value = 0; > + return 0; > + } > + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { > + *(int *)opt->value = opt->defval; > + return 0; > + } > + if (get_arg(p, opt, flags, &arg)) > + return -1; > + *(int *)opt->value = strtol(arg, (char **)&s, 10); > + if (*s) > + return opterror(opt, "expects a numerical value", flags); > + return 0; > + > + case OPTION_UINTEGER: > + if (unset) { > + *(unsigned int *)opt->value = 0; > + return 0; > + } > + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { > + *(unsigned int *)opt->value = opt->defval; > + return 0; > + } > + if (get_arg(p, opt, flags, &arg)) > + return -1; > + *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); > + if (*s) > + return opterror(opt, "expects a numerical value", flags); > + return 0; > + > + case OPTION_LONG: > + if (unset) { > + *(long *)opt->value = 0; > + return 0; > + } > + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { > + *(long *)opt->value = opt->defval; > + return 0; > + } > + if (get_arg(p, opt, flags, &arg)) > + return -1; > + *(long *)opt->value = strtol(arg, (char **)&s, 10); > + if (*s) > + return opterror(opt, "expects a numerical value", flags); > + return 0; > + > + case OPTION_U64: > + if (unset) { > + *(u64 *)opt->value = 0; > + return 0; > + } > + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { > + *(u64 *)opt->value = opt->defval; > + return 0; > + } > + if (get_arg(p, opt, flags, &arg)) > + return -1; > + *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); > + if (*s) > + return opterror(opt, "expects a numerical value", flags); > + return 0; > + > + case OPTION_END: > + case OPTION_ARGUMENT: > + case OPTION_GROUP: > + default: > + die("should not happen, someone must be hit on the forehead"); > + } > +} > + > +#define USAGE_OPTS_WIDTH 24 > +#define USAGE_GAP 2 > + > +static int usage_with_options_internal(const char * const *usagestr, > + const struct option *opts, int full) > +{ > + if (!usagestr) > + return PARSE_OPT_HELP; > + > + fprintf(stderr, "\n usage: %s\n", *usagestr++); > + while (*usagestr && **usagestr) > + fprintf(stderr, " or: %s\n", *usagestr++); > + while (*usagestr) { > + fprintf(stderr, "%s%s\n", > + **usagestr ? " " : "", > + *usagestr); > + usagestr++; > + } > + > + if (opts->type != OPTION_GROUP) > + fputc('\n', stderr); > + > + for (; opts->type != OPTION_END; opts++) { > + size_t pos; > + int pad; > + > + if (opts->type == OPTION_GROUP) { > + fputc('\n', stderr); > + if (*opts->help) > + fprintf(stderr, "%s\n", opts->help); > + continue; > + } > + if (!full && (opts->flags & PARSE_OPT_HIDDEN)) > + continue; > + > + pos = fprintf(stderr, " "); > + if (opts->short_name) > + pos += fprintf(stderr, "-%c", opts->short_name); > + else > + pos += fprintf(stderr, " "); > + > + if (opts->long_name && opts->short_name) > + pos += fprintf(stderr, ", "); > + if (opts->long_name) > + pos += fprintf(stderr, "--%s", opts->long_name); > + > + switch (opts->type) { > + case OPTION_ARGUMENT: > + break; > + case OPTION_LONG: > + case OPTION_U64: > + case OPTION_INTEGER: > + case OPTION_UINTEGER: > + if (opts->flags & PARSE_OPT_OPTARG) > + if (opts->long_name) > + pos += fprintf(stderr, "[=<n>]"); > + else > + pos += fprintf(stderr, "[<n>]"); > + else > + pos += fprintf(stderr, " <n>"); > + break; > + case OPTION_CALLBACK: > + if (opts->flags & PARSE_OPT_NOARG) > + break; > + /* FALLTHROUGH */ > + case OPTION_STRING: > + if (opts->argh) { > + if (opts->flags & PARSE_OPT_OPTARG) > + if (opts->long_name) > + pos += fprintf(stderr, "[=<%s>]", opts->argh); > + else > + pos += fprintf(stderr, "[<%s>]", opts->argh); > + else > + pos += fprintf(stderr, " <%s>", opts->argh); > + } else { > + if (opts->flags & PARSE_OPT_OPTARG) > + if (opts->long_name) > + pos += fprintf(stderr, "[=...]"); > + else > + pos += fprintf(stderr, "[...]"); > + else > + pos += fprintf(stderr, " ..."); > + } > + break; > + default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ > + case OPTION_END: > + case OPTION_GROUP: > + case OPTION_BIT: > + case OPTION_BOOLEAN: > + case OPTION_INCR: > + case OPTION_SET_UINT: > + case OPTION_SET_PTR: > + break; > + } > + 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, "", opts->help); > + } > + fputc('\n', stderr); > + > + return PARSE_OPT_HELP; > +} > + > +void usage_with_options(const char * const *usagestr, > + const struct option *opts) > +{ > + usage_with_options_internal(usagestr, opts, 0); > + exit(129); > +} > + > +static void check_typos(const char *arg, const struct option *options) > +{ > + if (strlen(arg) < 3) > + return; > + > + if (!prefixcmp(arg, "no-")) { > + error ("did you mean `--%s` (with two dashes ?)", arg); > + exit(129); > + } > + > + for (; options->type != OPTION_END; options++) { > + if (!options->long_name) > + continue; > + if (!prefixcmp(options->long_name, arg)) { > + error ("did you mean `--%s` (with two dashes ?)", arg); > + exit(129); > + } > + } > +} > + > +static int parse_options_usage(const char * const *usagestr, > + const struct option *opts) > +{ > + return usage_with_options_internal(usagestr, opts, 0); > +} > + > +static int parse_short_opt(struct parse_opt_ctx_t *p, > + const struct option *options) > +{ > + for (; options->type != OPTION_END; options++) { > + if (options->short_name == *p->opt) { > + p->opt = p->opt[1] ? p->opt + 1 : NULL; > + return get_value(p, options, OPT_SHORT); > + } > + } > + return -2; > +} > + > +static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, > + const struct option *options) > +{ > + const char *arg_end = strchr(arg, '='); > + const struct option *abbrev_option = NULL, *ambiguous_option = NULL; > + int abbrev_flags = 0, ambiguous_flags = 0; > + > + if (!arg_end) > + arg_end = arg + strlen(arg); > + > + for (; options->type != OPTION_END; options++) { > + const char *rest; > + int flags = 0; > + > + if (!options->long_name) > + continue; > + > + rest = skip_prefix(arg, options->long_name); > + if (options->type == OPTION_ARGUMENT) { > + if (!rest) > + continue; > + if (*rest == '=') > + return opterror(options, "takes no value", flags); > + if (*rest) > + continue; > + p->out[p->cpidx++] = arg - 2; > + return 0; > + } > + if (!rest) { > + /* abbreviated? */ > + if (!strncmp(options->long_name, arg, arg_end - arg)) { > +is_abbreviated: > + if (abbrev_option) { > + /* > + * If this is abbreviated, it is > + * ambiguous. So when there is no > + * exact match later, we need to > + * error out. > + */ > + ambiguous_option = abbrev_option; > + ambiguous_flags = abbrev_flags; > + } > + if (!(flags & OPT_UNSET) && *arg_end) > + p->opt = arg_end + 1; > + abbrev_option = options; > + abbrev_flags = flags; > + continue; > + } > + /* negated and abbreviated very much? */ > + if (!prefixcmp("no-", arg)) { > + flags |= OPT_UNSET; > + goto is_abbreviated; > + } > + /* negated? */ > + if (strncmp(arg, "no-", 3)) > + continue; > + flags |= OPT_UNSET; > + rest = skip_prefix(arg + 3, options->long_name); > + /* abbreviated and negated? */ > + if (!rest && !prefixcmp(options->long_name, arg + 3)) > + goto is_abbreviated; > + if (!rest) > + continue; > + } > + if (*rest) { > + if (*rest != '=') > + continue; > + p->opt = rest + 1; > + } > + return get_value(p, options, flags); > + } > + > + if (ambiguous_option) > + return error("Ambiguous option: %s " > + "(could be --%s%s or --%s%s)", > + arg, > + (ambiguous_flags & OPT_UNSET) ? "no-" : "", > + ambiguous_option->long_name, > + (abbrev_flags & OPT_UNSET) ? "no-" : "", > + abbrev_option->long_name); > + if (abbrev_option) > + return get_value(p, abbrev_option, abbrev_flags); > + return -2; > +} > + > + > +static void parse_options_start(struct parse_opt_ctx_t *ctx, int argc, > + const char **argv, int flags) > +{ > + memset(ctx, 0, sizeof(*ctx)); > + ctx->argc = argc; > + ctx->argv = argv; > + ctx->out = argv; > + ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0); > + ctx->flags = flags; > + if ((flags & PARSE_OPT_KEEP_UNKNOWN) && > + (flags & PARSE_OPT_STOP_AT_NON_OPTION)) > + die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together"); > +} > + > +static int parse_options_end(struct parse_opt_ctx_t *ctx) > +{ > + memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out)); > + ctx->out[ctx->cpidx + ctx->argc] = NULL; > + return ctx->cpidx + ctx->argc; > +} > + > + > +static int parse_options_step(struct parse_opt_ctx_t *ctx, > + const struct option *options, const char * const usagestr[]) > +{ > + int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); > + > + /* we must reset ->opt, unknown short option leave it dangling */ > + ctx->opt = NULL; > + > + for (; ctx->argc; ctx->argc--, ctx->argv++) { > + const char *arg = ctx->argv[0]; > + > + if (*arg != '-' || !arg[1]) { > + if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) > + break; > + ctx->out[ctx->cpidx++] = ctx->argv[0]; > + continue; > + } > + > + if (arg[1] != '-') { > + ctx->opt = arg + 1; > + if (internal_help && *ctx->opt == 'h') > + return parse_options_usage(usagestr, options); > + switch (parse_short_opt(ctx, options)) { > + case -1: > + return parse_options_usage(usagestr, options); > + case -2: > + goto unknown; > + default: > + break; > + } > + if (ctx->opt) > + check_typos(arg + 1, options); > + while (ctx->opt) { > + if (internal_help && *ctx->opt == 'h') > + return parse_options_usage(usagestr, options); > + switch (parse_short_opt(ctx, options)) { > + case -1: > + return parse_options_usage(usagestr, options); > + case -2: > + /* fake a short option thing to hide the fact that we may have > + * started to parse aggregated stuff > + * > + * This is leaky, too bad. > + */ > + ctx->argv[0] = strdup(ctx->opt - 1); > + *(char *)ctx->argv[0] = '-'; > + goto unknown; > + default: > + break; > + } > + } > + continue; > + } > + > + if (!arg[2]) { /* "--" */ > + if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) { > + ctx->argc--; > + ctx->argv++; > + } > + break; > + } > + > + if (internal_help && !strcmp(arg + 2, "help-all")) > + return usage_with_options_internal(usagestr, options, 1); > + if (internal_help && !strcmp(arg + 2, "help")) > + return parse_options_usage(usagestr, options); > + switch (parse_long_opt(ctx, arg + 2, options)) { > + case -1: > + return parse_options_usage(usagestr, options); > + case -2: > + goto unknown; > + default: > + break; > + } > + continue; > +unknown: > + if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN)) > + return PARSE_OPT_UNKNOWN; > + ctx->out[ctx->cpidx++] = ctx->argv[0]; > + ctx->opt = NULL; > + } > + return PARSE_OPT_DONE; > +} > + > +int parse_options(int argc, const char **argv, const struct option *options, > + const char * const usagestr[], int flags) > +{ > + struct parse_opt_ctx_t ctx; > + > + parse_options_start(&ctx, argc, argv, flags); > + switch (parse_options_step(&ctx, options, usagestr)) { > + case PARSE_OPT_HELP: > + exit(129); > + case PARSE_OPT_DONE: > + break; > + default: /* PARSE_OPT_UNKNOWN */ > + if (ctx.argv[0][1] == '-') { > + error("unknown option `%s'", ctx.argv[0] + 2); > + } else { > + error("unknown switch `%c'", *ctx.opt); > + } > + usage_with_options(usagestr, options); > + } > + > + return parse_options_end(&ctx); > +} > diff --git a/tools/kvm/util/strbuf.c b/tools/kvm/util/strbuf.c > new file mode 100644 > index 0000000..ec77ab1 > --- /dev/null > +++ b/tools/kvm/util/strbuf.c > @@ -0,0 +1,13 @@ > + > +/* user defined headers */ > +#include <kvm/strbuf.h> > + > +int prefixcmp(const char *str, const char *prefix) > +{ > + for (; ; str++, prefix++) { > + if (!*prefix) > + return 0; > + else if (*str != *prefix) > + return (unsigned char)*prefix - (unsigned char)*str; > + } > +} -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html