All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: Markus Armbruster <armbru@redhat.com>
Cc: amit.shah@redhat.com, Gerd Hoffmann <kraxel@redhat.com>,
	Brad Hards <bradh@frogmouth.net>,
	qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] qdev device documentation (Re: [PATCH 0/2] usb-linux: physical port handling.)
Date: Fri, 13 May 2011 09:30:09 -0500	[thread overview]
Message-ID: <4DCD4071.4040403@codemonkey.ws> (raw)
In-Reply-To: <m3zkmryrvx.fsf@blackfin.pond.sub.org>

[-- Attachment #1: Type: text/plain, Size: 496 bytes --]

On 05/13/2011 02:35 AM, Markus Armbruster wrote:
> Anthony Liguori<anthony@codemonkey.ws>  writes:
>
>> That's fine.  But what better way to ensure a consistent and stable UI
>> than having it centralized in one place.
>
> Consistent, stable, and bit-rotten.  Unless you come up with a way to
> catch bit-rot immediately.  That means on "make", not on "make docs".
>
> Extra points if the error message points right to the offending source
> line.

Er, hit send too fast.  Here's the next patch.

[-- Attachment #2: 0001-qdev-add-centralized-documentation-for-qdev-v2.patch --]
[-- Type: text/x-patch, Size: 9450 bytes --]

>From f5c30c922ce1cf755ef78887f4015c131d8d6841 Mon Sep 17 00:00:00 2001
From: Anthony Liguori <aliguori@us.ibm.com>
Date: Thu, 12 May 2011 10:56:29 -0500
Subject: [PATCH 1/1] qdev: add centralized documentation for qdev (v2)

This adds a -qdev-verify option that will confirm that the documentation matches
the code.  It returns a non-zero exit status if any errors are detected.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 Makefile                    |    2 +
 Makefile.doc                |    5 ++
 Makefile.objs               |    2 +-
 qdev-doc.h                  |   23 +++++++++++
 qdev-doc.json               |   16 ++++++++
 qemu-options.hx             |   10 +++++
 scripts/qdev-doc-to-c.py    |   30 ++++++++++++++
 scripts/qdev-doc-to-html.py |   40 +++++++++++++++++++
 vl.c                        |   89 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 216 insertions(+), 1 deletions(-)
 create mode 100644 Makefile.doc
 create mode 100644 qdev-doc.h
 create mode 100644 qdev-doc.json
 create mode 100644 scripts/qdev-doc-to-c.py
 create mode 100644 scripts/qdev-doc-to-html.py

diff --git a/Makefile b/Makefile
index 2b0438c..fddb261 100644
--- a/Makefile
+++ b/Makefile
@@ -341,5 +341,7 @@ tarbin:
 	$(mandir)/man1/qemu-img.1 \
 	$(mandir)/man8/qemu-nbd.8
 
+include $(SRC_PATH)/Makefile.doc
+
 # Include automatically generated dependency files
 -include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d)
diff --git a/Makefile.doc b/Makefile.doc
new file mode 100644
index 0000000..c1cf74a
--- /dev/null
+++ b/Makefile.doc
@@ -0,0 +1,5 @@
+qdev-doc.html: $(SRC_PATH)/qdev-doc.json $(SRC_PATH)/scripts/qdev-doc-to-html.py
+	python $(SRC_PATH)/scripts/qdev-doc-to-html.py < $< > $@
+
+qdev-doc.c: $(SRC_PATH)/qdev-doc.json $(SRC_PATH)/scripts/qdev-doc-to-c.py
+	python $(SRC_PATH)/scripts/qdev-doc-to-c.py < $< > $@
diff --git a/Makefile.objs b/Makefile.objs
index 4478c61..9547ab1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -97,7 +97,7 @@ common-obj-y += bt-hci-csr.o
 common-obj-y += buffered_file.o migration.o migration-tcp.o
 common-obj-y += qemu-char.o savevm.o #aio.o
 common-obj-y += msmouse.o ps2.o
-common-obj-y += qdev.o qdev-properties.o
+common-obj-y += qdev.o qdev-properties.o qdev-doc.o
 common-obj-y += block-migration.o iohandler.o
 common-obj-y += pflib.o
 common-obj-y += bitmap.o bitops.o
diff --git a/qdev-doc.h b/qdev-doc.h
new file mode 100644
index 0000000..401e03e
--- /dev/null
+++ b/qdev-doc.h
@@ -0,0 +1,23 @@
+#ifndef QDEV_DOC_H
+#define QDEV_DOC_H
+
+#include "qemu-common.h"
+
+typedef struct PropertyDocumentation
+{
+    const char *name;
+    const char *type;
+    const char *docs;
+} PropertyDocumentation;
+
+typedef struct DeviceStateDocumentation
+{
+    const char *name;
+    PropertyDocumentation *properties;
+} DeviceStateDocumentation;
+
+extern DeviceStateDocumentation device_docs[];
+
+bool qdev_verify_docs(void);
+
+#endif
diff --git a/qdev-doc.json b/qdev-doc.json
new file mode 100644
index 0000000..a798bff
--- /dev/null
+++ b/qdev-doc.json
@@ -0,0 +1,16 @@
+# -*- Mode: Python -*-
+
+[ { "device": "isa-serial",
+    "parent": "ISADevice",
+    "properties": {
+            "index": { "type": "uint32",
+                       "doc": "A value from 0-3 that describes which IO regions to expose the device on.  This sets appropriate values for iobase and irq." },
+            "iobase": { "type": "hex32",
+                        "doc": "The base IO address to expose the device on." },
+            "irq": { "type": "uint32",
+                     "doc": "The IRQ to use for the device." },
+            "chardev": { "type": "chr",
+                         "doc": "The name of a character device to specify." }
+            }
+  }
+  ]
diff --git a/qemu-options.hx b/qemu-options.hx
index 9f121ad..a6abab4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2378,6 +2378,16 @@ Specify a trace file to log output traces to.
 ETEXI
 #endif
 
+DEF("qdev-verify", 0, QEMU_OPTION_qdev_verify,
+    "-qdev-verify\n"
+    "                Verify qdev properties match documentation\n",
+    QEMU_ARCH_ALL)
+STEXI
+@item -qdev-verify
+@findex -qdev-verify
+Verify qdev properties match documentation.
+ETEXI
+
 HXCOMM This is the last statement. Insert new options before this line!
 STEXI
 @end table
diff --git a/scripts/qdev-doc-to-c.py b/scripts/qdev-doc-to-c.py
new file mode 100644
index 0000000..eb7ee59
--- /dev/null
+++ b/scripts/qdev-doc-to-c.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+
+import sys
+
+data = sys.stdin.read()
+
+docs = eval(data)
+
+sys.stdout.write('''
+#include "qdev-doc.h"
+
+DeviceStateDocumentation device_docs[] = {''')
+
+for item in docs:
+    sys.stdout.write('''
+    {
+      .name = "%(device)s",
+      .properties = (PropertyDocumentation[]){''' % item)
+    for prop in item["properties"]:
+        sys.stdout.write('''
+        { "%s", "%s", "%s" },''' % (prop, item["properties"][prop]['type'], item["properties"][prop]['doc']))
+
+    sys.stdout.write('''
+        { } },
+    },''')
+
+sys.stdout.write('''
+    { }
+};
+''')
diff --git a/scripts/qdev-doc-to-html.py b/scripts/qdev-doc-to-html.py
new file mode 100644
index 0000000..a25fe35
--- /dev/null
+++ b/scripts/qdev-doc-to-html.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+
+import sys
+
+data = sys.stdin.read()
+
+docs = eval(data)
+
+sys.stdout.write('''
+<html>
+<head>
+<title>QEMU device documentation</title>
+</head>
+<body>
+''')
+
+for item in docs:
+    sys.stdout.write('''
+<h2>%(device)s :: %(parent)s</h2>
+
+<table border="1">
+<tr>
+<th>Name</th><th>Type</th><th>Comments</th>
+</tr>
+''' % item)
+    for prop in item["properties"]:
+        sys.stdout.write('''
+<tr>
+<td>%s</td><td>%s</td><td>%s</td>
+</tr>
+''' % (prop, item["properties"][prop]['type'], item["properties"][prop]['doc']))
+
+    sys.stdout.write('''
+</table>
+''')
+
+sys.stdout.write('''
+</body>
+</html>
+''')
diff --git a/vl.c b/vl.c
index bffba69..b9f6e63 100644
--- a/vl.c
+++ b/vl.c
@@ -163,6 +163,8 @@ int main(int argc, char **argv)
 
 #include "ui/qemu-spice.h"
 
+#include "qdev-doc.h"
+
 //#define DEBUG_NET
 //#define DEBUG_SLIRP
 
@@ -1298,6 +1300,82 @@ void qemu_system_vmstop_request(int reason)
     qemu_notify_event();
 }
 
+bool qdev_verify_docs(void)
+{
+    DeviceStateDocumentation *doc;
+    DeviceInfo *dev;
+    int errors = 0;
+    int warnings = 0;
+
+    for (dev = device_info_list; dev; dev = dev->next) {
+        PropertyDocumentation *prop_doc;
+        Property *prop;
+
+        for (doc = device_docs; doc->name; doc++) {
+            if (strcmp(doc->name, dev->name) == 0) {
+                break;
+            }
+        }
+
+        if (doc->name == NULL) {
+            fprintf(stderr, "Warning: device `%s' is undocumented\n",
+                    dev->name);
+            warnings++;
+            continue;
+        }
+
+        for (prop = dev->props; prop->name; prop++) {
+            for (prop_doc = doc->properties; prop_doc->name; prop_doc++) {
+                if (strcmp(prop->name, prop_doc->name) == 0) {
+                    break;
+                }
+            }
+
+            if (prop_doc->name == NULL) {
+                fprintf(stderr, "Warning: device `%s' has undocumented property `%s'\n",
+                        dev->name, prop->name);
+                warnings++;
+            }
+        }
+
+        for (prop_doc = doc->properties; prop_doc->name; prop_doc++) {
+            for (prop = dev->props; prop->name; prop++) {
+                if (strcmp(prop->name, prop_doc->name) == 0) {
+                    break;
+                }
+            }
+
+            if (prop->name == NULL) {
+                fprintf(stderr, "Error: device `%s' has documented property `%s' with no definition\n",
+                        dev->name, prop_doc->name);
+                errors++;
+            }
+        }
+    }
+
+    for (doc = device_docs; doc->name; doc++) {
+        for (dev = device_info_list; dev; dev = dev->next) {
+            if (strcmp(doc->name, dev->name) == 0) {
+                break;
+            }
+        }
+
+        if (dev == NULL) {
+            fprintf(stderr, "Error: documented device `%s' has no definition\n",
+                    doc->name);
+            errors++;
+        }
+    }
+
+    fprintf(stderr, "%d warnings, %d errors.\n", warnings, errors);
+
+    if (errors > 0) {
+        return true;
+    }
+
+    return false;
+}
+
 void main_loop_wait(int nonblocking)
 {
     fd_set rfds, wfds, xfds;
@@ -2057,6 +2135,7 @@ int main(int argc, char **argv, char **envp)
 #endif
     int defconfig = 1;
     const char *trace_file = NULL;
+    bool do_qdev_verify = false;
 
     atexit(qemu_run_exit_notifiers);
     error_set_progname(argv[0]);
@@ -2890,6 +2969,9 @@ int main(int argc, char **argv, char **envp)
                     fclose(fp);
                     break;
                 }
+            case QEMU_OPTION_qdev_verify:
+                do_qdev_verify = true;
+                break;
             default:
                 os_parse_cmd_args(popt->index, optarg);
             }
@@ -3136,6 +3218,13 @@ int main(int argc, char **argv, char **envp)
 
     module_call_init(MODULE_INIT_DEVICE);
 
+    if (do_qdev_verify) {
+        if (qdev_verify_docs()) {
+            exit(1);
+        }
+        exit(0);
+    }
+
     if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, 0) != 0)
         exit(0);
 
-- 
1.7.4.1


  parent reply	other threads:[~2011-05-13 14:30 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-10 10:30 [Qemu-devel] [PATCH 0/2] usb-linux: physical port handling Gerd Hoffmann
2011-05-10 10:30 ` [Qemu-devel] [PATCH 1/2] usb-linux: fix device path aka " Gerd Hoffmann
2011-05-11  8:52   ` Markus Armbruster
2011-05-12  9:17     ` Gerd Hoffmann
2011-05-10 10:30 ` [Qemu-devel] [PATCH 2/2] usb-linux: add hostport property Gerd Hoffmann
2011-05-10 14:24 ` [Qemu-devel] [PATCH 0/2] usb-linux: physical port handling Brad Hards
2011-05-12  9:25   ` [Qemu-devel] qdev device documentation (Re: [PATCH 0/2] usb-linux: physical port handling.) Gerd Hoffmann
2011-05-12 11:09     ` Markus Armbruster
2011-05-12 15:25       ` Gerd Hoffmann
2011-05-12 15:35         ` Anthony Liguori
2011-05-12 16:08           ` Markus Armbruster
2011-05-12 16:23             ` Anthony Liguori
2011-05-12 17:58               ` Markus Armbruster
2011-05-12 18:07                 ` Anthony Liguori
2011-05-13  7:35                   ` Markus Armbruster
2011-05-13 14:29                     ` Anthony Liguori
2011-05-13 14:30                     ` Anthony Liguori [this message]
2011-05-12 18:15                 ` Peter Maydell
2011-05-12 19:32                   ` Alon Levy
2011-05-12 20:08                     ` Anthony Liguori
2011-05-13  7:13                   ` Markus Armbruster
2011-05-12 15:56         ` Markus Armbruster
2011-05-12 16:05           ` Anthony Liguori
2011-05-12 15:58         ` Anthony Liguori
2011-05-12 16:18           ` Markus Armbruster
2011-05-12 16:25             ` Anthony Liguori
2011-05-12 18:00               ` Markus Armbruster
2011-05-12 17:21             ` Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DCD4071.4040403@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=amit.shah@redhat.com \
    --cc=armbru@redhat.com \
    --cc=bradh@frogmouth.net \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.