* [PATCH 1/4] Generating list of common kvm tool commands
@ 2011-04-07 19:47 Prasad Joshi
2011-04-07 19:47 ` [PATCH 2/4] Mostly the copied code from perf for argument processing Prasad Joshi
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Prasad Joshi @ 2011-04-07 19:47 UTC (permalink / raw)
To: prasadjoshi124
Cc: mingo, kvm, penberg, asias.hejun, gorcunov, oswaldo.cadenas
- The Documentation/ directory will have a text file for each commmand. The
text file should contain the information about the command in manpage format.
- command-list.txt: is a list of common commands used with the kvm tool.
- util/generate-cmdlist.sh: is a shell script that uses command-list.txt and
text files in Documentation/ directory to generate the common-cmds.h file in
the include directory. The header file is furthur used to display a usage
messgae.
Signed-off-by: Prasad Joshi <prasadjoshi124@gmail.com>
---
tools/kvm/Documentation/kvm-run.txt | 48 +++++++++++++++++++++++++++++++++++
tools/kvm/command-list.txt | 5 +++
tools/kvm/util/generate-cmdlist.sh | 24 +++++++++++++++++
3 files changed, 77 insertions(+), 0 deletions(-)
create mode 100644 tools/kvm/Documentation/kvm-run.txt
create mode 100644 tools/kvm/command-list.txt
create mode 100755 tools/kvm/util/generate-cmdlist.sh
diff --git a/tools/kvm/Documentation/kvm-run.txt b/tools/kvm/Documentation/kvm-run.txt
new file mode 100644
index 0000000..f563898
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-run.txt
@@ -0,0 +1,48 @@
+kvm-run(1)
+================
+
+NAME
+----
+kvm-run - Start the virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'kvm run' [-k <kernel image> | --kernel <kernel image>]
+ [-d <image file> | --image <image file>]
+
+DESCRIPTION
+-----------
+The command starts a virtual machine.
+
+OPTIONS
+-------
+-m::
+--mem=::
+ Virtual machine memory size in MiB.
+
+-p::
+--params::
+ Additional kernel command line arguments.
+
+-i::
+--initrd=::
+ Initial RAM disk image.
+
+-k::
+--kernel=::
+ The virtual machine kernel.
+
+-d::
+--image=::
+ A disk image file.
+
+-s::
+--single-step:: Enable single stepping.
+
+-g::
+--ioport-debug:: Enable ioport debugging.
+
+SEE ALSO
+--------
+linkkvm:
diff --git a/tools/kvm/command-list.txt b/tools/kvm/command-list.txt
new file mode 100644
index 0000000..4eaf399
--- /dev/null
+++ b/tools/kvm/command-list.txt
@@ -0,0 +1,5 @@
+#
+# List of known perf commands.
+# command name category [deprecated] [common]
+#
+kvm-run mainporcelain common
diff --git a/tools/kvm/util/generate-cmdlist.sh b/tools/kvm/util/generate-cmdlist.sh
new file mode 100755
index 0000000..c3fd172
--- /dev/null
+++ b/tools/kvm/util/generate-cmdlist.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+echo "/* Automatically generated by $0 */
+struct cmdname_help
+{
+ char name[16];
+ char help[80];
+};
+
+static struct cmdname_help common_cmds[] = {"
+
+sed -n 's/^kvm-\([^ \t]*\).*common/\1/p' command-list.txt |
+sort |
+while read cmd
+do
+ # TODO following sed command should be fixed
+ sed -n '/^NAME/,/^kvm-'"$cmd"'/ {
+ /NAME/d
+ /--/d
+ s/.*kvm-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/
+ p
+ }' "Documentation/kvm-$cmd.txt"
+done
+echo "};"
--
1.7.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/4] Mostly the copied code from perf for argument processing
2011-04-07 19:47 [PATCH 1/4] Generating list of common kvm tool commands Prasad Joshi
@ 2011-04-07 19:47 ` Prasad Joshi
2011-04-07 20:17 ` David Ahern
2011-04-07 19:47 ` [PATCH 3/4] Provides the basic Gitish framework Prasad Joshi
2011-04-07 19:47 ` [PATCH 4/4] Using the Gitish freamwork to run the virtual machine Prasad Joshi
2 siblings, 1 reply; 11+ messages in thread
From: Prasad Joshi @ 2011-04-07 19:47 UTC (permalink / raw)
To: prasadjoshi124
Cc: mingo, kvm, penberg, asias.hejun, gorcunov, oswaldo.cadenas
- parse-options.[ch] has argument processing code.
- types.h: Additional types for argument processing.
- strbuf.[ch]: Added a function prefixcmp to compare string prefix
Signed-off-by: Prasad Joshi <prasadjoshi124@gmail.com>
---
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;
+ }
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/4] Provides the basic Gitish framework
2011-04-07 19:47 [PATCH 1/4] Generating list of common kvm tool commands Prasad Joshi
2011-04-07 19:47 ` [PATCH 2/4] Mostly the copied code from perf for argument processing Prasad Joshi
@ 2011-04-07 19:47 ` Prasad Joshi
2011-04-07 20:14 ` Ingo Molnar
2011-04-07 19:47 ` [PATCH 4/4] Using the Gitish freamwork to run the virtual machine Prasad Joshi
2 siblings, 1 reply; 11+ messages in thread
From: Prasad Joshi @ 2011-04-07 19:47 UTC (permalink / raw)
To: prasadjoshi124
Cc: mingo, kvm, penberg, asias.hejun, gorcunov, oswaldo.cadenas
- kvm-cmd.h: Adds a new structure cmd_struct to create a table of commands
and callback function.
- kvm-cmd.c: implements two main functions for command processing.
kvm_get_command(): searches table for specific command.
handle_command(): invokes the callback function for a given command.
- kvm-help.[ch] Implements the kvm help command.
Signed-off-by: Prasad Joshi <prasadjoshi124@gmail.com>
---
tools/kvm/include/kvm/kvm-cmd.h | 12 ++++++++
tools/kvm/include/kvm/kvm-help.h | 6 ++++
tools/kvm/kvm-cmd.c | 55 ++++++++++++++++++++++++++++++++++++++
tools/kvm/kvm-help.c | 43 +++++++++++++++++++++++++++++
4 files changed, 116 insertions(+), 0 deletions(-)
create mode 100644 tools/kvm/include/kvm/kvm-cmd.h
create mode 100644 tools/kvm/include/kvm/kvm-help.h
create mode 100644 tools/kvm/kvm-cmd.c
create mode 100644 tools/kvm/kvm-help.c
diff --git a/tools/kvm/include/kvm/kvm-cmd.h b/tools/kvm/include/kvm/kvm-cmd.h
new file mode 100644
index 0000000..8d5fca5
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm-cmd.h
@@ -0,0 +1,12 @@
+#ifndef __KVM_CMD_H__
+#define __KVM_CMD_H__
+
+struct cmd_struct {
+ const char *cmd;
+ int (*fn)(int, const char **, const char *);
+ int option;
+};
+
+int handle_command(struct cmd_struct *command, int argc, const char **argv);
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm-help.h b/tools/kvm/include/kvm/kvm-help.h
new file mode 100644
index 0000000..2946743
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm-help.h
@@ -0,0 +1,6 @@
+#ifndef __KVM_HELP_H__
+#define __KVM_HELP_H__
+
+int kvm_cmd_help(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/kvm-cmd.c b/tools/kvm/kvm-cmd.c
new file mode 100644
index 0000000..ef9a454
--- /dev/null
+++ b/tools/kvm/kvm-cmd.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <assert.h>
+
+/* user defined header files */
+#include <kvm/kvm-cmd.h>
+
+/* kvm_get_command: Searches the command in an array of the commands and
+ returns a pointer to cmd_struct if a match is found.
+
+ Input parameters:
+ command: Array of possible commands. The last entry in the array must be
+ NULL.
+ cmd: A string command to search in the array
+
+ Return Value:
+ NULL: If the cmd is not matched with any of the command in the command array
+ p: Pointer to cmd_struct of the matching command
+ */
+static struct cmd_struct *kvm_get_command(struct cmd_struct *command,
+ const char *cmd)
+{
+ struct cmd_struct *p = command;
+
+ while (p->cmd) {
+ if (!strcmp(p->cmd, cmd))
+ return p;
+ p++;
+ }
+ return NULL;
+}
+
+int handle_command(struct cmd_struct *command, int argc, const char **argv)
+{
+ struct cmd_struct *p;
+ const char *prefix = NULL;
+
+ if (!argv || !*argv) {
+ p = kvm_get_command(command, "help");
+ assert(p);
+ return p->fn(argc, argv, prefix);
+ }
+
+ p = kvm_get_command(command, argv[0]);
+ if (!p) {
+ p = kvm_get_command(command, "help");
+ assert(p);
+ p->fn(argc, argv, prefix);
+ return EINVAL;
+ }
+
+ return p->fn(argc - 1, &argv[1], prefix);
+}
diff --git a/tools/kvm/kvm-help.c b/tools/kvm/kvm-help.c
new file mode 100644
index 0000000..fd133a9
--- /dev/null
+++ b/tools/kvm/kvm-help.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <string.h>
+
+/* user defined headers */
+#include <common-cmds.h>
+
+#include <kvm/util.h>
+#include <kvm/kvm-help.h>
+
+
+const char kvm_usage_string[] =
+ "kvm [--version] [--help] COMMAND [ARGS]";
+
+const char kvm_more_info_string[] =
+ "See 'kvm help COMMAND' for more information on a specific command.";
+
+
+static void list_common_cmds_help(void)
+{
+ unsigned int i, longest = 0;
+
+ for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
+ if (longest < strlen(common_cmds[i].name))
+ longest = strlen(common_cmds[i].name);
+ }
+
+ puts(" The most commonly used kvm commands are:");
+ for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
+ printf(" %-*s ", longest, common_cmds[i].name);
+ puts(common_cmds[i].help);
+ }
+}
+
+int kvm_cmd_help(int argc, const char **argv, const char *prefix)
+{
+ if (!argv || !*argv) {
+ printf("\n usage: %s\n\n", kvm_usage_string);
+ list_common_cmds_help();
+ printf("\n %s\n\n", kvm_more_info_string);
+ return 0;
+ }
+ return 0;
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/4] Using the Gitish freamwork to run the virtual machine
2011-04-07 19:47 [PATCH 1/4] Generating list of common kvm tool commands Prasad Joshi
2011-04-07 19:47 ` [PATCH 2/4] Mostly the copied code from perf for argument processing Prasad Joshi
2011-04-07 19:47 ` [PATCH 3/4] Provides the basic Gitish framework Prasad Joshi
@ 2011-04-07 19:47 ` Prasad Joshi
2 siblings, 0 replies; 11+ messages in thread
From: Prasad Joshi @ 2011-04-07 19:47 UTC (permalink / raw)
To: prasadjoshi124
Cc: mingo, kvm, penberg, asias.hejun, gorcunov, oswaldo.cadenas
- kvm-run.[ch] Adds a new kvm command called 'run'. The most of the code is
copied from main.c.
- main.c is modified to use the functionality provided by framework.
The old code from main.c is moved to kvm-run.c.
Signed-off-by: Prasad Joshi <prasadjoshi124@gmail.com>
---
tools/kvm/Makefile | 19 +++-
tools/kvm/include/kvm/kvm-run.h | 6 +
tools/kvm/kvm-run.c | 231 +++++++++++++++++++++++++++++++++++++
tools/kvm/main.c | 243 ++-------------------------------------
4 files changed, 267 insertions(+), 232 deletions(-)
create mode 100644 tools/kvm/include/kvm/kvm-run.h
create mode 100644 tools/kvm/kvm-run.c
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 747aa51..3224cee 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -24,6 +24,11 @@ OBJS += main.o
OBJS += mmio.o
OBJS += pci.o
OBJS += util.o
+OBJS += util/parse-options.o
+OBJS += util/strbuf.o
+OBJS += kvm-help.o
+OBJS += kvm-cmd.o
+OBJS += kvm-run.o
DEPS := $(patsubst %.o,%.d,$(OBJS))
@@ -53,7 +58,8 @@ endif
DEFINES += -D_FILE_OFFSET_BITS=64
DEFINES += -D_GNU_SOURCE
-CFLAGS += $(CPPFLAGS) $(DEFINES) -Iinclude -I../../include -I../../arch/$(ARCH)/include/ -Os -g
+KVM_INCLUDE := include
+CFLAGS += $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -Os -g
WARNINGS += -Werror
WARNINGS += -Wall
@@ -85,12 +91,22 @@ $(DEPS):
%.d: %.c
$(Q) $(CC) -M -MT $(patsubst %.d,%.o,$@) $(CFLAGS) $< -o $@
+# The header file common-cmds.h is needed for compilation of kvm-help.c.
+kvm-help.d: $(KVM_INCLUDE)/common-cmds.h
+
$(OBJS):
%.o: %.c
$(E) " CC " $@
$(Q) $(CC) -c $(CFLAGS) $< -o $@
+
+$(KVM_INCLUDE)/common-cmds.h: util/generate-cmdlist.sh command-list.txt
+
+$(KVM_INCLUDE)/common-cmds.h: $(wildcard Documentation/kvm-*.txt)
+ $(E) " GEN " $@
+ $(Q) util/generate-cmdlist.sh > $@+ && mv $@+ $@
+
#
# BIOS assembly weirdness
#
@@ -127,6 +143,7 @@ clean:
$(Q) rm -f bios/bios-rom.h
$(Q) rm -f $(DEPS) $(OBJS) $(PROGRAM)
$(Q) rm -f cscope.*
+ $(Q) rm -f $(KVM_INCLUDE)/common-cmds.h
.PHONY: clean
KVM_DEV ?= /dev/kvm
diff --git a/tools/kvm/include/kvm/kvm-run.h b/tools/kvm/include/kvm/kvm-run.h
new file mode 100644
index 0000000..13104e2
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm-run.h
@@ -0,0 +1,6 @@
+#ifndef __KVM_RUN_H__
+#define __KVM_RUN_H__
+
+int kvm_cmd_run(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
new file mode 100644
index 0000000..832e811
--- /dev/null
+++ b/tools/kvm/kvm-run.c
@@ -0,0 +1,231 @@
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <termios.h>
+
+/* user defined header files */
+#include <linux/types.h>
+#include <kvm/kvm.h>
+#include <kvm/8250-serial.h>
+#include <kvm/blk-virtio.h>
+#include <kvm/disk-image.h>
+#include <kvm/util.h>
+#include <kvm/pci.h>
+
+/* header files for gitish interface */
+#include <kvm/kvm-run.h>
+#include <kvm/parse-options.h>
+
+#define MB_SHIFT (20)
+#define MIN_RAM_SIZE_MB (64UL)
+#define MIN_RAM_SIZE_BYTE (MIN_RAM_SIZE_MB << MB_SHIFT)
+
+static struct kvm *kvm;
+static struct termios orig_term;
+
+static void setup_console(void)
+{
+ struct termios term;
+
+ if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
+ die("unable to save initial standard input settings");
+
+ term = orig_term;
+
+ term.c_lflag &= ~(ICANON|ECHO);
+
+ tcsetattr(STDIN_FILENO, TCSANOW, &term);
+}
+
+static void cleanup_console(void)
+{
+ tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
+}
+
+static void shutdown(void)
+{
+ cleanup_console();
+}
+
+static void handle_sigint(int sig)
+{
+ exit(1);
+}
+
+static void handle_sigquit(int sig)
+{
+ kvm__show_registers(kvm);
+ kvm__show_code(kvm);
+ kvm__show_page_tables(kvm);
+
+ kvm__delete(kvm);
+
+ exit(1);
+}
+
+static u64 ram_size;
+static const char *kernel_cmdline;
+static const char *kernel_filename;
+static const char *initrd_filename;
+static const char *image_filename;
+static bool single_step = false;
+extern bool ioport_debug;
+
+static const char * const run_usage[] = {
+ "kvm run [<options>]",
+ NULL
+};
+
+static const struct option options[] = {
+ OPT_U64('m', "mem", &ram_size, "Virtual machine memory size in MiB."),
+ OPT_STRING('p', "params", &kernel_cmdline, "params",
+ "Kernel command line arguments"),
+ OPT_STRING('i', "initrd", &initrd_filename, "initrd",
+ "Initial RAM disk image"),
+ OPT_STRING('k', "kernel", &kernel_filename, "kernel",
+ "Kernel to boot in virtual machine"),
+ OPT_STRING('d', "image", &image_filename, "image", "Disk image"),
+ OPT_BOOLEAN('s', "single-step", &single_step, "Enable single stepping"),
+ OPT_BOOLEAN('g', "ioport-debug", &ioport_debug,
+ "Enable ioport debugging"),
+ OPT_END()
+};
+
+int kvm_cmd_run(int argc, const char **argv, const char *prefix)
+{
+ const char *kvm_dev = "/dev/kvm";
+ static char real_cmdline[2048];
+
+ argc = parse_options(argc, argv, options, run_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ if (!argc && (!kernel_filename || !image_filename)) {
+ /* no argument specified or manadatory argument not specified
+ display the usage message
+ */
+ usage_with_options(run_usage, options);
+ }
+
+ if (ram_size < MIN_RAM_SIZE_MB) {
+ die("Not enough memory specified: %luMB (min %luMB)", ram_size,
+ MIN_RAM_SIZE_MB);
+ }
+ ram_size <<= MB_SHIFT;
+
+ signal(SIGQUIT, handle_sigquit);
+ signal(SIGINT, handle_sigint);
+
+ setup_console();
+
+ atexit(shutdown);
+
+
+ kvm = kvm__init(kvm_dev, ram_size);
+
+ if (image_filename) {
+ kvm->disk_image = disk_image__open(image_filename);
+ if (!kvm->disk_image)
+ die("unable to load disk image %s", image_filename);
+ }
+
+ kvm__setup_cpuid(kvm);
+
+ strcpy(real_cmdline, "notsc nolapic noacpi pci=conf1 console=ttyS0 ");
+ if (!kernel_cmdline || !strstr(kernel_cmdline, "root=")) {
+ strlcat(real_cmdline, "root=/dev/vda rw ",
+ sizeof(real_cmdline));
+ }
+
+ if (kernel_cmdline) {
+ strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline));
+ real_cmdline[sizeof(real_cmdline)-1] = '\0';
+ }
+
+ if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename,
+ real_cmdline))
+ die("unable to load kernel %s", kernel_filename);
+
+ kvm__reset_vcpu(kvm);
+
+ kvm__setup_bios(kvm);
+
+ if (single_step)
+ kvm__enable_singlestep(kvm);
+
+ serial8250__init(kvm);
+ pci__init();
+
+ blk_virtio__init(kvm);
+
+ kvm__start_timer(kvm);
+
+ for (;;) {
+ kvm__run(kvm);
+
+ switch (kvm->kvm_run->exit_reason) {
+ case KVM_EXIT_DEBUG:
+ kvm__show_registers(kvm);
+ kvm__show_code(kvm);
+ break;
+ case KVM_EXIT_IO: {
+ bool ret;
+
+ ret = kvm__emulate_io(kvm,
+ kvm->kvm_run->io.port,
+ (uint8_t *)kvm->kvm_run +
+ kvm->kvm_run->io.data_offset,
+ kvm->kvm_run->io.direction,
+ kvm->kvm_run->io.size,
+ kvm->kvm_run->io.count);
+
+ if (!ret)
+ goto panic_kvm;
+ break;
+ }
+ case KVM_EXIT_MMIO: {
+ bool ret;
+
+ ret = kvm__emulate_mmio(kvm,
+ kvm->kvm_run->mmio.phys_addr,
+ kvm->kvm_run->mmio.data,
+ kvm->kvm_run->mmio.len,
+ kvm->kvm_run->mmio.is_write);
+
+ if (!ret)
+ goto panic_kvm;
+ break;
+ }
+ case KVM_EXIT_INTR: {
+ serial8250__interrupt(kvm);
+ break;
+ }
+ case KVM_EXIT_SHUTDOWN:
+ goto exit_kvm;
+ default:
+ goto panic_kvm;
+ }
+ }
+exit_kvm:
+ disk_image__close(kvm->disk_image);
+ kvm__delete(kvm);
+
+ return 0;
+
+panic_kvm:
+ fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n",
+ kvm->kvm_run->exit_reason,
+ kvm_exit_reasons[kvm->kvm_run->exit_reason]);
+ if (kvm->kvm_run->exit_reason == KVM_EXIT_UNKNOWN)
+ fprintf(stderr, "KVM exit code: 0x%" PRIu64 "\n",
+ kvm->kvm_run->hw.hardware_exit_reason);
+ disk_image__close(kvm->disk_image);
+ kvm__show_registers(kvm);
+ kvm__show_code(kvm);
+ kvm__show_page_tables(kvm);
+ kvm__delete(kvm);
+
+ return 1;
+}
diff --git a/tools/kvm/main.c b/tools/kvm/main.c
index 7beb6a6..4fbb268 100644
--- a/tools/kvm/main.c
+++ b/tools/kvm/main.c
@@ -1,241 +1,22 @@
-#include "kvm/kvm.h"
-
-#include "kvm/8250-serial.h"
-#include "kvm/blk-virtio.h"
-#include "kvm/disk-image.h"
-#include "kvm/util.h"
-#include "kvm/pci.h"
-
-#include <inttypes.h>
-#include <termios.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
#include <stdio.h>
-extern bool ioport_debug;
-
-static void usage(char *argv[])
-{
- fprintf(stderr, " usage: %s "
- "[--single-step] [--ioport-debug] "
- "[--kvm-dev=<device>] [--mem=<size-in-MiB>] [--params=<kernel-params>] "
- "[--initrd=<initrd>] [--kernel=]<kernel-image> [--image=]<disk-image>\n",
- argv[0]);
- exit(1);
-}
-
-static struct kvm *kvm;
-
-static struct termios orig_term;
-
-static void setup_console(void)
-{
- struct termios term;
-
- if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
- die("unable to save initial standard input settings");
-
- term = orig_term;
-
- term.c_lflag &= ~(ICANON|ECHO);
-
- tcsetattr(STDIN_FILENO, TCSANOW, &term);
-}
+/* user defined header files */
+#include <kvm/kvm-cmd.h>
+#include <kvm/kvm-help.h>
+#include <kvm/kvm-run.h>
-static void cleanup_console(void)
+static int handle_kvm_command(int argc, char **argv)
{
- tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
-}
-
-static void shutdown(void)
-{
- cleanup_console();
-}
-
-static void handle_sigint(int sig)
-{
- exit(1);
-}
-
-static void handle_sigquit(int sig)
-{
- kvm__show_registers(kvm);
- kvm__show_code(kvm);
- kvm__show_page_tables(kvm);
-
- kvm__delete(kvm);
-
- exit(1);
-}
-
-static char real_cmdline[2048];
+ struct cmd_struct command[] = {
+ { "help", kvm_cmd_help, 0 },
+ { "run", kvm_cmd_run, 0 },
+ { NULL, NULL, 0 },
+ };
-static bool option_matches(char *arg, const char *option)
-{
- return !strncmp(arg, option, strlen(option));
+ return handle_command(command, argc, (const char **) &argv[0]);
}
int main(int argc, char *argv[])
{
- const char *kernel_filename = NULL;
- const char *initrd_filename = NULL;
- const char *image_filename = NULL;
- const char *kernel_cmdline = NULL;
- const char *kvm_dev = "/dev/kvm";
- unsigned long ram_size = 64UL << 20;
- bool single_step = false;
- int i;
-
- signal(SIGQUIT, handle_sigquit);
- signal(SIGINT, handle_sigint);
-
- setup_console();
-
- atexit(shutdown);
-
- for (i = 1; i < argc; i++) {
- if (option_matches(argv[i], "--kernel=")) {
- kernel_filename = &argv[i][9];
- continue;
- } else if (option_matches(argv[i], "--image=")) {
- image_filename = &argv[i][8];
- continue;
- } else if (option_matches(argv[i], "--initrd=")) {
- initrd_filename = &argv[i][9];
- continue;
- } else if (option_matches(argv[i], "--params=")) {
- kernel_cmdline = &argv[i][9];
- continue;
- } else if (option_matches(argv[i], "--kvm-dev=")) {
- kvm_dev = &argv[i][10];
- continue;
- } else if (option_matches(argv[i], "--single-step")) {
- single_step = true;
- continue;
- } else if (option_matches(argv[i], "--mem=")) {
- unsigned long val = atol(&argv[i][6]) << 20;
- if (val < ram_size)
- die("Not enough memory specified: %sMB (min %luMB)",
- argv[i], ram_size >> 20);
- ram_size = val;
- continue;
- } else if (option_matches(argv[i], "--ioport-debug")) {
- ioport_debug = true;
- continue;
- } else {
- /* any unspecified arg is kernel image */
- if (argv[i][0] != '-')
- kernel_filename = argv[i];
- else
- warning("Unknown option: %s", argv[i]);
- }
- }
-
- /* at least we should have kernel image passed */
- if (!kernel_filename)
- usage(argv);
-
- kvm = kvm__init(kvm_dev, ram_size);
-
- if (image_filename) {
- kvm->disk_image = disk_image__open(image_filename);
- if (!kvm->disk_image)
- die("unable to load disk image %s", image_filename);
- }
-
- kvm__setup_cpuid(kvm);
-
- strcpy(real_cmdline, "notsc nolapic noacpi pci=conf1 console=ttyS0 ");
- if (!kernel_cmdline || !strstr(kernel_cmdline, "root="))
- strlcat(real_cmdline, "root=/dev/vda rw ", sizeof(real_cmdline));
-
- if (kernel_cmdline) {
- strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline));
- real_cmdline[sizeof(real_cmdline)-1] = '\0';
- }
-
- if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename, real_cmdline))
- die("unable to load kernel %s", kernel_filename);
-
- kvm__reset_vcpu(kvm);
-
- kvm__setup_bios(kvm);
-
- if (single_step)
- kvm__enable_singlestep(kvm);
-
- serial8250__init(kvm);
- pci__init();
-
- blk_virtio__init(kvm);
-
- kvm__start_timer(kvm);
-
- for (;;) {
- kvm__run(kvm);
-
- switch (kvm->kvm_run->exit_reason) {
- case KVM_EXIT_DEBUG:
- kvm__show_registers(kvm);
- kvm__show_code(kvm);
- break;
- case KVM_EXIT_IO: {
- bool ret;
-
- ret = kvm__emulate_io(kvm,
- kvm->kvm_run->io.port,
- (uint8_t *)kvm->kvm_run + kvm->kvm_run->io.data_offset,
- kvm->kvm_run->io.direction,
- kvm->kvm_run->io.size,
- kvm->kvm_run->io.count);
-
- if (!ret)
- goto panic_kvm;
- break;
- }
- case KVM_EXIT_MMIO: {
- bool ret;
-
- ret = kvm__emulate_mmio(kvm,
- kvm->kvm_run->mmio.phys_addr,
- kvm->kvm_run->mmio.data,
- kvm->kvm_run->mmio.len,
- kvm->kvm_run->mmio.is_write);
-
- if (!ret)
- goto panic_kvm;
- break;
- }
- case KVM_EXIT_INTR: {
- serial8250__interrupt(kvm);
- break;
- }
- case KVM_EXIT_SHUTDOWN:
- goto exit_kvm;
- default:
- goto panic_kvm;
- }
- }
-exit_kvm:
- disk_image__close(kvm->disk_image);
- kvm__delete(kvm);
-
- return 0;
-
-panic_kvm:
- fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n",
- kvm->kvm_run->exit_reason, kvm_exit_reasons[kvm->kvm_run->exit_reason]);
- if (kvm->kvm_run->exit_reason == KVM_EXIT_UNKNOWN)
- fprintf(stderr, "KVM exit code: 0x%" PRIu64 "\n",
- kvm->kvm_run->hw.hardware_exit_reason);
- disk_image__close(kvm->disk_image);
- kvm__show_registers(kvm);
- kvm__show_code(kvm);
- kvm__show_page_tables(kvm);
- kvm__delete(kvm);
-
- return 1;
+ return handle_kvm_command(argc - 1, &argv[1]);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 3/4] Provides the basic Gitish framework
2011-04-07 19:47 ` [PATCH 3/4] Provides the basic Gitish framework Prasad Joshi
@ 2011-04-07 20:14 ` Ingo Molnar
2011-04-07 22:33 ` Prasad Joshi
0 siblings, 1 reply; 11+ messages in thread
From: Ingo Molnar @ 2011-04-07 20:14 UTC (permalink / raw)
To: Prasad Joshi; +Cc: kvm, penberg, asias.hejun, gorcunov, oswaldo.cadenas
* Prasad Joshi <prasadjoshi124@gmail.com> wrote:
> - kvm-cmd.h: Adds a new structure cmd_struct to create a table of commands
> and callback function.
>
> - kvm-cmd.c: implements two main functions for command processing.
> kvm_get_command(): searches table for specific command.
> handle_command(): invokes the callback function for a given command.
>
> - kvm-help.[ch] Implements the kvm help command.
Please credit the people/projects from where you took these bits.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/4] Mostly the copied code from perf for argument processing
2011-04-07 19:47 ` [PATCH 2/4] Mostly the copied code from perf for argument processing Prasad Joshi
@ 2011-04-07 20:17 ` David Ahern
2011-04-08 5:43 ` Pekka Enberg
0 siblings, 1 reply; 11+ messages in thread
From: David Ahern @ 2011-04-07 20:17 UTC (permalink / raw)
To: Prasad Joshi; +Cc: mingo, kvm, penberg, asias.hejun, gorcunov, oswaldo.cadenas
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@gmail.com>
> ---
> 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;
> + }
> +}
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/4] Provides the basic Gitish framework
2011-04-07 20:14 ` Ingo Molnar
@ 2011-04-07 22:33 ` Prasad Joshi
2011-04-08 5:44 ` Pekka Enberg
0 siblings, 1 reply; 11+ messages in thread
From: Prasad Joshi @ 2011-04-07 22:33 UTC (permalink / raw)
To: Ingo Molnar; +Cc: kvm, penberg, asias.hejun, gorcunov, oswaldo.cadenas
On Thu, Apr 7, 2011 at 9:14 PM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Prasad Joshi <prasadjoshi124@gmail.com> wrote:
>
>> - kvm-cmd.h: Adds a new structure cmd_struct to create a table of commands
>> and callback function.
>>
>> - kvm-cmd.c: implements two main functions for command processing.
>> kvm_get_command(): searches table for specific command.
>> handle_command(): invokes the callback function for a given command.
>>
>> - kvm-help.[ch] Implements the kvm help command.
>
> Please credit the people/projects from where you took these bits.
Oh yes!
struct cmd_struct and list_common_cmds_help() is copied from perf.
>
> Thanks,
>
> Ingo
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/4] Mostly the copied code from perf for argument processing
2011-04-07 20:17 ` David Ahern
@ 2011-04-08 5:43 ` Pekka Enberg
2011-04-08 6:04 ` Ingo Molnar
0 siblings, 1 reply; 11+ messages in thread
From: Pekka Enberg @ 2011-04-08 5:43 UTC (permalink / raw)
To: David Ahern
Cc: Prasad Joshi, mingo, kvm, asias.hejun, gorcunov, oswaldo.cadenas
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
On Thu, 2011-04-07 at 14:17 -0600, David Ahern wrote:
> Rather than copy perf code, how about a tools/lib?
It's a good idea but lets not do it in our tree. We're still trying to
keep things well-contained under 'tools/kvm' for merge reasons.
You could try to do the cleanup in perf tree if you're interested and
when that hits mainline, we can pull the bits from there and clean up
our tree.
Pekka
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/4] Provides the basic Gitish framework
2011-04-07 22:33 ` Prasad Joshi
@ 2011-04-08 5:44 ` Pekka Enberg
2011-04-08 6:10 ` Ingo Molnar
0 siblings, 1 reply; 11+ messages in thread
From: Pekka Enberg @ 2011-04-08 5:44 UTC (permalink / raw)
To: Prasad Joshi; +Cc: Ingo Molnar, kvm, asias.hejun, gorcunov, oswaldo.cadenas
On Thu, 2011-04-07 at 23:33 +0100, Prasad Joshi wrote:
> On Thu, Apr 7, 2011 at 9:14 PM, Ingo Molnar <mingo@elte.hu> wrote:
> >
> > * Prasad Joshi <prasadjoshi124@gmail.com> wrote:
> >
> >> - kvm-cmd.h: Adds a new structure cmd_struct to create a table of commands
> >> and callback function.
> >>
> >> - kvm-cmd.c: implements two main functions for command processing.
> >> kvm_get_command(): searches table for specific command.
> >> handle_command(): invokes the callback function for a given command.
> >>
> >> - kvm-help.[ch] Implements the kvm help command.
> >
> > Please credit the people/projects from where you took these bits.
>
> Oh yes!
> struct cmd_struct and list_common_cmds_help() is copied from perf.
Please just add that to the changelog.
Pekka
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/4] Mostly the copied code from perf for argument processing
2011-04-08 5:43 ` Pekka Enberg
@ 2011-04-08 6:04 ` Ingo Molnar
0 siblings, 0 replies; 11+ messages in thread
From: Ingo Molnar @ 2011-04-08 6:04 UTC (permalink / raw)
To: Pekka Enberg
Cc: David Ahern, Prasad Joshi, kvm, asias.hejun, gorcunov,
oswaldo.cadenas
* Pekka Enberg <penberg@kernel.org> wrote:
> 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
>
> On Thu, 2011-04-07 at 14:17 -0600, David Ahern wrote:
> > Rather than copy perf code, how about a tools/lib?
>
> It's a good idea but lets not do it in our tree. We're still trying to keep
> things well-contained under 'tools/kvm' for merge reasons.
Agreed.
> You could try to do the cleanup in perf tree if you're interested and when
> that hits mainline, we can pull the bits from there and clean up our tree.
Yes, that ordering would make sense - the perf copies of Git code are also much
more complete.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/4] Provides the basic Gitish framework
2011-04-08 5:44 ` Pekka Enberg
@ 2011-04-08 6:10 ` Ingo Molnar
0 siblings, 0 replies; 11+ messages in thread
From: Ingo Molnar @ 2011-04-08 6:10 UTC (permalink / raw)
To: Pekka Enberg; +Cc: Prasad Joshi, kvm, asias.hejun, gorcunov, oswaldo.cadenas
* Pekka Enberg <penberg@kernel.org> wrote:
> On Thu, 2011-04-07 at 23:33 +0100, Prasad Joshi wrote:
> > On Thu, Apr 7, 2011 at 9:14 PM, Ingo Molnar <mingo@elte.hu> wrote:
> > >
> > > * Prasad Joshi <prasadjoshi124@gmail.com> wrote:
> > >
> > >> - kvm-cmd.h: Adds a new structure cmd_struct to create a table of commands
> > >> and callback function.
> > >>
> > >> - kvm-cmd.c: implements two main functions for command processing.
> > >> kvm_get_command(): searches table for specific command.
> > >> handle_command(): invokes the callback function for a given command.
> > >>
> > >> - kvm-help.[ch] Implements the kvm help command.
> > >
> > > Please credit the people/projects from where you took these bits.
> >
> > Oh yes!
> > struct cmd_struct and list_common_cmds_help() is copied from perf.
>
> Please just add that to the changelog.
Yeah - and perf took it from Git :-)
The way we credited the Git project in perf was this commit:
1b173f77dd0d: perf_counter tools: Add CREDITS file for Git contributors
basically a CREDITS file for Git library contributors. If you expect to take
more bits, such as the help system (look at tools/perf/Documentation/) and
other bits, the easiest solution would be for you to take the CREDITS file and
name it CREDITS-lib or so.
This also serves as a way to grandfather in other history (and copyrights), the
exact upstream Git sha1 is mentioned. The Git project is GPLv2 as well like the
kernel and like tools/perf/, so this works out well and you do not have to
re-credit again and again so precisely, as you take more bits of Git's library
code.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2011-04-08 6:10 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-07 19:47 [PATCH 1/4] Generating list of common kvm tool commands Prasad Joshi
2011-04-07 19:47 ` [PATCH 2/4] Mostly the copied code from perf for argument processing Prasad Joshi
2011-04-07 20:17 ` David Ahern
2011-04-08 5:43 ` Pekka Enberg
2011-04-08 6:04 ` Ingo Molnar
2011-04-07 19:47 ` [PATCH 3/4] Provides the basic Gitish framework Prasad Joshi
2011-04-07 20:14 ` Ingo Molnar
2011-04-07 22:33 ` Prasad Joshi
2011-04-08 5:44 ` Pekka Enberg
2011-04-08 6:10 ` Ingo Molnar
2011-04-07 19:47 ` [PATCH 4/4] Using the Gitish freamwork to run the virtual machine Prasad Joshi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox