From nobody Thu Nov 6 15:49:44 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1489387399324722.81106879003; Sun, 12 Mar 2017 23:43:19 -0700 (PDT) Received: from localhost ([::1]:50467 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cnJhO-00029u-4d for importer@patchew.org; Mon, 13 Mar 2017 02:43:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52415) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cnJJq-0007bA-W4 for qemu-devel@nongnu.org; Mon, 13 Mar 2017 02:19:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cnJJl-0003cp-Ty for qemu-devel@nongnu.org; Mon, 13 Mar 2017 02:18:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56814) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cnJJl-0003Zy-DA for qemu-devel@nongnu.org; Mon, 13 Mar 2017 02:18:53 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7E76A83F46; Mon, 13 Mar 2017 06:18:53 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v2D6Iplk011048 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 13 Mar 2017 02:18:53 -0400 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 4B2F71138610; Mon, 13 Mar 2017 07:18:47 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Mon, 13 Mar 2017 07:18:16 +0100 Message-Id: <1489385927-6735-17-git-send-email-armbru@redhat.com> In-Reply-To: <1489385927-6735-1-git-send-email-armbru@redhat.com> References: <1489385927-6735-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 13 Mar 2017 06:18:53 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-2.9 16/47] qapi2texi: Convert to QAPISchemaVisitor X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: marcandre.lureau@redhat.com, mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" qapi2texi works with schema expression trees. Such a tight coupling to schema language syntax is not a good idea. Convert it to the visitor interface the other generators use. No change to generated documentation. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- scripts/qapi2texi.py | 228 ++++++++++++++++++++++++++---------------------= ---- 1 file changed, 118 insertions(+), 110 deletions(-) diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py index 299dcf9..6d4e757 100755 --- a/scripts/qapi2texi.py +++ b/scripts/qapi2texi.py @@ -123,31 +123,39 @@ def texi_format(doc): return "\n".join(lines) =20 =20 -def texi_body(doc, only_documented=3DFalse): - """ - Format the body of a symbol documentation: - - main body - - table of arguments - - followed by "Returns/Notes/Since/Example" sections - """ - body =3D texi_format(str(doc.body)) + "\n" - - args =3D '' - for name, section in doc.args.iteritems(): - if not section.content and not only_documented: - continue # Undocumented TODO require doc and drop - desc =3D str(section) - opt =3D '' - if section.optional: - desc =3D re.sub(r'^ *#optional *\n?|\n? *#optional *$|#optiona= l', - '', desc) - opt =3D ' (optional)' - args +=3D "@item @code{'%s'}%s\n%s\n" % (name, opt, texi_format(de= sc)) - if args: - body +=3D "@table @asis\n" - body +=3D args - body +=3D "@end table\n" +def texi_body(doc): + """Format the main documentation body""" + return texi_format(str(doc.body)) + '\n' =20 + +def texi_enum_value(value): + """Format a table of members item for an enumeration value""" + return "@item @code{'%s'}\n" % value.name + + +def texi_member(member): + """Format a table of members item for an object type member""" + return "@item @code{'%s'}%s\n" % ( + member.name, ' (optional)' if member.optional else '') + + +def texi_members(doc, member_func, show_undocumented): + """Format the table of members""" + items =3D '' + for section in doc.args.itervalues(): + if not section.content and not show_undocumented: + continue # Undocumented TODO require doc and drop + desc =3D re.sub(r'^ *#optional *\n?|\n? *#optional *$|#optional', + '', str(section)) + items +=3D member_func(section.member) + texi_format(desc) + '\n' + if not items: + return '' + return '@table @asis\n' + items + '@end table\n' + + +def texi_sections(doc): + """Format additional sections following arguments""" + body =3D '' for section in doc.sections: name, doc =3D (section.name, str(section)) func =3D texi_format @@ -159,94 +167,94 @@ def texi_body(doc, only_documented=3DFalse): body +=3D "\n\n@b{%s:}\n" % name =20 body +=3D func(doc) - return body =20 =20 -def texi_alternate(expr, doc): - """Format an alternate to texi""" - body =3D texi_body(doc) - return TYPE_FMT(type=3D"Alternate", - name=3Ddoc.symbol, - body=3Dbody) - - -def texi_union(expr, doc): - """Format a union to texi""" - discriminator =3D expr.get("discriminator") - if discriminator: - union =3D "Flat Union" - else: - union =3D "Simple Union" - - body =3D texi_body(doc) - return TYPE_FMT(type=3Dunion, - name=3Ddoc.symbol, - body=3Dbody) - - -def texi_enum(expr, doc): - """Format an enum to texi""" - body =3D texi_body(doc, True) - return TYPE_FMT(type=3D"Enum", - name=3Ddoc.symbol, - body=3Dbody) - - -def texi_struct(expr, doc): - """Format a struct to texi""" - body =3D texi_body(doc) - return TYPE_FMT(type=3D"Struct", - name=3Ddoc.symbol, - body=3Dbody) - - -def texi_command(expr, doc): - """Format a command to texi""" - body =3D texi_body(doc) - return MSG_FMT(type=3D"Command", - name=3Ddoc.symbol, - body=3Dbody) - - -def texi_event(expr, doc): - """Format an event to texi""" - body =3D texi_body(doc) - return MSG_FMT(type=3D"Event", - name=3Ddoc.symbol, - body=3Dbody) - - -def texi_expr(expr, doc): - """Format an expr to texi""" - (kind, _) =3D expr.items()[0] - - fmt =3D {"command": texi_command, - "struct": texi_struct, - "enum": texi_enum, - "union": texi_union, - "alternate": texi_alternate, - "event": texi_event}[kind] - - return fmt(expr, doc) - - -def texi(docs): - """Convert QAPI schema expressions to texi documentation""" - res =3D [] - for doc in docs: - expr =3D doc.expr - if not expr: - res.append(texi_body(doc)) - continue - try: - doc =3D texi_expr(expr, doc) - res.append(doc) - except: - print >>sys.stderr, "error at @%s" % doc.info - raise - - return '\n'.join(res) +def texi_entity(doc, member_func=3Dtexi_member, show_undocumented=3DFalse): + return (texi_body(doc) + + texi_members(doc, member_func, show_undocumented) + + texi_sections(doc)) + + +class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor): + def __init__(self): + self.out =3D None + self.cur_doc =3D None + + def visit_begin(self, schema): + self.out =3D '' + + def visit_enum_type(self, name, info, values, prefix): + doc =3D self.cur_doc + if self.out: + self.out +=3D '\n' + self.out +=3D TYPE_FMT(type=3D'Enum', + name=3Ddoc.symbol, + body=3Dtexi_entity(doc, + member_func=3Dtexi_enum_valu= e, + show_undocumented=3DTrue)) + + def visit_object_type(self, name, info, base, members, variants): + doc =3D self.cur_doc + if not variants: + typ =3D 'Struct' + elif variants._tag_name: # TODO unclean member access + typ =3D 'Flat Union' + else: + typ =3D 'Simple Union' + if self.out: + self.out +=3D '\n' + self.out +=3D TYPE_FMT(type=3Dtyp, + name=3Ddoc.symbol, + body=3Dtexi_entity(doc)) + + def visit_alternate_type(self, name, info, variants): + doc =3D self.cur_doc + if self.out: + self.out +=3D '\n' + self.out +=3D TYPE_FMT(type=3D'Alternate', + name=3Ddoc.symbol, + body=3Dtexi_entity(doc)) + + def visit_command(self, name, info, arg_type, ret_type, + gen, success_response, boxed): + doc =3D self.cur_doc + if self.out: + self.out +=3D '\n' + self.out +=3D MSG_FMT(type=3D'Command', + name=3Ddoc.symbol, + body=3Dtexi_entity(doc)) + + def visit_event(self, name, info, arg_type, boxed): + doc =3D self.cur_doc + if self.out: + self.out +=3D '\n' + self.out +=3D MSG_FMT(type=3D'Event', + name=3Ddoc.symbol, + body=3Dtexi_entity(doc)) + + def symbol(self, doc, entity): + self.cur_doc =3D doc + entity.visit(self) + self.cur_doc =3D None + + def freeform(self, doc): + assert not doc.args + if self.out: + self.out +=3D '\n' + self.out +=3D texi_body(doc) + texi_sections(doc) + + +def texi_schema(schema): + """Convert QAPI schema documentation to Texinfo""" + gen =3D QAPISchemaGenDocVisitor() + gen.visit_begin(schema) + for doc in schema.docs: + if doc.symbol: + gen.symbol(doc, schema.lookup_entity(doc.symbol)) + else: + gen.freeform(doc) + return gen.out =20 =20 def main(argv): @@ -259,7 +267,7 @@ def main(argv): if not qapi.doc_required: print >>sys.stderr, ("%s: need pragma 'doc-required' " "to generate documentation" % argv[0]) - print texi(schema.docs) + print texi_schema(schema) =20 =20 if __name__ =3D=3D "__main__": --=20 2.7.4