qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/4] Add qapi doc generation scripts
@ 2016-09-22 15:58 Marc-André Lureau
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 1/4] qapi: add qapi2texi script Marc-André Lureau
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Marc-André Lureau @ 2016-09-22 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Hi,

Add the qapi2texi script and a few optional targets to excercie the
generator. The documentation isn't complete yet, so don't bother to
build it by default or install it.

Marc-André Lureau (4):
  qapi: add qapi2texi script
  qapi: fix schema symbol sections
  docs: add qapi texi template
  build-sys: add qapi doc generation targets

 Makefile                        |  15 ++
 scripts/qapi.py                 |  90 +++++++++++-
 scripts/qapi2texi.py            | 307 ++++++++++++++++++++++++++++++++++++++++
 docs/qapi-code-gen.txt          |  44 ++++--
 docs/qemu-ga-qapi.template.texi |  58 ++++++++
 docs/qemu-qapi.template.texi    | 148 +++++++++++++++++++
 docs/qmp-intro.txt              |  87 ------------
 qapi-schema.json                |   9 +-
 qapi/block-core.json            |   1 +
 qga/qapi-schema.json            |   3 +
 10 files changed, 661 insertions(+), 101 deletions(-)
 create mode 100755 scripts/qapi2texi.py
 create mode 100644 docs/qemu-ga-qapi.template.texi
 create mode 100644 docs/qemu-qapi.template.texi
 delete mode 100644 docs/qmp-intro.txt

-- 
2.10.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 1/4] qapi: add qapi2texi script
  2016-09-22 15:58 [Qemu-devel] [PATCH 0/4] Add qapi doc generation scripts Marc-André Lureau
@ 2016-09-22 15:58 ` Marc-André Lureau
  2016-09-22 16:25   ` Eric Blake
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 2/4] qapi: fix schema symbol sections Marc-André Lureau
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Marc-André Lureau @ 2016-09-22 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

As the name suggests, the qapi2texi script converts JSON QAPI
description into a standalone texi file suitable for different target
formats.

It parses the following kind of blocks with some little variations:

  ##
  # = Section
  # == Subsection
  #
  # Some text foo with *emphasis*
  # 1. with a list
  # 2. like that
  #
  # And some code:
  # | $ echo foo
  # | <- do this
  # | -> get that
  #
  ##

  ##
  # @symbol
  #
  # Symbol body ditto ergo sum. Foo bar
  # baz ding.
  #
  # @arg: foo
  # @arg: #optional foo
  #
  # Returns: returns bla bla
  #
  #          Or bla blah
  #
  # Since: version
  # Notes: notes, comments can have
  #        - itemized list
  #        - like this
  #
  #        and continue...
  #
  # Example:
  #
  # -> { "execute": "quit" }
  # <- { "return": {} }
  #
  ##

Thanks to the json declaration, it's able to give extra information
about the type of arguments and return value expected.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi.py        |  90 ++++++++++++++-
 scripts/qapi2texi.py   | 307 +++++++++++++++++++++++++++++++++++++++++++++++++
 docs/qapi-code-gen.txt |  44 +++++--
 3 files changed, 429 insertions(+), 12 deletions(-)
 create mode 100755 scripts/qapi2texi.py

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 21bc32f..7c14773 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -122,6 +122,69 @@ class QAPIExprError(Exception):
             "%s:%d: %s" % (self.info['file'], self.info['line'], self.msg)
 
 
+class QAPIDoc:
+    def __init__(self, comment):
+        self.symbol = None
+        self.comment = ""
+        self.args = OrderedDict()
+        self.meta = OrderedDict()
+        self.section = None
+
+        for line in comment.split('\n'):
+            sline = ' '.join(line.split())
+            split = sline.split(' ', 1)
+            key = split[0].rstrip(':')
+
+            if line.startswith(" @"):
+                key = key[1:]
+                sline = split[1] if len(split) > 1 else ""
+                if self.symbol is None:
+                    self.symbol = key
+                else:
+                    self.start_section(self.args, key)
+            elif self.symbol and \
+                    key in ("Since", "Returns",
+                            "Note", "Notes",
+                            "Example", "Examples"):
+                sline = split[1] if len(split) > 1 else ""
+                line = None
+                self.start_section(self.meta, key)
+
+            if self.section and self.section[1] in ("Example", "Examples"):
+                self.append_comment(line)
+            else:
+                self.append_comment(sline)
+
+        self.end_section()
+
+    def append_comment(self, line):
+        if line is None:
+            return
+        if self.section is not None:
+            if self.section[-1] == "" and line == "":
+                self.end_section()
+            else:
+                self.section.append(line)
+        elif self.comment == "":
+            self.comment = line
+        else:
+            self.comment += "\n" + line
+
+    def end_section(self):
+        if self.section is not None:
+            dic = self.section[0]
+            key = self.section[1]
+            doc = "\n".join(self.section[2:])
+            if key != "Example":
+                doc = doc.strip()
+            dic[key] = doc
+            self.section = None
+
+    def start_section(self, dic, key):
+        self.end_section()
+        self.section = [dic, key]  # .. remaining elems will be the doc
+
+
 class QAPISchemaParser(object):
 
     def __init__(self, fp, previously_included=[], incl_info=None):
@@ -137,11 +200,14 @@ class QAPISchemaParser(object):
         self.line = 1
         self.line_pos = 0
         self.exprs = []
+        self.comment = None
+        self.apidoc = incl_info['doc'] if incl_info else []
         self.accept()
 
         while self.tok is not None:
             expr_info = {'file': fname, 'line': self.line,
-                         'parent': self.incl_info}
+                         'parent': self.incl_info, 'doc': self.apidoc}
+            self.apidoc = []
             expr = self.get_expr(False)
             if isinstance(expr, dict) and "include" in expr:
                 if len(expr) != 1:
@@ -162,6 +228,8 @@ class QAPISchemaParser(object):
                     inf = inf['parent']
                 # skip multiple include of the same file
                 if incl_abs_fname in previously_included:
+                    expr_info['doc'].extend(self.apidoc)
+                    self.apidoc = expr_info['doc']
                     continue
                 try:
                     fobj = open(incl_abs_fname, 'r')
@@ -176,6 +244,12 @@ class QAPISchemaParser(object):
                              'info': expr_info}
                 self.exprs.append(expr_elem)
 
+    def append_doc(self):
+        if self.comment:
+            apidoc = QAPIDoc(self.comment)
+            self.apidoc.append(apidoc)
+            self.comment = None
+
     def accept(self):
         while True:
             self.tok = self.src[self.cursor]
@@ -184,8 +258,20 @@ class QAPISchemaParser(object):
             self.val = None
 
             if self.tok == '#':
-                self.cursor = self.src.find('\n', self.cursor)
+                end = self.src.find('\n', self.cursor)
+                line = self.src[self.cursor:end+1]
+                # start a comment section after ##
+                if line[0] == "#":
+                    if self.comment is None:
+                        self.comment = ""
+                # skip modeline
+                elif line.find("-*") == -1 and self.comment is not None:
+                    self.comment += line
+                if self.src[end] == "\n" and self.src[end+1] == "\n":
+                    self.append_doc()
+                self.cursor = end
             elif self.tok in "{}:,[]":
+                self.append_doc()
                 return
             elif self.tok == "'":
                 string = ''
diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
new file mode 100755
index 0000000..77bd1e2
--- /dev/null
+++ b/scripts/qapi2texi.py
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+# QAPI texi generator
+#
+# This work is licensed under the terms of the GNU GPL, version 2.
+# See the COPYING file in the top-level directory.
+"""This script produces the documentation of a qapi schema in texinfo format"""
+import re
+import sys
+
+from qapi import QAPISchemaParser, QAPISchemaError, check_exprs, QAPIExprError
+
+COMMAND_FMT = """
+@deftypefn {type} {{{ret}}} {name} @
+{{{args}}}
+
+{body}
+
+@end deftypefn
+
+""".format
+
+ENUM_FMT = """
+@deftp Enum {name}
+
+{body}
+
+@end deftp
+
+""".format
+
+STRUCT_FMT = """
+@deftp {type} {name} @
+{{{attrs}}}
+
+{body}
+
+@end deftp
+
+""".format
+
+EXAMPLE_FMT = """@example
+{code}
+@end example
+""".format
+
+
+def subst_emph(doc):
+    """Replaces *foo* by @emph{foo}"""
+    return re.sub(r'\*(\w+)\*', r'@emph{\1}', doc)
+
+
+def subst_vars(doc):
+    """Replaces @var by @var{var}"""
+    return re.sub(r'@(\w+)', r'@var{\1}', doc)
+
+
+def subst_braces(doc):
+    """Replaces {} with @{ @}"""
+    return doc.replace("{", "@{").replace("}", "@}")
+
+
+def texi_example(doc):
+    """Format @example"""
+    doc = subst_braces(doc).strip('\n')
+    return EXAMPLE_FMT(code=doc)
+
+
+def texi_comment(doc):
+    """
+    Format a comment
+
+    Lines starting with:
+    - |: generates an @example
+    - =: generates @section
+    - ==: generates @subsection
+    - 1. or 1): generates an @enumerate @item
+    - o/*/-: generates an @itemize list
+    """
+    lines = []
+    doc = subst_braces(doc)
+    doc = subst_vars(doc)
+    doc = subst_emph(doc)
+    inlist = ""
+    lastempty = False
+    for line in doc.split('\n'):
+        empty = line == ""
+
+        if line.startswith("| "):
+            line = EXAMPLE_FMT(code=line[1:])
+        elif line.startswith("= "):
+            line = "@section " + line[1:]
+        elif line.startswith("== "):
+            line = "@subsection " + line[2:]
+        elif re.match("^([0-9]*[.)]) ", line):
+            if not inlist:
+                lines.append("@enumerate")
+                inlist = "enumerate"
+            line = line[line.find(" ")+1:]
+            lines.append("@item")
+        elif re.match("^[o*-] ", line):
+            if not inlist:
+                lines.append("@itemize %s" % {'o': "@bullet",
+                                              '*': "@minus",
+                                              '-': ""}[line[0]])
+                inlist = "itemize"
+            lines.append("@item")
+            line = line[2:]
+        elif lastempty and inlist:
+            lines.append("@end %s\n" % inlist)
+            inlist = ""
+
+        lastempty = empty
+        lines.append(line)
+
+    if inlist:
+        lines.append("@end %s\n" % inlist)
+    return "\n".join(lines)
+
+
+def texi_args(expr):
+    """
+    Format the functions/structure/events.. arguments/members
+    """
+    data = expr["data"] if "data" in expr else {}
+    if isinstance(data, str):
+        args = data
+    else:
+        arg_list = []
+        for name, typ in data.iteritems():
+            # optional arg
+            if name.startswith("*"):
+                name = name[1:]
+                arg_list.append("['%s': @var{%s}]" % (name, typ))
+            # regular arg
+            else:
+                arg_list.append("'%s': @var{%s}" % (name, typ))
+        args = ", ".join(arg_list)
+    return args
+
+
+def texi_body(doc, arg="@var"):
+    """
+    Format the body of a symbol documentation:
+    - a table of arguments
+    - followed by "Returns/Notes/Since/Example" sections
+    """
+    body = "@table %s\n" % arg
+    for arg, desc in doc.args.iteritems():
+        if desc.startswith("#optional"):
+            desc = desc[10:]
+            arg += "*"
+        elif desc.endswith("#optional"):
+            desc = desc[:-10]
+            arg += "*"
+        body += "@item %s\n%s\n" % (arg, texi_comment(desc))
+    body += "@end table\n"
+    body += texi_comment(doc.comment)
+
+    for k in ("Returns", "Note", "Notes", "Since", "Example", "Examples"):
+        if k not in doc.meta:
+            continue
+        func = texi_comment
+        if k in ("Example", "Examples"):
+            func = texi_example
+        body += "\n@quotation %s\n%s\n@end quotation" % \
+                (k, func(doc.meta[k]))
+    return body
+
+
+def texi_alternate(expr, doc):
+    """
+    Format an alternate to texi
+    """
+    args = texi_args(expr)
+    body = texi_body(doc)
+    return STRUCT_FMT(type="Alternate",
+                      name=doc.symbol,
+                      attrs="[ " + args + " ]",
+                      body=body)
+
+
+def texi_union(expr, doc):
+    """
+    Format an union to texi
+    """
+    args = texi_args(expr)
+    body = texi_body(doc)
+    return STRUCT_FMT(type="Union",
+                      name=doc.symbol,
+                      attrs="[ " + args + " ]",
+                      body=body)
+
+
+def texi_enum(_, doc):
+    """
+    Format an enum to texi
+    """
+    body = texi_body(doc, "@samp")
+    return ENUM_FMT(name=doc.symbol,
+                    body=body)
+
+
+def texi_struct(expr, doc):
+    """
+    Format a struct to texi
+    """
+    args = texi_args(expr)
+    body = texi_body(doc)
+    return STRUCT_FMT(type="Struct",
+                      name=doc.symbol,
+                      attrs="@{ " + args + " @}",
+                      body=body)
+
+
+def texi_command(expr, doc):
+    """
+    Format a command to texi
+    """
+    args = texi_args(expr)
+    ret = expr["returns"] if "returns" in expr else ""
+    body = texi_body(doc)
+    return COMMAND_FMT(type="Command",
+                       name=doc.symbol,
+                       ret=ret,
+                       args="(" + args + ")",
+                       body=body)
+
+
+def texi_event(expr, doc):
+    """
+    Format an event to texi
+    """
+    args = texi_args(expr)
+    body = texi_body(doc)
+    return COMMAND_FMT(type="Event",
+                       name=doc.symbol,
+                       ret="",
+                       args="(" + args + ")",
+                       body=body)
+
+
+def texi(exprs):
+    """
+    Convert QAPI schema expressions to texi documentation
+    """
+    res = []
+    for qapi in exprs:
+        try:
+            docs = qapi['info']['doc']
+            expr = qapi['expr']
+            expr_doc = docs[-1]
+            body = docs[0:-1]
+
+            (kind, _) = expr.items()[0]
+
+            for doc in body:
+                res.append(texi_body(doc))
+
+            fmt = {"command": texi_command,
+                   "struct": texi_struct,
+                   "enum": texi_enum,
+                   "union": texi_union,
+                   "alternate": texi_alternate,
+                   "event": texi_event}
+            try:
+                fmt = fmt[kind]
+            except KeyError:
+                raise ValueError("Unknown expression kind '%s'" % kind)
+            res.append(fmt(expr, expr_doc))
+        except:
+            print >>sys.stderr, "error at @%s" % qapi
+            raise
+
+    return '\n'.join(res)
+
+
+def parse_schema(fname):
+    """
+    Parse the given schema file and return the exprs
+    """
+    try:
+        schema = QAPISchemaParser(open(fname, "r"))
+        check_exprs(schema.exprs)
+        return schema.exprs
+    except (QAPISchemaError, QAPIExprError), err:
+        print >>sys.stderr, err
+        exit(1)
+
+
+def main(argv):
+    """
+    Takes argv arguments, prints result to stdout
+    """
+    if len(argv) != 4:
+        print >>sys.stderr, "%s: need exactly 3 arguments: " \
+            "TEMPLATE VERSION SCHEMA" % argv[0]
+        sys.exit(1)
+
+    exprs = parse_schema(argv[3])
+
+    templ = open(argv[1])
+    qapi = texi(exprs)
+    print templ.read().format(version=argv[2], qapi=qapi)
+
+
+if __name__ == "__main__":
+    main(sys.argv)
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 5d4c2cd..0bf9a81 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -45,16 +45,13 @@ QAPI parser does not).  At present, there is no place where a QAPI
 schema requires the use of JSON numbers or null.
 
 Comments are allowed; anything between an unquoted # and the following
-newline is ignored.  Although there is not yet a documentation
-generator, a form of stylized comments has developed for consistently
-documenting details about an expression and when it was added to the
-schema.  The documentation is delimited between two lines of ##, then
-the first line names the expression, an optional overview is provided,
-then individual documentation about each member of 'data' is provided,
-and finally, a 'Since: x.y.z' tag lists the release that introduced
-the expression.  Optional members are tagged with the phrase
-'#optional', often with their default value; and extensions added
-after the expression was first released are also given a '(since
+newline is ignored.  The documentation is delimited between two lines
+of ##, then the first line names the expression, an optional overview
+is provided, then individual documentation about each member of 'data'
+is provided, and finally, a 'Since: x.y.z' tag lists the release that
+introduced the expression.  Optional members are tagged with the
+phrase '#optional', often with their default value; and extensions
+added after the expression was first released are also given a '(since
 x.y.z)' comment.  For example:
 
     ##
@@ -73,12 +70,39 @@ x.y.z)' comment.  For example:
     #           (Since 2.0)
     #
     # Since: 0.14.0
+    #
+    # Notes: You can also make a list:
+    #        - with items
+    #        - like this
+    #
+    # Example:
+    #
+    # -> { "execute": ... }
+    # <- { "return": ... }
+    #
     ##
     { 'struct': 'BlockStats',
       'data': {'*device': 'str', 'stats': 'BlockDeviceStats',
                '*parent': 'BlockStats',
                '*backing': 'BlockStats'} }
 
+It's also possible to create documentation sections, such as:
+
+    ##
+    # = Section
+    # == Subsection
+    #
+    # Some text foo with *emphasis*
+    # 1. with a list
+    # 2. like that
+    #
+    # And some code:
+    # | $ echo foo
+    # | <- do this
+    # | -> get that
+    #
+    ##
+
 The schema sets up a series of types, as well as commands and events
 that will use those types.  Forward references are allowed: the parser
 scans in two passes, where the first pass learns all type names, and
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 2/4] qapi: fix schema symbol sections
  2016-09-22 15:58 [Qemu-devel] [PATCH 0/4] Add qapi doc generation scripts Marc-André Lureau
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 1/4] qapi: add qapi2texi script Marc-André Lureau
@ 2016-09-22 15:58 ` Marc-André Lureau
  2016-09-22 16:26   ` Eric Blake
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 3/4] docs: add qapi texi template Marc-André Lureau
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 4/4] build-sys: add qapi doc generation targets Marc-André Lureau
  3 siblings, 1 reply; 7+ messages in thread
From: Marc-André Lureau @ 2016-09-22 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

According to documentation, there needs to be '##' to start a symbol
section, that's also what the documentation parser expects.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qapi-schema.json     | 9 +++++++--
 qapi/block-core.json | 1 +
 qga/qapi-schema.json | 3 +++
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index e507061..f07ffd7 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -65,6 +65,7 @@
 { 'enum': 'LostTickPolicy',
   'data': ['discard', 'delay', 'merge', 'slew' ] }
 
+##
 # @add_client
 #
 # Allow client connections for VNC, Spice and socket based
@@ -439,6 +440,7 @@
            'cache-miss': 'int', 'cache-miss-rate': 'number',
            'overflow': 'int' } }
 
+##
 # @MigrationStatus:
 #
 # An enumeration of migration status.
@@ -617,6 +619,7 @@
 ##
 { 'command': 'query-migrate-capabilities', 'returns':   ['MigrationCapabilityStatus']}
 
+##
 # @MigrationParameter
 #
 # Migration parameters enumeration
@@ -665,7 +668,7 @@
            'cpu-throttle-initial', 'cpu-throttle-increment',
            'tls-creds', 'tls-hostname'] }
 
-#
+##
 # @migrate-set-parameters
 #
 # Set the following migration parameters
@@ -710,7 +713,7 @@
             '*tls-creds': 'str',
             '*tls-hostname': 'str'} }
 
-#
+##
 # @MigrationParameters
 #
 # @compress-level: compression level
@@ -2172,6 +2175,7 @@
 ##
 { 'command': 'migrate-incoming', 'data': {'uri': 'str' } }
 
+##
 # @xen-save-devices-state:
 #
 # Save the state of all devices to file. The RAM and the block devices
@@ -3359,6 +3363,7 @@
             'modelb': 'CpuModelInfo' },
   'returns': 'CpuModelBaselineInfo' }
 
+##
 # @AddfdInfo:
 #
 # Information about a file descriptor that was added to an fd set.
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 24223fd..043c21e 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2665,6 +2665,7 @@
             'offset': 'int',
             'speed' : 'int' } }
 
+##
 # @PreallocMode
 #
 # Preallocation mode of QEMU image file
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index c21f308..09c9728 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -837,6 +837,7 @@
 { 'command': 'guest-set-user-password',
   'data': { 'username': 'str', 'password': 'str', 'crypted': 'bool' } }
 
+##
 # @GuestMemoryBlock:
 #
 # @phys-index: Arbitrary guest-specific unique identifier of the MEMORY BLOCK.
@@ -936,6 +937,7 @@
   'data':    {'mem-blks': ['GuestMemoryBlock'] },
   'returns': ['GuestMemoryBlockResponse'] }
 
+##
 # @GuestMemoryBlockInfo:
 #
 # @size: the size (in bytes) of the guest memory blocks,
@@ -960,6 +962,7 @@
 { 'command': 'guest-get-memory-block-info',
   'returns': 'GuestMemoryBlockInfo' }
 
+##
 # @GuestExecStatus:
 #
 # @exited: true if process has already terminated.
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 3/4] docs: add qapi texi template
  2016-09-22 15:58 [Qemu-devel] [PATCH 0/4] Add qapi doc generation scripts Marc-André Lureau
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 1/4] qapi: add qapi2texi script Marc-André Lureau
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 2/4] qapi: fix schema symbol sections Marc-André Lureau
@ 2016-09-22 15:58 ` Marc-André Lureau
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 4/4] build-sys: add qapi doc generation targets Marc-André Lureau
  3 siblings, 0 replies; 7+ messages in thread
From: Marc-André Lureau @ 2016-09-22 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

The qapi2texi scripts uses a template for the texi file. Since we are
going to generate the documentation in multiple formats, move qmp-intro
to qemu-qapi template. (it would be nice to write something similar for
qemu-ga, but this is left for a future patch)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 docs/qemu-ga-qapi.template.texi |  58 ++++++++++++++++
 docs/qemu-qapi.template.texi    | 148 ++++++++++++++++++++++++++++++++++++++++
 docs/qmp-intro.txt              |  87 -----------------------
 3 files changed, 206 insertions(+), 87 deletions(-)
 create mode 100644 docs/qemu-ga-qapi.template.texi
 create mode 100644 docs/qemu-qapi.template.texi
 delete mode 100644 docs/qmp-intro.txt

diff --git a/docs/qemu-ga-qapi.template.texi b/docs/qemu-ga-qapi.template.texi
new file mode 100644
index 0000000..3ddbf56
--- /dev/null
+++ b/docs/qemu-ga-qapi.template.texi
@@ -0,0 +1,58 @@
+\input texinfo
+@setfilename qemu-ga-qapi
+@documentlanguage en
+@exampleindent 0
+@paragraphindent 0
+
+@settitle QEMU-GA QAPI Reference Manual
+
+@ifinfo
+@direntry
+* QEMU-GA-QAPI: (qemu-doc).    QEMU-GA QAPI Reference Manual
+@end direntry
+@end ifinfo
+
+@iftex
+@titlepage
+@sp 7
+@center @titlefont{{QEMU Guest Agent {version}}}
+@sp 1
+@center @titlefont{{QAPI Reference Manual}}
+@sp 3
+@end titlepage
+@end iftex
+
+@ifnottex
+@node Top
+@top
+
+This is the QEMU Guest Agent QAPI reference for QEMU {version}.
+
+@menu
+* API Reference::
+* Commands and Events Index::
+* Data Types Index::
+@end menu
+
+@end ifnottex
+
+@contents
+
+@node API Reference
+@chapter API Reference
+
+@c man begin DESCRIPTION
+{qapi}
+@c man end
+
+@c man begin SEEALSO
+The HTML documentation of QEMU for more precise information.
+@c man end
+
+@node Commands and Events Index
+@unnumbered Commands and Events Index
+@printindex fn
+@node Data Types Index
+@unnumbered Data Types Index
+@printindex tp
+@bye
diff --git a/docs/qemu-qapi.template.texi b/docs/qemu-qapi.template.texi
new file mode 100644
index 0000000..102c8d9
--- /dev/null
+++ b/docs/qemu-qapi.template.texi
@@ -0,0 +1,148 @@
+\input texinfo
+@setfilename qemu-qapi
+@documentlanguage en
+@exampleindent 0
+@paragraphindent 0
+
+@settitle QEMU QAPI Reference Manual
+
+@ifinfo
+@direntry
+* QEMU: (qemu-doc).    QEMU QAPI Reference Manual
+@end direntry
+@end ifinfo
+
+@iftex
+@titlepage
+@sp 7
+@center @titlefont{{QEMU Emulator {version}}}
+@sp 1
+@center @titlefont{{QAPI Reference Manual}}
+@sp 3
+@end titlepage
+@end iftex
+
+@ifnottex
+@node Top
+@top
+
+This is the QMP QAPI reference for QEMU {version}.
+
+@menu
+* Introduction::
+* API Reference::
+* Commands and Events Index::
+* Data Types Index::
+@end menu
+
+@end ifnottex
+
+@contents
+
+@node Introduction
+@chapter Introduction
+
+The QEMU Machine Protocol (@acronym{{QMP}}) allows applications to
+operate a QEMU instance.
+
+QMP is @uref{{http://www.json.org, JSON}} based and features the
+following:
+
+@itemize @minus
+@item
+Lightweight, text-based, easy to parse data format
+@item
+Asynchronous messages support (ie. events)
+@item
+Capabilities Negotiation
+@end itemize
+
+For detailed information on QEMU Machine Protocol, the specification
+is in @file{{qmp-spec.txt}}.
+
+@section Usage
+
+You can use the @option{{-qmp}} option to enable QMP. For example, the
+following makes QMP available on localhost port 4444:
+
+@example
+$ qemu [...] -qmp tcp:localhost:4444,server,nowait
+@end example
+
+However, for more flexibility and to make use of more options, the
+@option{{-mon}} command-line option should be used. For instance, the
+following example creates one HMP instance (human monitor) on stdio
+and one QMP instance on localhost port 4444:
+
+@example
+$ qemu [...] -chardev stdio,id=mon0 -mon chardev=mon0,mode=readline \
+             -chardev socket,id=mon1,host=localhost,port=4444,server,nowait \
+             -mon chardev=mon1,mode=control,pretty=on
+@end example
+
+Please, refer to QEMU's manpage for more information.
+
+@section Simple testing
+
+To manually test QMP one can connect with telnet and issue commands by
+hand:
+
+@example
+$ telnet localhost 4444
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+@{{
+    "QMP": @{{
+        "version": @{{
+            "qemu": @{{
+                "micro": 50,
+                "minor": 6,
+                "major": 1
+            @}},
+            "package": ""
+        @}},
+        "capabilities": [
+        ]
+    @}}
+@}}
+
+@{{ "execute": "qmp_capabilities" @}}
+@{{
+    "return": @{{
+    @}}
+@}}
+
+@{{ "execute": "query-status" @}}
+@{{
+    "return": @{{
+        "status": "prelaunch",
+        "singlestep": false,
+        "running": false
+    @}}
+@}}
+@end example
+
+@section Wiki
+
+Please refer to the @uref{{http://wiki.qemu-project.org/QMP, QMP QEMU
+ wiki page}} for more details on QMP.
+
+@node API Reference
+@chapter API Reference
+
+@c man begin DESCRIPTION
+{qapi}
+@c man end
+
+@c man begin SEEALSO
+The HTML documentation of QEMU for more precise information.
+@c man end
+
+@node Commands and Events Index
+@unnumbered Commands and Events Index
+@printindex fn
+@node Data Types Index
+@unnumbered Data Types Index
+@printindex tp
+@bye
diff --git a/docs/qmp-intro.txt b/docs/qmp-intro.txt
deleted file mode 100644
index f6a3a03..0000000
--- a/docs/qmp-intro.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-                          QEMU Machine Protocol
-                          =====================
-
-Introduction
-------------
-
-The QEMU Machine Protocol (QMP) allows applications to operate a
-QEMU instance.
-
-QMP is JSON[1] based and features the following:
-
-- Lightweight, text-based, easy to parse data format
-- Asynchronous messages support (ie. events)
-- Capabilities Negotiation
-
-For detailed information on QMP's usage, please, refer to the following files:
-
-o qmp-spec.txt      QEMU Machine Protocol current specification
-o qmp-commands.txt  QMP supported commands (auto-generated at build-time)
-o qmp-events.txt    List of available asynchronous events
-
-[1] http://www.json.org
-
-Usage
------
-
-You can use the -qmp option to enable QMP. For example, the following
-makes QMP available on localhost port 4444:
-
-$ qemu [...] -qmp tcp:localhost:4444,server,nowait
-
-However, for more flexibility and to make use of more options, the -mon
-command-line option should be used. For instance, the following example
-creates one HMP instance (human monitor) on stdio and one QMP instance
-on localhost port 4444:
-
-$ qemu [...] -chardev stdio,id=mon0 -mon chardev=mon0,mode=readline \
-             -chardev socket,id=mon1,host=localhost,port=4444,server,nowait \
-             -mon chardev=mon1,mode=control,pretty=on
-
-Please, refer to QEMU's manpage for more information.
-
-Simple Testing
---------------
-
-To manually test QMP one can connect with telnet and issue commands by hand:
-
-$ telnet localhost 4444
-Trying 127.0.0.1...
-Connected to localhost.
-Escape character is '^]'.
-{
-    "QMP": {
-        "version": {
-            "qemu": {
-                "micro": 50, 
-                "minor": 6, 
-                "major": 1
-            }, 
-            "package": ""
-        }, 
-        "capabilities": [
-        ]
-    }
-}
-
-{ "execute": "qmp_capabilities" }
-{
-    "return": {
-    }
-}
-
-{ "execute": "query-status" }
-{
-    "return": {
-        "status": "prelaunch", 
-        "singlestep": false, 
-        "running": false
-    }
-}
-
-Please, refer to the qapi-schema.json file for a complete command reference.
-
-QMP wiki page
--------------
-
-http://wiki.qemu-project.org/QMP
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH 4/4] build-sys: add qapi doc generation targets
  2016-09-22 15:58 [Qemu-devel] [PATCH 0/4] Add qapi doc generation scripts Marc-André Lureau
                   ` (2 preceding siblings ...)
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 3/4] docs: add qapi texi template Marc-André Lureau
@ 2016-09-22 15:58 ` Marc-André Lureau
  3 siblings, 0 replies; 7+ messages in thread
From: Marc-André Lureau @ 2016-09-22 15:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: eblake, armbru, Marc-André Lureau

Add qapi doc generation targets, qemu-qapi.texi, qemu-ga-qapi.texi
(implicit pdf works too) and qemu-qapi.txt. The generated
documentation isn't complete yet, so don't bother to build it by
default or install it yet.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 Makefile | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Makefile b/Makefile
index f103616..6e00559 100644
--- a/Makefile
+++ b/Makefile
@@ -269,6 +269,7 @@ qemu-ga$(EXESUF): QEMU_CFLAGS += -I qga/qapi-generated
 gen-out-type = $(subst .,-,$(suffix $@))
 
 qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
+qapi-py += $(SRC_PATH)/scripts/qapi2texi.py
 
 qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\
 $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
@@ -558,9 +559,23 @@ qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
 qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
+qemu-qapi.txt: qemu-qapi.texi
+	$(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --plaintext $< -o $@,\
+	"  GEN   $@")
+
 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
+qemu-qapi.texi: $(qapi-modules) $(qapi-py) \
+	$(SRC_PATH)/docs/qemu-qapi.template.texi
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py \
+	$(SRC_PATH)/docs/qemu-qapi.template.texi $(VERSION) $< > $@,"  GEN   $@")
+
+qemu-ga-qapi.texi: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py) \
+	$(SRC_PATH)/docs/qemu-ga-qapi.template.texi
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py \
+	$(SRC_PATH)/docs/qemu-ga-qapi.template.texi $(VERSION) $< > $@,"  GEN   $@")
+
 qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu.pod && \
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH 1/4] qapi: add qapi2texi script
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 1/4] qapi: add qapi2texi script Marc-André Lureau
@ 2016-09-22 16:25   ` Eric Blake
  0 siblings, 0 replies; 7+ messages in thread
From: Eric Blake @ 2016-09-22 16:25 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel; +Cc: armbru

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

On 09/22/2016 10:58 AM, Marc-André Lureau wrote:
> As the name suggests, the qapi2texi script converts JSON QAPI
> description into a standalone texi file suitable for different target
> formats.
> 
> It parses the following kind of blocks with some little variations:
> 
>   ##
>   # = Section
>   # == Subsection
>   #
>   # Some text foo with *emphasis*
>   # 1. with a list
>   # 2. like that
>   #
>   # And some code:
>   # | $ echo foo
>   # | <- do this
>   # | -> get that

Arrows are backwards; should be -> do this, <- get that.

>   #
>   ##
> 
>   ##
>   # @symbol
>   #
>   # Symbol body ditto ergo sum. Foo bar
>   # baz ding.
>   #
>   # @arg: foo
>   # @arg: #optional foo
>   #
>   # Returns: returns bla bla
>   #
>   #          Or bla blah
>   #
>   # Since: version
>   # Notes: notes, comments can have
>   #        - itemized list
>   #        - like this
>   #
>   #        and continue...
>   #
>   # Example:
>   #
>   # -> { "execute": "quit" }
>   # <- { "return": {} }
>   #
>   ##
> 
> Thanks to the json declaration, it's able to give extra information
> about the type of arguments and return value expected.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi.py        |  90 ++++++++++++++-
>  scripts/qapi2texi.py   | 307 +++++++++++++++++++++++++++++++++++++++++++++++++
>  docs/qapi-code-gen.txt |  44 +++++--
>  3 files changed, 429 insertions(+), 12 deletions(-)
>  create mode 100755 scripts/qapi2texi.py

Not a close review at this point, so much as first impressions...


> +++ b/scripts/qapi2texi.py
> @@ -0,0 +1,307 @@
> +#!/usr/bin/env python
> +# QAPI texi generator
> +#
> +# This work is licensed under the terms of the GNU GPL, version 2.

Can you fix this to GPLv2+?  Our GPLv2-only scripts were a mistake that
should not be repeated.

> +++ b/docs/qapi-code-gen.txt
> @@ -45,16 +45,13 @@ QAPI parser does not).  At present, there is no place where a QAPI
>  schema requires the use of JSON numbers or null.
>  
>  Comments are allowed; anything between an unquoted # and the following
> -newline is ignored.  Although there is not yet a documentation
> -generator, a form of stylized comments has developed for consistently
> -documenting details about an expression and when it was added to the
> -schema.  The documentation is delimited between two lines of ##, then
> -the first line names the expression, an optional overview is provided,
> -then individual documentation about each member of 'data' is provided,
> -and finally, a 'Since: x.y.z' tag lists the release that introduced
> -the expression.  Optional members are tagged with the phrase
> -'#optional', often with their default value; and extensions added
> -after the expression was first released are also given a '(since
> +newline is ignored.  The documentation is delimited between two lines
> +of ##, then the first line names the expression, an optional overview
> +is provided, then individual documentation about each member of 'data'
> +is provided, and finally, a 'Since: x.y.z' tag lists the release that
> +introduced the expression.  Optional members are tagged with the
> +phrase '#optional', often with their default value; and extensions
> +added after the expression was first released are also given a '(since
>  x.y.z)' comment.  For example:
>  
>      ##
> @@ -73,12 +70,39 @@ x.y.z)' comment.  For example:
>      #           (Since 2.0)
>      #
>      # Since: 0.14.0
> +    #
> +    # Notes: You can also make a list:
> +    #        - with items
> +    #        - like this
> +    #
> +    # Example:
> +    #
> +    # -> { "execute": ... }
> +    # <- { "return": ... }
> +    #
>      ##

Thanks for remembering this. It does no good to parse a nebulous format,
but calling out the format means we have something to copy from and to
bring existing outliers into conformance.

>      { 'struct': 'BlockStats',
>        'data': {'*device': 'str', 'stats': 'BlockDeviceStats',
>                 '*parent': 'BlockStats',
>                 '*backing': 'BlockStats'} }
>  
> +It's also possible to create documentation sections, such as:
> +
> +    ##
> +    # = Section
> +    # == Subsection
> +    #
> +    # Some text foo with *emphasis*
> +    # 1. with a list
> +    # 2. like that
> +    #
> +    # And some code:
> +    # | $ echo foo
> +    # | <- do this
> +    # | -> get that

Again, arrows look backwards here.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] qapi: fix schema symbol sections
  2016-09-22 15:58 ` [Qemu-devel] [PATCH 2/4] qapi: fix schema symbol sections Marc-André Lureau
@ 2016-09-22 16:26   ` Eric Blake
  0 siblings, 0 replies; 7+ messages in thread
From: Eric Blake @ 2016-09-22 16:26 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel; +Cc: armbru

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

On 09/22/2016 10:58 AM, Marc-André Lureau wrote:
> According to documentation, there needs to be '##' to start a symbol
> section, that's also what the documentation parser expects.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  qapi-schema.json     | 9 +++++++--
>  qapi/block-core.json | 1 +
>  qga/qapi-schema.json | 3 +++
>  3 files changed, 11 insertions(+), 2 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-09-22 16:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-09-22 15:58 [Qemu-devel] [PATCH 0/4] Add qapi doc generation scripts Marc-André Lureau
2016-09-22 15:58 ` [Qemu-devel] [PATCH 1/4] qapi: add qapi2texi script Marc-André Lureau
2016-09-22 16:25   ` Eric Blake
2016-09-22 15:58 ` [Qemu-devel] [PATCH 2/4] qapi: fix schema symbol sections Marc-André Lureau
2016-09-22 16:26   ` Eric Blake
2016-09-22 15:58 ` [Qemu-devel] [PATCH 3/4] docs: add qapi texi template Marc-André Lureau
2016-09-22 15:58 ` [Qemu-devel] [PATCH 4/4] build-sys: add qapi doc generation targets Marc-André Lureau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).