From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567024368; cv=none; d=zoho.com; s=zohoarc; b=dDUTBk2zqqj7t34xFao08VSeIS2RI1oKBhTh2mfgbzDCsieeQ7MMsPVrJ8/zh8ILjNNP1P1HCQwV8fKmoWlZJRpIVxmSc8oSTZZjkX/o4VXTukU76IfXFRl7g6ZYxyl3LPFPN0D090cwqYq9kcZReoOLIAfv5n9lg0H+43oeyqU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567024368; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=fuei9EQQ6N0XzYBntImXtYCaUKd0eBTnmWDfA+cagKs=; b=FWIYqmworrS7e2+ZLc2WVCrdyqCuk2NMWUDlFikMkh6OZcs2ctnxUA/YejrfbLjMlvuIyVqSpjv0li1ZlcDTzcutBNAZJW+lncd4J+cZBzyDtyOXXcDyVqXj5Rs5Tlc3cR/YLUetoAsq5/I+dsIZw+qYLTZyCVFJd8+mRZBBVMw= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1567024368342103.78169938492988; Wed, 28 Aug 2019 13:32:48 -0700 (PDT) Received: from localhost ([::1]:42442 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34cW-00009x-L1 for importer@patchew.org; Wed, 28 Aug 2019 16:32:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51806) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wk-0003cb-FL for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wj-0002m9-0Y for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58208) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wi-0002l9-Ma for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:44 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 333FD3083363; Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0023319D7A; Wed, 28 Aug 2019 20:26:42 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 6E01A1165362; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:33 +0200 Message-Id: <20190828202641.24752-2-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 1/9] qapi: Drop check_type()'s redundant parameter @allow_optional X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" check_type() uses @allow_optional only when @value is a dictionary and @allow_dict is True. All callers that pass allow_dict=3DTrue also pass allow_optional=3DTrue. Therefore, @allow_optional is always True when check_type() uses it. Drop the redundant parameter. Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index d61bfdc526..9aefcfe015 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -783,9 +783,8 @@ def check_if(expr, info): check_if_str(ifcond, info) =20 =20 -def check_type(info, source, value, allow_array=3DFalse, - allow_dict=3DFalse, allow_optional=3DFalse, - allow_metas=3D[]): +def check_type(info, source, value, + allow_array=3DFalse, allow_dict=3DFalse, allow_metas=3D[]): global all_names =20 if value is None: @@ -821,7 +820,7 @@ def check_type(info, source, value, allow_array=3DFalse, # value is a dictionary, check that each member is okay for (key, arg) in value.items(): check_name(info, "Member of %s" % source, key, - allow_optional=3Dallow_optional) + allow_optional=3DTrue) if c_name(key, False) =3D=3D 'u' or c_name(key, False).startswith(= 'has_'): raise QAPISemError(info, "Member of %s uses reserved name '%s'" % (source, key)) @@ -843,14 +842,14 @@ def check_command(expr, info): if boxed: args_meta +=3D ['union', 'alternate'] check_type(info, "'data' for command '%s'" % name, - expr.get('data'), allow_dict=3Dnot boxed, allow_optional=3D= True, + expr.get('data'), allow_dict=3Dnot boxed, allow_metas=3Dargs_meta) returns_meta =3D ['union', 'struct'] if name in returns_whitelist: returns_meta +=3D ['built-in', 'alternate', 'enum'] check_type(info, "'returns' for command '%s'" % name, expr.get('returns'), allow_array=3DTrue, - allow_optional=3DTrue, allow_metas=3Dreturns_meta) + allow_metas=3Dreturns_meta) =20 =20 def check_event(expr, info): @@ -861,7 +860,7 @@ def check_event(expr, info): if boxed: meta +=3D ['union', 'alternate'] check_type(info, "'data' for event '%s'" % name, - expr.get('data'), allow_dict=3Dnot boxed, allow_optional=3D= True, + expr.get('data'), allow_dict=3Dnot boxed, allow_metas=3Dmeta) =20 =20 @@ -889,7 +888,7 @@ def check_union(expr, info): else: # The object must have a string or dictionary 'base'. check_type(info, "'base' for union '%s'" % name, - base, allow_dict=3DTrue, allow_optional=3DTrue, + base, allow_dict=3DTrue, allow_metas=3D['struct']) if not base: raise QAPISemError(info, "Flat union '%s' must have a base" @@ -1012,7 +1011,7 @@ def check_struct(expr, info): features =3D expr.get('features') =20 check_type(info, "'data' for struct '%s'" % name, members, - allow_dict=3DTrue, allow_optional=3DTrue) + allow_dict=3DTrue) check_type(info, "'base' for struct '%s'" % name, expr.get('base'), allow_metas=3D['struct']) =20 --=20 2.21.0 From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567025299; cv=none; d=zoho.com; s=zohoarc; b=BQOEgOsx7hVzCFrReXhe572P/rUdJpyNQnuEiaukcRlcCRc4so0AvTJr8tsVWKedeh6A1d8UzYUuBC9/wMl78q2bxXYdeMj3zQeiVpKRxTBOHNwq1BljAuaIqr+63Q1CQRcswUqD76K+oKqI9k/7/QeDclLR08aU7CQX2XFurfE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567025299; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=273MhUlZBn6ZL8lIbMpjRL1oD3gPNseRj8sPYlB2ViI=; b=n2HZwk1q20F15cxgzzCd/hQgWI8ra0KD/XDVef99SSv46CWtMuso73N6d93HxYQHanSUABAnrYjDq4sAL7bGlcNR+/W6El9F1J2+kyFWt8b8ALbo7u5AHi0h3QG8rEckmz35xFZD7610pNpX17w7RLng/c9UvcqAYFmb6WBMX78= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1567025299871714.5773184570172; Wed, 28 Aug 2019 13:48:19 -0700 (PDT) Received: from localhost ([::1]:42672 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34rY-0007v3-Hf for importer@patchew.org; Wed, 28 Aug 2019 16:48:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51819) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wk-0003dB-U4 for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wj-0002m2-0B for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36788) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wi-0002lF-Mt for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:44 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 68CEF3082145; Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 08D461001B07; Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 70DBE116536A; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:34 +0200 Message-Id: <20190828202641.24752-3-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 2/9] qapi: Drop support for boxed alternate for commands, events X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Commands and events can define their argument type inline (default) or by referring to another type ('boxed': true, since commit c818408e44 "qapi: Implement boxed types for commands/events", v2.7.0). The unboxed inline definition is an (anonymous) struct type. The boxed type may be a struct, union, or alternate type. The latter is problematic: docs/interop/qemu-spec.txt requires the value of the 'data' key to be a json-object, but any non-degenerate alternate type has at least one branch that isn't. Fortunately, we haven't made use of alternates in this context outside tests/. Drop support for them. QAPISchemaAlternateType.is_empty() is now unused. Drop it, too. Signed-off-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 12 ++++++------ tests/qapi-schema/qapi-schema-test.json | 2 +- scripts/qapi/common.py | 7 ++----- tests/qapi-schema/qapi-schema-test.out | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index e8ec8ac1de..3d3931fb7a 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -612,9 +612,9 @@ the command. Normally, 'data' is a dictionary for an a= nonymous type, or names a struct type (possibly empty, but not a union), and its members are passed as separate arguments to this function. If the command definition includes a key 'boxed' with the boolean value true, -then 'data' is instead the name of any non-empty complex type -(struct, union, or alternate), and a pointer to that QAPI type is -passed as a single argument. +then 'data' is instead the name of any non-empty complex type (struct +or union), and a pointer to that QAPI type is passed as a single +argument. =20 The generator also emits a marshalling function that extracts arguments for the user's function out of an input QDict, calls the @@ -714,9 +714,9 @@ The generator emits a function to send the event. Norm= ally, 'data' is a dictionary for an anonymous type, or names a struct type (possibly empty, but not a union), and its members are passed as separate arguments to this function. If the event definition includes a key -'boxed' with the boolean value true, then 'data' is instead the name of -any non-empty complex type (struct, union, or alternate), and a -pointer to that QAPI type is passed as a single argument. +'boxed' with the boolean value true, then 'data' is instead the name +of any non-empty complex type (struct or union), and a pointer to that +QAPI type is passed as a single argument. =20 =20 =3D=3D=3D Features =3D=3D=3D diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qa= pi-schema-test.json index c6d59acc3e..0fadb4ddd7 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -180,7 +180,7 @@ { 'event': 'EVENT_D', 'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'E= numOne' } } { 'event': 'EVENT_E', 'boxed': true, 'data': 'UserDefZero' } -{ 'event': 'EVENT_F', 'boxed': true, 'data': 'UserDefAlternate' } +{ 'event': 'EVENT_F', 'boxed': true, 'data': 'UserDefFlatUnion' } =20 # test that we correctly compile downstream extensions, as well as munge # ticklish names diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 9aefcfe015..c54c148263 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -840,7 +840,7 @@ def check_command(expr, info): =20 args_meta =3D ['struct'] if boxed: - args_meta +=3D ['union', 'alternate'] + args_meta +=3D ['union'] check_type(info, "'data' for command '%s'" % name, expr.get('data'), allow_dict=3Dnot boxed, allow_metas=3Dargs_meta) @@ -858,7 +858,7 @@ def check_event(expr, info): =20 meta =3D ['struct'] if boxed: - meta +=3D ['union', 'alternate'] + meta +=3D ['union'] check_type(info, "'data' for event '%s'" % name, expr.get('data'), allow_dict=3Dnot boxed, allow_metas=3Dmeta) @@ -1690,9 +1690,6 @@ class QAPISchemaAlternateType(QAPISchemaType): visitor.visit_alternate_type(self.name, self.info, self.ifcond, self.variants) =20 - def is_empty(self): - return False - =20 class QAPISchemaCommand(QAPISchemaEntity): def __init__(self, name, info, doc, ifcond, arg_type, ret_type, diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qap= i-schema-test.out index 85d510bc00..5470a525f5 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -252,7 +252,7 @@ event EVENT_D q_obj_EVENT_D-arg boxed=3DFalse event EVENT_E UserDefZero boxed=3DTrue -event EVENT_F UserDefAlternate +event EVENT_F UserDefFlatUnion boxed=3DTrue enum __org.qemu_x-Enum member __org.qemu_x-value --=20 2.21.0 From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567025413; cv=none; d=zoho.com; s=zohoarc; b=jh+N/TJPmxWjnw8vT+O5kINKpmj8Yf3vQur2GrWGibdYyjJ3lD8eJj38g4JrQYvvkdjHMybnvHfPsIC6AW8FMqxIbzub2bZWA245WonWK7psdr9kOHLYqAH+S9qH2rbvkIuGfIwwnELIBZ/kOLuYVi3Sfso5pj11PUC8FJfgYCU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567025413; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=UgS3DGmxTExATRi7O3GIXdZv+0eN9ZTg7y4uUVAeuEE=; b=HcgV2xv1BUXyh6B9PoZUtZUzBu7T+Xsi++oF+L720TjjiN9P8KK9mPKEHIddy5x1oIe7ffhG7V3KQWHG3+Jo0SWYVedCV1k/F7Y5uvc9SDL6ISFbA/9lOWpcESOp4AnoqgyQrD325YyoxcWk6sv7QI2v9O6MtfqFMy1uGHPckGY= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 156702541332672.076011943053; Wed, 28 Aug 2019 13:50:13 -0700 (PDT) Received: from localhost ([::1]:42686 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34tP-0001KP-VV for importer@patchew.org; Wed, 28 Aug 2019 16:50:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51820) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wk-0003dD-Vj for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wj-0002mE-0a for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59972) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wi-0002lE-Mk for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:44 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 66C70811D8; Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 08E9360BF7; Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7441E116560E; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:35 +0200 Message-Id: <20190828202641.24752-4-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 3/9] docs/devel/qapi-code-gen: Minor specification fixes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" The specification claims "Each expression that isn't an include directive may be preceded by a documentation block", but the code also rejects them for pragma directives. The code is correct. Fix the specification. The specification claims "The string 'max' is not allowed as an enum value". Untrue. Fix the specification. While there, delete the naming advice, because it's redundant with the naming rules in section "Schema overview" The specification claims "No branch of the union can be named 'max', as this would collide with the implicit enum". Untrue. Fix the specification. The specification claims "It is not allowed to name an event 'MAX', since the generator also produces a C enumeration of all event names with a generated _MAX value at the end." Untrue. Fix the specification. The specification claims "All branches of the union must be complex types", but the code permits only struct types. The code is correct. Fix the specification. The specification claims a command's return type "must be the string name of a complex or built-in type, a one-element array containing the name of a complex or built-in type" unless the command is in pragma 'returns-whitelist'. The code does not permit built-in types. Fix the specification. Signed-off-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 3d3931fb7a..0373c1322c 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -117,9 +117,9 @@ Example: =20 =3D=3D=3D=3D Expression documentation =3D=3D=3D=3D =20 -Each expression that isn't an include directive may be preceded by a -documentation block. Such blocks are called expression documentation -blocks. +Expressions other than include and pragma directives may be preceded +by a documentation block. Such blocks are called expression +documentation blocks. =20 When documentation is required (see pragma 'doc-required'), expression documentation blocks are mandatory. @@ -398,10 +398,10 @@ whose value is a list of strings. An example enumera= tion is: =20 { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] } =20 +The strings must be distinct. + Nothing prevents an empty enumeration, although it is probably not -useful. The list of strings should be lower case; if an enum name -represents multiple words, use '-' between words. The string 'max' is -not allowed as an enum value, and values should not be repeated. +useful. =20 The enum constants will be named by using a heuristic to turn the type name into a set of underscore separated words. For the example @@ -460,15 +460,14 @@ discriminator value, as in these examples: =20 The generated C code uses a struct containing a union. Additionally, an implicit C enum 'NameKind' is created, corresponding to the union -'Name', for accessing the various branches of the union. No branch of -the union can be named 'max', as this would collide with the implicit -enum. The value for each branch can be of any type. +'Name', for accessing the various branches of the union. The value +for each branch can be of any type. =20 A flat union definition avoids nesting on the wire, and specifies a set of common members that occur in all variants of the union. The 'base' key must specify either a type name (the type must be a struct, not a union), or a dictionary representing an anonymous type. -All branches of the union must be complex types, and the top-level +All branches of the union must be struct types, and the top-level members of the union dictionary on the wire will be combination of members from both the base type and the appropriate branch type (when merging two dictionaries, there must be no keys in common). The @@ -578,8 +577,8 @@ The 'returns' member describes what will appear in the = "return" member of a Client JSON Protocol reply on successful completion of a command. The member is optional from the command declaration; if absent, the "return" member will be an empty dictionary. If 'returns' is present, -it must be the string name of a complex or built-in type, a -one-element array containing the name of a complex or built-in type. +it must be the string name of a complex type, or a +one-element array containing the name of a complex. To return anything else, you have to list the command in pragma 'returns-whitelist'. If you do this, the command cannot be extended to return additional information in the future. Use of @@ -691,13 +690,11 @@ started with --preconfig. Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT, '*boxed': true } =20 -Events are defined with the keyword 'event'. It is not allowed to -name an event 'MAX', since the generator also produces a C enumeration -of all event names with a generated _MAX value at the end. When -'data' is also specified, additional info will be included in the -event, with similar semantics to a 'struct' expression. Finally there -will be C API generated in qapi-events.h; when called by QEMU code, a -message with timestamp will be emitted on the wire. +Events are defined with the keyword 'event'. When 'data' is also +specified, additional info will be included in the event, with similar +semantics to a 'struct' expression. Finally there will be C API +generated in qapi-events.h; when called by QEMU code, a message with +timestamp will be emitted on the wire. =20 An example event is: =20 --=20 2.21.0 From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567024389; cv=none; d=zoho.com; s=zohoarc; b=WIGbdtmZDt0pq0yQy2uza4GPNjnnqp5omtNaP3WyQwzqaEUG3rTCQzjMcq53jor0OYhSRCMmEylCvmI/kTCEOHisfgVUsFZZDE+HhRTgdmNycHsKB8gY604021y67a5EONhB3hjj2Ru5+6KxA+wcy+t7I6qL/msnrEFmQfNNbz0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567024389; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=BeNmaapAtC+JAokEZu053YcG2sMLL2aWx9S9uNsK+A4=; b=PiZy+H1qRoY7V6+RkNgLdCcITqqY/wo4UZJyneumHrI7iWvVDvRL/lf2uQV6aRNmvy/16upbxgTh4f0ecnoicNw8tbf9tLoKaytSjwS6wVqkwesvSEhAgpAjhngBEiM34SHd8kyDv0oUcvuMWEYRg0yh1+mc1uiCJkxkVa51Mjk= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1567024389094241.9394296418244; Wed, 28 Aug 2019 13:33:09 -0700 (PDT) Received: from localhost ([::1]:42452 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34ct-0000bb-1u for importer@patchew.org; Wed, 28 Aug 2019 16:33:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51810) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wk-0003cm-IW for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wj-0002mJ-20 for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35084) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wi-0002l8-Mi for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:44 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 41BDD4E93D; Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0DAE8196B2; Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 776BB1165612; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:36 +0200 Message-Id: <20190828202641.24752-5-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Wed, 28 Aug 2019 20:26:43 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 4/9] qapi: Outlaw control characters in strings X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" RFC 8259 on string contents: All Unicode characters may be placed within the quotation marks, except for the characters that MUST be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F). The QAPI schema parser accepts both less and more than JSON: it accepts only ASCII (less), and accepts control characters other than LF (new line) unescaped. Make it accept strictly less: require control characters to be escaped. All of them, even DEL, because treating DEL different than other control characters feels wrong. Signed-off-by: Markus Armbruster --- tests/qapi-schema/string-control.json | 2 ++ scripts/qapi/common.py | 3 +++ tests/Makefile.include | 1 + tests/qapi-schema/string-control.err | 1 + tests/qapi-schema/string-control.exit | 1 + tests/qapi-schema/string-control.out | 0 6 files changed, 8 insertions(+) create mode 100644 tests/qapi-schema/string-control.json create mode 100644 tests/qapi-schema/string-control.err create mode 100644 tests/qapi-schema/string-control.exit create mode 100644 tests/qapi-schema/string-control.out diff --git a/tests/qapi-schema/string-control.json b/tests/qapi-schema/stri= ng-control.json new file mode 100644 index 0000000000..a14be4659a --- /dev/null +++ b/tests/qapi-schema/string-control.json @@ -0,0 +1,2 @@ +# control characters in strings +{ 'command': '=7F=0C' } diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index c54c148263..d8c47ac2ac 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -564,6 +564,9 @@ class QAPISchemaParser(object): elif ch =3D=3D "'": self.val =3D string return + elif ord(ch) < 32 or ch =3D=3D '\x7f': + raise QAPIParseError(self, + 'Control character in string') else: string +=3D ch elif self.src.startswith('true', self.pos): diff --git a/tests/Makefile.include b/tests/Makefile.include index 49684fd4f4..543bac6f93 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -452,6 +452,7 @@ qapi-schema +=3D returns-array-bad.json qapi-schema +=3D returns-dict.json qapi-schema +=3D returns-unknown.json qapi-schema +=3D returns-whitelist.json +qapi-schema +=3D string-control.json qapi-schema +=3D struct-base-clash-deep.json qapi-schema +=3D struct-base-clash.json qapi-schema +=3D struct-data-invalid.json diff --git a/tests/qapi-schema/string-control.err b/tests/qapi-schema/strin= g-control.err new file mode 100644 index 0000000000..30a9d57d57 --- /dev/null +++ b/tests/qapi-schema/string-control.err @@ -0,0 +1 @@ +tests/qapi-schema/string-control.json:2:14: Control character in string diff --git a/tests/qapi-schema/string-control.exit b/tests/qapi-schema/stri= ng-control.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/string-control.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/string-control.out b/tests/qapi-schema/strin= g-control.out new file mode 100644 index 0000000000..e69de29bb2 --=20 2.21.0 From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567025530; cv=none; d=zoho.com; s=zohoarc; b=Bu5jOcmXrS8ohAJUouQgdXp8c7Vo6NGRTvFXFSdHywqx2g5bC0b+V+WQO/0Xo9SF50a1+CF0223Gkr+Luh9qu9T5JSAoIyU6Y5IzUs/gk2wBi3JE45Ek/K7v4QeRPnFb+aNIH6HjlBU5Esc6f2do/xu8qQyKtpc4siFmSHRq+aE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567025530; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=OxipjGuD5WurOk1CpNjxHPV+fvI9MQMouPJYUIlpoHU=; b=fwwEsERiAkygB0Ker6RSHaWw55cMj4ENsSPEHtGXDA4Hgs25QSDdG4Lhfg8lqMNlTp17FZ2Y5qjvXB3UVRpJ0Q2vJ8y1dTCm9s+NZnZLHYVzuTaPJRXqTUq//iG5mWHBe+Lv7VJTpJBjVHO0ri2v96HtaqWXop1mIKnr7Rthgqw= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1567025530440212.67883564465842; Wed, 28 Aug 2019 13:52:10 -0700 (PDT) Received: from localhost ([::1]:42706 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34vJ-0002o4-A2 for importer@patchew.org; Wed, 28 Aug 2019 16:52:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51883) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wn-0003gk-Ns for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wk-0002oX-Sl for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43714) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wk-0002n6-IM for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:46 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BE979875219; Wed, 28 Aug 2019 20:26:45 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8DC425C1D6; Wed, 28 Aug 2019 20:26:44 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7AC011165613; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:37 +0200 Message-Id: <20190828202641.24752-6-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.68]); Wed, 28 Aug 2019 20:26:45 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 5/9] tests/qapi-schema: Consistently name string tests string-FOO X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Signed-off-by: Markus Armbruster --- .../{unclosed-string.json =3D> string-unclosed.json} | 0 tests/qapi-schema/{unicode-str.json =3D> string-unicode.json} | 0 tests/Makefile.include | 4 ++-- tests/qapi-schema/string-unclosed.err | 1 + .../{unclosed-string.exit =3D> string-unclosed.exit} | 0 .../qapi-schema/{unclosed-string.out =3D> string-unclosed.out} | 0 tests/qapi-schema/string-unicode.err | 1 + tests/qapi-schema/{unicode-str.exit =3D> string-unicode.exit} | 0 tests/qapi-schema/{unicode-str.out =3D> string-unicode.out} | 0 tests/qapi-schema/unclosed-string.err | 1 - tests/qapi-schema/unicode-str.err | 1 - 11 files changed, 4 insertions(+), 4 deletions(-) rename tests/qapi-schema/{unclosed-string.json =3D> string-unclosed.json} = (100%) rename tests/qapi-schema/{unicode-str.json =3D> string-unicode.json} (100%) create mode 100644 tests/qapi-schema/string-unclosed.err rename tests/qapi-schema/{unclosed-string.exit =3D> string-unclosed.exit} = (100%) rename tests/qapi-schema/{unclosed-string.out =3D> string-unclosed.out} (1= 00%) create mode 100644 tests/qapi-schema/string-unicode.err rename tests/qapi-schema/{unicode-str.exit =3D> string-unicode.exit} (100%) rename tests/qapi-schema/{unicode-str.out =3D> string-unicode.out} (100%) delete mode 100644 tests/qapi-schema/unclosed-string.err delete mode 100644 tests/qapi-schema/unicode-str.err diff --git a/tests/qapi-schema/unclosed-string.json b/tests/qapi-schema/str= ing-unclosed.json similarity index 100% rename from tests/qapi-schema/unclosed-string.json rename to tests/qapi-schema/string-unclosed.json diff --git a/tests/qapi-schema/unicode-str.json b/tests/qapi-schema/string-= unicode.json similarity index 100% rename from tests/qapi-schema/unicode-str.json rename to tests/qapi-schema/string-unicode.json diff --git a/tests/Makefile.include b/tests/Makefile.include index 543bac6f93..af1baca936 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -453,6 +453,8 @@ qapi-schema +=3D returns-dict.json qapi-schema +=3D returns-unknown.json qapi-schema +=3D returns-whitelist.json qapi-schema +=3D string-control.json +qapi-schema +=3D string-unclosed.json +qapi-schema +=3D string-unicode.json qapi-schema +=3D struct-base-clash-deep.json qapi-schema +=3D struct-base-clash.json qapi-schema +=3D struct-data-invalid.json @@ -463,8 +465,6 @@ qapi-schema +=3D trailing-comma-object.json qapi-schema +=3D type-bypass-bad-gen.json qapi-schema +=3D unclosed-list.json qapi-schema +=3D unclosed-object.json -qapi-schema +=3D unclosed-string.json -qapi-schema +=3D unicode-str.json qapi-schema +=3D union-base-empty.json qapi-schema +=3D union-base-no-discriminator.json qapi-schema +=3D union-branch-case.json diff --git a/tests/qapi-schema/string-unclosed.err b/tests/qapi-schema/stri= ng-unclosed.err new file mode 100644 index 0000000000..bc6c00a0ec --- /dev/null +++ b/tests/qapi-schema/string-unclosed.err @@ -0,0 +1 @@ +tests/qapi-schema/string-unclosed.json:1:11: Missing terminating "'" diff --git a/tests/qapi-schema/unclosed-string.exit b/tests/qapi-schema/str= ing-unclosed.exit similarity index 100% rename from tests/qapi-schema/unclosed-string.exit rename to tests/qapi-schema/string-unclosed.exit diff --git a/tests/qapi-schema/unclosed-string.out b/tests/qapi-schema/stri= ng-unclosed.out similarity index 100% rename from tests/qapi-schema/unclosed-string.out rename to tests/qapi-schema/string-unclosed.out diff --git a/tests/qapi-schema/string-unicode.err b/tests/qapi-schema/strin= g-unicode.err new file mode 100644 index 0000000000..9a1bb0bc22 --- /dev/null +++ b/tests/qapi-schema/string-unicode.err @@ -0,0 +1 @@ +tests/qapi-schema/string-unicode.json:2: 'command' uses invalid name '=C3= =A9' diff --git a/tests/qapi-schema/unicode-str.exit b/tests/qapi-schema/string-= unicode.exit similarity index 100% rename from tests/qapi-schema/unicode-str.exit rename to tests/qapi-schema/string-unicode.exit diff --git a/tests/qapi-schema/unicode-str.out b/tests/qapi-schema/string-u= nicode.out similarity index 100% rename from tests/qapi-schema/unicode-str.out rename to tests/qapi-schema/string-unicode.out diff --git a/tests/qapi-schema/unclosed-string.err b/tests/qapi-schema/uncl= osed-string.err deleted file mode 100644 index 12b187074e..0000000000 --- a/tests/qapi-schema/unclosed-string.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/unclosed-string.json:1:11: Missing terminating "'" diff --git a/tests/qapi-schema/unicode-str.err b/tests/qapi-schema/unicode-= str.err deleted file mode 100644 index f621cd6448..0000000000 --- a/tests/qapi-schema/unicode-str.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/unicode-str.json:2: 'command' uses invalid name '=C3=A9' --=20 2.21.0 From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567025650; cv=none; d=zoho.com; s=zohoarc; b=fXaCGgiHVsv4oMx432AY2iWFx+gbfAgDKhNpKFzeX4Ta891QKaczxo2jwIo+19ljnorus+TgorOlltkqEyEK2SP1Us+dBqvIN8mLPSn+J5H2oARcPVmw3ixf9YtsrOmO5GBgpimFjIWiNRpqr8GwThCfefpX2kfF/VohrvWL9/4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567025650; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=7QIGQuv4AdeXXRghPEr2mLcKITwQ50d4aIC9oUDI4nk=; b=TOMJcLS5ouSWXHeNdwEJzBfk9nRyujV9A9qlvn50Gr9iZ7gAVdRYHidAfc9bdbDseMhl+49R36H4jf+aWHWeEjASSgSnUj/oZ2tPDUlTv3vuZ0MM22GQsjUTl5XiJ7IkUb+gOmxqRRWN0Gmw86PRyfosJlM1gQsOaDzSvo/3UsM= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1567025650988409.9422663474684; Wed, 28 Aug 2019 13:54:10 -0700 (PDT) Received: from localhost ([::1]:42728 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34xB-0004ep-FQ for importer@patchew.org; Wed, 28 Aug 2019 16:54:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51885) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wo-0003hC-2P for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wk-0002oE-Jl for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41574) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wk-0002mx-9c for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:46 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9609D10F23EA; Wed, 28 Aug 2019 20:26:45 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8DC7660BF7; Wed, 28 Aug 2019 20:26:44 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 7E2D61165614; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:38 +0200 Message-Id: <20190828202641.24752-7-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.66]); Wed, 28 Aug 2019 20:26:45 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 6/9] docs/devel/qapi-code-gen: Reorder sections for readability X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Section "QMP/Guest agent schema" starts with a brief introduction, then subsection "Comments", then subsection "Schema overview" (more elaborate introduction), and only then talks about schema entities like types, commands, and so forth. Subsection "Comments" is long and tiring: almost 500 words, mostly about doc comments. Move the doc comment part to its own subsection "Documentation comments" at the very end of "QMP/Guest agent schema". Subsection "Schema overview" explains naming rules at considerable length: 250 words. Move this part to its own subsection "Naming rules and reserved names" right after the subsections on schema entities. Subsection "Enumeration types" is wedged between "Struct types" and "Union types". Move it before "Struct types". Signed-off-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 434 ++++++++++++++++++----------------- 1 file changed, 220 insertions(+), 214 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 0373c1322c..ca9915e5f0 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -50,147 +50,6 @@ schema requires the use of JSON numbers or null. Comments are allowed; anything between an unquoted # and the following newline is ignored. =20 -A multi-line comment that starts and ends with a '##' line is a -documentation comment. These are parsed by the documentation -generator, which recognizes certain markup detailed below. - - -=3D=3D=3D=3D Documentation markup =3D=3D=3D=3D - -Comment text starting with '=3D' is a section title: - - # =3D Section title - -Double the '=3D' for a subsection title: - - # =3D=3D Subsection title - -'|' denotes examples: - - # | Text of the example, may span - # | multiple lines - -'*' starts an itemized list: - - # * First item, may span - # multiple lines - # * Second item - -You can also use '-' instead of '*'. - -A decimal number followed by '.' starts a numbered list: - - # 1. First item, may span - # multiple lines - # 2. Second item - -The actual number doesn't matter. You could even use '*' instead of -'2.' for the second item. - -Lists can't be nested. Blank lines are currently not supported within -lists. - -Additional whitespace between the initial '#' and the comment text is -permitted. - -*foo* and _foo_ are for strong and emphasis styles respectively (they -do not work over multiple lines). @foo is used to reference a name in -the schema. - -Example: - -## -# =3D Section -# =3D=3D Subsection -# -# Some text foo with *strong* and _emphasis_ -# 1. with a list -# 2. like that -# -# And some code: -# | $ echo foo -# | -> do this -# | <- get that -# -## - - -=3D=3D=3D=3D Expression documentation =3D=3D=3D=3D - -Expressions other than include and pragma directives may be preceded -by a documentation block. Such blocks are called expression -documentation blocks. - -When documentation is required (see pragma 'doc-required'), expression -documentation blocks are mandatory. - -The documentation block consists of a first line naming the -expression, an optional overview, a description of each argument (for -commands and events) or member (for structs, unions and alternates), -and optional tagged sections. - -FIXME: the parser accepts these things in almost any order. - -Extensions added after the expression was first released carry a -'(since x.y.z)' comment. - -A tagged section starts with one of the following words: -"Note:"/"Notes:", "Since:", "Example"/"Examples", "Returns:", "TODO:". -The section ends with the start of a new section. - -A 'Since: x.y.z' tagged section lists the release that introduced the -expression. - -For example: - -## -# @BlockStats: -# -# Statistics of a virtual block device or a block backing device. -# -# @device: If the stats are for a virtual block device, the name -# corresponding to the virtual block device. -# -# @node-name: The node name of the device. (since 2.3) -# -# ... more members ... -# -# Since: 0.14.0 -## -{ 'struct': 'BlockStats', - 'data': {'*device': 'str', '*node-name': 'str', - ... more members ... } } - -## -# @query-blockstats: -# -# Query the @BlockStats for all virtual block devices. -# -# @query-nodes: If true, the command will query all the -# block nodes ... explain, explain ... (since 2.3) -# -# Returns: A list of @BlockStats for each virtual block devices. -# -# Since: 0.14.0 -# -# Example: -# -# -> { "execute": "query-blockstats" } -# <- { -# ... lots of output ... -# } -# -## -{ 'command': 'query-blockstats', - 'data': { '*query-nodes': 'bool' }, - 'returns': ['BlockStats'] } - -=3D=3D=3D=3D Free-form documentation =3D=3D=3D=3D - -A documentation block that isn't an expression documentation block is -a free-form documentation block. These may be used to provide -additional text and structuring content. - =20 =3D=3D=3D Schema overview =3D=3D=3D =20 @@ -217,42 +76,6 @@ refers to a single-dimension array of that type; multi-= dimension arrays are not directly supported (although an array of a complex struct that contains an array member is possible). =20 -All names must begin with a letter, and contain only ASCII letters, -digits, hyphen, and underscore. There are two exceptions: enum values -may start with a digit, and names that are downstream extensions (see -section Downstream extensions) start with underscore. - -Names beginning with 'q_' are reserved for the generator, which uses -them for munging QMP names that resemble C keywords or other -problematic strings. For example, a member named "default" in qapi -becomes "q_default" in the generated C code. - -Types, commands, and events share a common namespace. Therefore, -generally speaking, type definitions should always use CamelCase for -user-defined type names, while built-in types are lowercase. - -Type names ending with 'Kind' or 'List' are reserved for the -generator, which uses them for implicit union enums and array types, -respectively. - -Command names, and member names within a type, should be all lower -case with words separated by a hyphen. However, some existing older -commands and complex types use underscore; when extending such -expressions, consistency is preferred over blindly avoiding -underscore. - -Event names should be ALL_CAPS with words separated by underscore. - -Member names starting with 'has-' or 'has_' are reserved for the -generator, which uses them for tracking optional members. - -Any name (command, event, type, member, or enum value) beginning with -"x-" is marked experimental, and may be withdrawn or changed -incompatibly in a future release. - -Pragma 'name-case-whitelist' lets you violate the rules on use of -upper and lower case. Use for new code is strongly discouraged. - In the rest of this document, usage lines are given for each expression type, with literal strings written in lower case and placeholders written in capitals. If a literal string includes a @@ -327,6 +150,43 @@ Pragma 'name-case-whitelist' takes a list of names tha= t may violate rules on use of upper- vs. lower-case letters. Default is none. =20 =20 +=3D=3D=3D Enumeration types =3D=3D=3D + +Usage: { 'enum': STRING, 'data': ARRAY-OF-STRING } + { 'enum': STRING, '*prefix': STRING, 'data': ARRAY-OF-STRING } + +An enumeration type is a dictionary containing a single 'data' key +whose value is a list of strings. An example enumeration is: + + { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] } + +The strings must be distinct. + +Nothing prevents an empty enumeration, although it is probably not +useful. + +The enum constants will be named by using a heuristic to turn the +type name into a set of underscore separated words. For the example +above, 'MyEnum' will turn into 'MY_ENUM' giving a constant name +of 'MY_ENUM_VALUE1' for the first value. If the default heuristic +does not result in a desirable name, the optional 'prefix' member +can be used when defining the enum. + +The enumeration values are passed as strings over the Client JSON +Protocol, but are encoded as C enum integral values in generated code. +While the C code starts numbering at 0, it is better to use explicit +comparisons to enum values than implicit comparisons to 0; the C code +will also include a generated enum member ending in _MAX for tracking +the size of the enum, useful when using common functions for +converting between strings and enum values. Since the wire format +always passes by name, it is acceptable to reorder or add new +enumeration members in any location without breaking clients of Client +JSON Protocol; however, removing enum values would break +compatibility. For any struct that has a member that will only contain +a finite set of string values, using an enum type for that member is +better than open-coding the member to be type 'str'. + + =3D=3D=3D Struct types =3D=3D=3D =20 Usage: { 'struct': STRING, 'data': DICT, '*base': STRUCT-NAME } @@ -388,43 +248,6 @@ both members like this: "backing": "/some/place/my-backing-file" } =20 =20 -=3D=3D=3D Enumeration types =3D=3D=3D - -Usage: { 'enum': STRING, 'data': ARRAY-OF-STRING } - { 'enum': STRING, '*prefix': STRING, 'data': ARRAY-OF-STRING } - -An enumeration type is a dictionary containing a single 'data' key -whose value is a list of strings. An example enumeration is: - - { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] } - -The strings must be distinct. - -Nothing prevents an empty enumeration, although it is probably not -useful. - -The enum constants will be named by using a heuristic to turn the -type name into a set of underscore separated words. For the example -above, 'MyEnum' will turn into 'MY_ENUM' giving a constant name -of 'MY_ENUM_VALUE1' for the first value. If the default heuristic -does not result in a desirable name, the optional 'prefix' member -can be used when defining the enum. - -The enumeration values are passed as strings over the Client JSON -Protocol, but are encoded as C enum integral values in generated code. -While the C code starts numbering at 0, it is better to use explicit -comparisons to enum values than implicit comparisons to 0; the C code -will also include a generated enum member ending in _MAX for tracking -the size of the enum, useful when using common functions for -converting between strings and enum values. Since the wire format -always passes by name, it is acceptable to reorder or add new -enumeration members in any location without breaking clients of Client -JSON Protocol; however, removing enum values would break -compatibility. For any struct that has a member that will only contain -a finite set of string values, using an enum type for that member is -better than open-coding the member to be type 'str'. - - =3D=3D=3D Union types =3D=3D=3D =20 Usage: { 'union': STRING, 'data': DICT } @@ -744,6 +567,45 @@ This expanded form is necessary if you want to make th= e feature conditional (see below in "Configuring the schema"). =20 =20 +=3D=3D=3D Naming rules and reserved names =3D=3D=3D + +All names must begin with a letter, and contain only ASCII letters, +digits, hyphen, and underscore. There are two exceptions: enum values +may start with a digit, and names that are downstream extensions (see +section Downstream extensions) start with underscore. + +Names beginning with 'q_' are reserved for the generator, which uses +them for munging QMP names that resemble C keywords or other +problematic strings. For example, a member named "default" in qapi +becomes "q_default" in the generated C code. + +Types, commands, and events share a common namespace. Therefore, +generally speaking, type definitions should always use CamelCase for +user-defined type names, while built-in types are lowercase. + +Type names ending with 'Kind' or 'List' are reserved for the +generator, which uses them for implicit union enums and array types, +respectively. + +Command names, and member names within a type, should be all lower +case with words separated by a hyphen. However, some existing older +commands and complex types use underscore; when extending such +expressions, consistency is preferred over blindly avoiding +underscore. + +Event names should be ALL_CAPS with words separated by underscore. + +Member names starting with 'has-' or 'has_' are reserved for the +generator, which uses them for tracking optional members. + +Any name (command, event, type, member, or enum value) beginning with +"x-" is marked experimental, and may be withdrawn or changed +incompatibly in a future release. + +Pragma 'name-case-whitelist' lets you violate the rules on use of +upper and lower case. Use for new code is strongly discouraged. + + =3D=3D=3D Downstream extensions =3D=3D=3D =20 QAPI schema names that are externally visible, say in the Client JSON @@ -814,6 +676,150 @@ The presence of 'if' keys in the schema is reflected = through to the introspection output depending on the build configuration. =20 =20 +=3D=3D=3D Documentation comments =3D=3D=3D + +A multi-line comment that starts and ends with a '##' line is a +documentation comment. These are parsed by the documentation +generator, which recognizes certain markup detailed below. + + +=3D=3D=3D=3D Documentation markup =3D=3D=3D=3D + +Comment text starting with '=3D' is a section title: + + # =3D Section title + +Double the '=3D' for a subsection title: + + # =3D=3D Subsection title + +'|' denotes examples: + + # | Text of the example, may span + # | multiple lines + +'*' starts an itemized list: + + # * First item, may span + # multiple lines + # * Second item + +You can also use '-' instead of '*'. + +A decimal number followed by '.' starts a numbered list: + + # 1. First item, may span + # multiple lines + # 2. Second item + +The actual number doesn't matter. You could even use '*' instead of +'2.' for the second item. + +Lists can't be nested. Blank lines are currently not supported within +lists. + +Additional whitespace between the initial '#' and the comment text is +permitted. + +*foo* and _foo_ are for strong and emphasis styles respectively (they +do not work over multiple lines). @foo is used to reference a name in +the schema. + +Example: + +## +# =3D Section +# =3D=3D Subsection +# +# Some text foo with *strong* and _emphasis_ +# 1. with a list +# 2. like that +# +# And some code: +# | $ echo foo +# | -> do this +# | <- get that +# +## + + +=3D=3D=3D=3D Expression documentation =3D=3D=3D=3D + +Expressions other than include and pragma directives may be preceded +by a documentation block. Such blocks are called expression +documentation blocks. + +When documentation is required (see pragma 'doc-required'), expression +documentation blocks are mandatory. + +The documentation block consists of a first line naming the +expression, an optional overview, a description of each argument (for +commands and events) or member (for structs, unions and alternates), +and optional tagged sections. + +FIXME: the parser accepts these things in almost any order. + +Extensions added after the expression was first released carry a +'(since x.y.z)' comment. + +A tagged section starts with one of the following words: +"Note:"/"Notes:", "Since:", "Example"/"Examples", "Returns:", "TODO:". +The section ends with the start of a new section. + +A 'Since: x.y.z' tagged section lists the release that introduced the +expression. + +For example: + +## +# @BlockStats: +# +# Statistics of a virtual block device or a block backing device. +# +# @device: If the stats are for a virtual block device, the name +# corresponding to the virtual block device. +# +# @node-name: The node name of the device. (since 2.3) +# +# ... more members ... +# +# Since: 0.14.0 +## +{ 'struct': 'BlockStats', + 'data': {'*device': 'str', '*node-name': 'str', + ... more members ... } } + +## +# @query-blockstats: +# +# Query the @BlockStats for all virtual block devices. +# +# @query-nodes: If true, the command will query all the +# block nodes ... explain, explain ... (since 2.3) +# +# Returns: A list of @BlockStats for each virtual block devices. +# +# Since: 0.14.0 +# +# Example: +# +# -> { "execute": "query-blockstats" } +# <- { +# ... lots of output ... +# } +# +## +{ 'command': 'query-blockstats', + 'data': { '*query-nodes': 'bool' }, + 'returns': ['BlockStats'] } + +=3D=3D=3D=3D Free-form documentation =3D=3D=3D=3D + +A documentation block that isn't an expression documentation block is +a free-form documentation block. These may be used to provide +additional text and structuring content. + + =3D=3D Client JSON Protocol introspection =3D=3D =20 Clients of a Client JSON Protocol commonly need to figure out what --=20 2.21.0 From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567024584; cv=none; d=zoho.com; s=zohoarc; b=OvpAnPmpmdQoOa2kcOXjX8pZHJziz0XWF+6r5dPi4aXX7GJ5eT2rr+10bnQj+XWHfdw4xJSIYFpjh/IZsrX8XmX28Amv9GLn9cdGieykZfJx335IaqZZg8/2g2txNhKXcM8jvZFbCbu1OCyDTPnNeky1qSkV7EWPB+VgkGgXvEw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567024584; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=ElQs7z7ZYzE/tmLuD1xDDSFx2C3GXg//UvwzjaZOwt8=; b=iRhYpV5aqMJIXVrV3R14VjLeqjLfZ9Eq6OwOIPQ+K7doMfHtQ8CtzpVnl08ssmuKIOH9zfYkdHK86kbRK5qum4zJMfkJUykFJUBZUEj81asTfvKAwQFKTOBHpFzVaMiNo6HQK84+LEOjMMX7sO5Tcd40rLabYSCPgvwaXliOrR0= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 15670245849524.81187117963259; Wed, 28 Aug 2019 13:36:24 -0700 (PDT) Received: from localhost ([::1]:42490 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34g1-0004yu-HQ for importer@patchew.org; Wed, 28 Aug 2019 16:36:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51849) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wl-0003ea-Ut for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wj-0002nA-UE for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53626) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wj-0002mN-Kv for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:45 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EC3B118B3D83; Wed, 28 Aug 2019 20:26:44 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8FD8E6092D; Wed, 28 Aug 2019 20:26:44 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 816D41165615; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:39 +0200 Message-Id: <20190828202641.24752-8-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.63]); Wed, 28 Aug 2019 20:26:44 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 7/9] docs/devel/qapi-code-gen: Rewrite compatibility considerations X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" We have some compatibility advice buried in sections "Enumeration types" and "Struct types". Compatibility is actually about commands and events. It devolves to the types used there. All kinds of types, not just enumerations and structs. Replace the existing advice by a new section "Compatibility considerations". Signed-off-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 95 +++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 35 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index ca9915e5f0..5c9146c92e 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -178,14 +178,11 @@ While the C code starts numbering at 0, it is better = to use explicit comparisons to enum values than implicit comparisons to 0; the C code will also include a generated enum member ending in _MAX for tracking the size of the enum, useful when using common functions for -converting between strings and enum values. Since the wire format -always passes by name, it is acceptable to reorder or add new -enumeration members in any location without breaking clients of Client -JSON Protocol; however, removing enum values would break -compatibility. For any struct that has a member that will only contain -a finite set of string values, using an enum type for that member is -better than open-coding the member to be type 'str'. +converting between strings and enum values. =20 +For any struct that has a member that will only contain a finite set +of string values, using an enum type for that member is better than +open-coding the member to be type 'str'. =20 =3D=3D=3D Struct types =3D=3D=3D =20 @@ -203,34 +200,6 @@ name. An example of a struct is: The use of '*' as a prefix to the name means the member is optional in the corresponding JSON protocol usage. =20 -The default initialization value of an optional argument should not be cha= nged -between versions of QEMU unless the new default maintains backward -compatibility to the user-visible behavior of the old default. - -With proper documentation, this policy still allows some flexibility; for -example, documenting that a default of 0 picks an optimal buffer size allo= ws -one release to declare the optimal size at 512 while another release decla= res -the optimal size at 4096 - the user-visible behavior is not the bytes used= by -the buffer, but the fact that the buffer was optimal size. - -On input structures (only mentioned in the 'data' side of a command), chan= ging -from mandatory to optional is safe (older clients will supply the option, = and -newer clients can benefit from the default); changing from optional to -mandatory is backwards incompatible (older clients may be omitting the opt= ion, -and must continue to work). - -On output structures (only mentioned in the 'returns' side of a command), -changing from mandatory to optional is in general unsafe (older clients ma= y be -expecting the member, and could crash if it is missing), although it -can be done if the only way that the optional argument will be omitted -is when it is triggered by the presence of a new input flag to the -command that older clients don't know to send. Changing from optional -to mandatory is safe. - -A structure that is used in both input and output of various commands -must consider the backwards compatibility constraints of both directions -of use. - A struct definition can specify another struct as its base. In this case, the members of the base type are included as top-level membe= rs of the new struct's dictionary in the Client JSON Protocol wire @@ -1037,6 +1006,62 @@ the names of built-in types. Clients should examine= member "json-type" instead of hard-coding names of built-in types. =20 =20 +=3D=3D Compatibility considerations =3D=3D + +Maintaining backward compatibility at the Client JSON Protocol level +while evolving the schema requires some care. This section is about +syntactic compatibility. Necessary, but not sufficient for actual +compatibility. + +Clients send commands with argument data, and receive command +responses with return data and events with event data. + +Adding opt-in functionality to the send direction is backwards +compatible: adding commands, optional arguments, enumeration values, +union and alternate branches; turning an argument type into an +alternate of that type; making mandatory arguments optional. Clients +oblivious of the new functionality continue to work. + +Incompatible changes include removing commands, command arguments, +enumeration values, union and alternate branches, adding mandatory +command arguments, and making optional arguments mandatory. + +The specified behavior of an absent optional argument should remain +the same. With proper documentation, this policy still allows some +flexibility; for example, when an optional 'buffer-size' argument is +specified to default to a sensible buffer size, the actual default +value can still be changed. The specified default behavior is not the +exact size of the buffer, only that the default size is sensible. + +Adding functionality to the receive direction is generally backwards +compatible: adding events, adding return and event data members. +Clients are expected to ignore the ones they don't know. + +Removing "unreachable" stuff like events that can't be triggered +anymore, optional return or event data members that can't be sent +anymore, and return or event data member (enumeration) values that +can't be sent anymore makes no difference to clients, except for +introspection. The latter can conceivably confuse clients, so tread +carefully. + +Incompatible changes include removing return and event data members. + +Any change to a command definition's 'data' or one of the types used +there (recursively) needs to consider send direction compatibility. + +Any change to a command definition's 'return', an event definition's +'data', or one of the types used there (recursively) needs to consider +receive direction compatibility. + +Any change to types used in both contexts need to consider both. + +Members of enumeration types, complex types and alternate types may be +reordered freely. For enumerations and alternate types, this doesn't +affect the wire encoding. For complex types, this might make the +implementation emit JSON object members in a different order, which +the Client JSON Protocol permits. + + =3D=3D Code generation =3D=3D =20 The QAPI code generator qapi-gen.py generates code and documentation --=20 2.21.0 From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567024567; cv=none; d=zoho.com; s=zohoarc; b=EZ+mxMS4kGA1mxpzhn8xFau4FQhvmu9HKiU8yqqgOh9vI3NwL/+wYJ8gNs4uY+pIYcPrxz6GbJvRyJyNRgNQHJ/A7AQEFpEAC+fzeSs95/s3ivsgGjJpX0ZVi6OU2qOv8BYGJYVvdZ4ZNYRsxO9riWgxflCLGXFVvFc0jTWZALs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567024567; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=pdv0hy/c7WQYemDtkTWcHE1vYqyzjEo2WLM34UBWXBk=; b=O9IlDm/4Vu+IhFoCLd4tB7u7ctbFsACeiG7CDIPoC9xinF3XgWDzoZrw462z4kp5YJtJ6zSu3ywuQ8lkfejlUSqK3jN5hULHYd2/yA0gVDrc6ofLChH0WVtXiI1ZHJz6rVAbgl6y56LtYC+3N89J2zfJV2744F0TOJz5AF3t+Po= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1567024567636236.64279546275736; Wed, 28 Aug 2019 13:36:07 -0700 (PDT) Received: from localhost ([::1]:42482 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34fl-0004eh-Sx for importer@patchew.org; Wed, 28 Aug 2019 16:36:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51859) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wm-0003ex-7v for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wj-0002nF-Uq for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44466) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wj-0002mP-LK for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:45 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F0DBD30842A8; Wed, 28 Aug 2019 20:26:44 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 90008600CD; Wed, 28 Aug 2019 20:26:44 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 84D491165616; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:40 +0200 Message-Id: <20190828202641.24752-9-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Wed, 28 Aug 2019 20:26:45 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 8/9] docs/devel/qapi-code-gen: Rewrite introduction to schema X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" The introduction to the QAPI schema is somewhat rambling. Rewrite for clarity. Signed-off-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 106 ++++++++++++++++------------------- 1 file changed, 47 insertions(+), 59 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 5c9146c92e..4502502531 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -16,65 +16,53 @@ well as the QEMU Guest Agent (QGA) for communicating wi= th the guest. The remainder of this document uses "Client JSON Protocol" when referring to the wire contents of a QMP or QGA connection. =20 -To map Client JSON Protocol interfaces to the native C QAPI -implementations, a JSON-based schema is used to define types and -function signatures, and a set of scripts is used to generate types, -signatures, and marshaling/dispatch code. This document will describe -how the schemas, scripts, and resulting code are used. - - -=3D=3D QMP/Guest agent schema =3D=3D - -A QAPI schema file is designed to be loosely based on JSON -(http://www.ietf.org/rfc/rfc8259.txt) with changes for quoting style -and the use of comments; a QAPI schema file is then parsed by a python -code generation program. A valid QAPI schema consists of a series of -top-level expressions, with no commas between them. Where -dictionaries (JSON objects) are used, they are parsed as python -OrderedDicts so that ordering is preserved (for predictable layout of -generated C structs and parameter lists). Ordering doesn't matter -between top-level expressions or the keys within an expression, but -does matter within dictionary values for 'data' and 'returns' members -of a single expression. QAPI schema input is written using 'single -quotes' instead of JSON's "double quotes" (in contrast, Client JSON -Protocol uses no comments, and while input accepts 'single quotes' as -an extension, output is strict JSON using only "double quotes"). As -in JSON, trailing commas are not permitted in arrays or dictionaries. -Input must be ASCII (although QMP supports full Unicode strings, the -QAPI parser does not). At present, there is no place where a QAPI -schema requires the use of JSON numbers or null. - - -=3D=3D=3D Comments =3D=3D=3D - -Comments are allowed; anything between an unquoted # and the following -newline is ignored. - - -=3D=3D=3D Schema overview =3D=3D=3D - -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 -the second validates the schema and generates the code. This allows -the definition of complex structs that can have mutually recursive -types, and allows for indefinite nesting of Client JSON Protocol that -satisfies the schema. A type name should not be defined more than -once. It is permissible for the schema to contain additional types -not used by any commands or events in the Client JSON Protocol, for -the side effect of generated C code used internally. - -There are eight top-level expressions recognized by the parser: -'include', 'pragma', 'command', 'struct', 'enum', 'union', -'alternate', and 'event'. There are several groups of types: simple -types (a number of built-in types, such as 'int' and 'str'; as well as -enumerations), complex types (structs and two flavors of unions), and -alternate types (a choice between other types). The 'command' and -'event' expressions can refer to existing types by name, or list an -anonymous type as a dictionary. Listing a type name inside an array -refers to a single-dimension array of that type; multi-dimension -arrays are not directly supported (although an array of a complex -struct that contains an array member is possible). +To map between Client JSON Protocol interfaces and the native C API, +we generate C code from a QAPI schema. This document describes the +QAPI schema language, and how it gets mapped to the Client JSON +Protocol and to C. It additionally provides guidance on maintaining +Client JSON Protocol compatibility. + + +=3D=3D The QAPI schema language =3D=3D + +The QAPI schema defines the Client JSON Protocol's commands and +events, as well as types used by them. Forward references are +allowed. + +It is permissible for the schema to contain additional types not used +by any commands or events, for the side effect of generated C code +used internally. + +There are several kinds of types: simple types (a number of built-in +types, such as 'int' and 'str'; as well as enumerations), arrays, +complex types (structs and two flavors of unions), and alternate types +(a choice between other types). + + +=3D=3D=3D Schema syntax =3D=3D=3D + +Syntax is loosely based on JSON (http://www.ietf.org/rfc/rfc8259.txt). +Differences: + +* Comments: start with a hash character (#) that is not part of a + string, and extend to the end of the line. + +* Strings are enclosed in 'single quotes', not "double quotes". + +* Strings are restricted to ASCII. All control characters must be + escaped, even DEL. + +* Numbers are not supported. + +A QAPI schema consists of a series of top-level expressions (JSON +objects). Their order does not matter. + +The order of keys within JSON objects does not matter unless +explicitly noted. + +There are eight kinds of top-level expressions: 'include', 'pragma', +'command', 'struct', 'enum', 'union', 'alternate', and 'event'. These +are discussed in detail below. =20 In the rest of this document, usage lines are given for each expression type, with literal strings written in lower case and --=20 2.21.0 From nobody Mon Apr 29 19:03:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1567024763; cv=none; d=zoho.com; s=zohoarc; b=X3GIs2spPyIQeolC6LIt0CmA0LIuR/UKXhqUNkIwKHWj1gZnyeN2edxJlxZx5m191l6gyTr6dxFFd6kwZre+sy+tr06B63wrN0oC0rv67UMzYIzsCjmSd/acxNP7HsIWgM7UK8aXTJ8jArb+LCR4ALlrqgqiezEqFlITEArX2rQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1567024763; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=hmyVmECyVR1lZXm4afAFZSxrfl5mYFV3HqVMVwMvHew=; b=Y3zVfy7ZQAXJiMYvmaz0i1xv714JOtgUMUcSHb1MVL0gt586HNO7fYei/IcTw0/KEOfLGFyml6sawe9nwkc8xzCulGmMwtmGbbrlAIGGrk1Dn2AdYG0rQOiSNYgE7Lz5aKQTfhHg0SV+ttv5A99pWO6xKW0kGbPWha4F+6Qq/2o= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1567024763109547.1339400082924; Wed, 28 Aug 2019 13:39:23 -0700 (PDT) Received: from localhost ([::1]:42560 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34iv-0000GD-JY for importer@patchew.org; Wed, 28 Aug 2019 16:39:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51895) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i34Wp-0003jd-Ql for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i34Wk-0002o9-JL for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49574) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1i34Wk-0002mn-6f for qemu-devel@nongnu.org; Wed, 28 Aug 2019 16:26:46 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7ABB4881342; Wed, 28 Aug 2019 20:26:45 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-117-142.ams2.redhat.com [10.36.117.142]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 941FE600F8; Wed, 28 Aug 2019 20:26:44 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 886561165617; Wed, 28 Aug 2019 22:26:41 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Wed, 28 Aug 2019 22:26:41 +0200 Message-Id: <20190828202641.24752-10-armbru@redhat.com> In-Reply-To: <20190828202641.24752-1-armbru@redhat.com> References: <20190828202641.24752-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.69]); Wed, 28 Aug 2019 20:26:45 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 9/9] docs/devel/qapi-code-gen: Improve QAPI schema language doc X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mdroth@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" We document the language by giving patterns of valid JSON objects. The patterns contain placeholders we don't define anywhere; their names have to speak for themselves. I guess they do, but I'd prefer a bit more rigor. Provide a grammar instead, and rework the text accordingly. Documentation for QAPI schema conditionals (commit 967c885108, 6cc32b0e14, 87adbbffd4..3e270dcacc) and feature flags (commit 6a8c0b5102) was bolted on. The sections documenting types, commands and events don't mention them. Section "Features" and "Configuring the schema" then provide additional syntax for types, commands and events. I hate that. Fix the sections documenting types, commands and events to provide accurate syntax, and point to "Features" and "Configuring the schema" for details. While there, make spacing more consistent, and avoid the terms "dictionary" and "key". Stick to JSON terminology "object" and "member name" instead. Signed-off-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 528 ++++++++++++++++++++++------------- 1 file changed, 330 insertions(+), 198 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 4502502531..495ef15215 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -4,12 +4,12 @@ Copyright IBM Corp. 2011 Copyright (C) 2012-2016 Red Hat, Inc. =20 This work is licensed under the terms of the GNU GPL, version 2 or -later. See the COPYING file in the top-level directory. +later. See the COPYING file in the top-level directory. =20 =3D=3D Introduction =3D=3D =20 QAPI is a native C API within QEMU which provides management-level -functionality to internal and external users. For external +functionality to internal and external users. For external users/processes, this interface is made available by a JSON-based wire format for the QEMU Monitor Protocol (QMP) for controlling qemu, as well as the QEMU Guest Agent (QGA) for communicating with the guest. @@ -54,23 +54,42 @@ Differences: =20 * Numbers are not supported. =20 -A QAPI schema consists of a series of top-level expressions (JSON -objects). Their order does not matter. +A second layer of syntax defines the sequences of JSON texts that are +a correctly structured QAPI schema. We provide a grammar for this +syntax in an EBNF-like notation: =20 -The order of keys within JSON objects does not matter unless +* Production rules look like non-terminal =3D expression +* Concatenation: Expression A B matches expression A, then B +* Alternation: Expression A | B matches expression A or B +* Repetition: Expression A... matches zero or more occurences of + expression A; expression A, ... likewise, but separated by , +* JSON's six structural characters are terminals: { } [ ] : , +* JSON's three literal names are terminals: false true null +* String literals enclosed in 'single quotes' are terminal, and match + this JSON string, with a leading '*' stripped off +* When JSON object member's name starts with '*', the member is + optional. +* The symbol STRING is a terminal, and matches any JSON string +* The symbol BOOL is a terminal, and matches JSON false or true +* ALL-CAPS words other than STRING are non-terminals + +The order of members within JSON objects does not matter unless explicitly noted. =20 -There are eight kinds of top-level expressions: 'include', 'pragma', -'command', 'struct', 'enum', 'union', 'alternate', and 'event'. These -are discussed in detail below. - -In the rest of this document, usage lines are given for each -expression type, with literal strings written in lower case and -placeholders written in capitals. If a literal string includes a -prefix of '*', that key/value pair can be omitted from the expression. -For example, a usage statement that includes '*base':STRUCT-NAME -means that an expression has an optional key 'base', which if present -must have a value that forms a struct name. +A QAPI schema consists of a series of top-level expressions: + + SCHEMA =3D EXPRESSION... + +The top-level expressions are all JSON objects. Their order does not +matter. + +There are eight kinds of top-level expressions: + + EXPRESSION =3D INCLUDE | PRAGMA + | ENUM | STRUCT | UNION | ALTERNATE + | COMMAND | EVENT + +These are discussed in detail below. =20 =20 =3D=3D=3D Built-in Types =3D=3D=3D @@ -100,16 +119,17 @@ The following types are predefined, and map to C as f= ollows: =20 =3D=3D=3D Include directives =3D=3D=3D =20 -Usage: { 'include': STRING } +Syntax: + INCLUDE =3D { 'include': STRING } =20 The QAPI schema definitions can be modularized using the 'include' directi= ve: =20 { 'include': 'path/to/file.json' } =20 -The directive is evaluated recursively, and include paths are relative to = the -file using the directive. Multiple includes of the same file are -idempotent. No other keys should appear in the expression, and the include -value should be a string. +The directive is evaluated recursively, and include paths are relative +to the file using the directive. Multiple includes of the same file +are idempotent. No other members should appear in the expression, and +the include value should be a string. =20 As a matter of style, it is a good idea to have all files be self-contained, but at the moment, nothing prevents an included file @@ -120,10 +140,12 @@ prevent incomplete include files. =20 =3D=3D=3D Pragma directives =3D=3D=3D =20 -Usage: { 'pragma': DICT } +Syntax: + PRAGMA =3D { 'pragma': { '*doc-required': BOOL }, + '*returns-whitelist': [ STRING, ... ], + '*name-case-whitelist': [ STRING, ... ] } =20 The pragma directive lets you control optional generator behavior. -The dictionary's entries are pragma names and values. =20 Pragma's scope is currently the complete schema. Setting the same pragma to different values in parts of the schema doesn't work. @@ -140,60 +162,95 @@ rules on use of upper- vs. lower-case letters. Defau= lt is none. =20 =3D=3D=3D Enumeration types =3D=3D=3D =20 -Usage: { 'enum': STRING, 'data': ARRAY-OF-STRING } - { 'enum': STRING, '*prefix': STRING, 'data': ARRAY-OF-STRING } +Syntax: + ENUM =3D { 'enum': STRING, + 'data': [ ENUM-VALUE, ... ], + '*prefix': STRING, + '*if': COND } + ENUM-VALUE =3D STRING + | { 'name': STRING, '*if': COND } =20 -An enumeration type is a dictionary containing a single 'data' key -whose value is a list of strings. An example enumeration is: +Member 'enum' names the enum type. + +Each member of the 'data' array defines a value of the enumeration +type. The form STRING is shorthand for { 'name': STRING }. The +'name' values must be be distinct. + +Example: =20 { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] } =20 -The strings must be distinct. - Nothing prevents an empty enumeration, although it is probably not useful. =20 -The enum constants will be named by using a heuristic to turn the -type name into a set of underscore separated words. For the example -above, 'MyEnum' will turn into 'MY_ENUM' giving a constant name -of 'MY_ENUM_VALUE1' for the first value. If the default heuristic -does not result in a desirable name, the optional 'prefix' member -can be used when defining the enum. - -The enumeration values are passed as strings over the Client JSON -Protocol, but are encoded as C enum integral values in generated code. -While the C code starts numbering at 0, it is better to use explicit -comparisons to enum values than implicit comparisons to 0; the C code -will also include a generated enum member ending in _MAX for tracking -the size of the enum, useful when using common functions for -converting between strings and enum values. - -For any struct that has a member that will only contain a finite set -of string values, using an enum type for that member is better than -open-coding the member to be type 'str'. +On the wire, an enumeration type's value is represented by its +(string) name. In C, it's represented by an enumeration constant. +These are of the form PREFIX_NAME, where PREFIX is derived from the +enumeration type's name, and NAME from the value's name. For the +example above, the generator maps 'MyEnum' to MY_ENUM and 'value1' to +VALUE1, resulting in the enumeration constant MY_ENUM_VALUE1. The +optional 'prefix' member overrides PREFIX. + +The generated C enumeration constants have values 0, 1, ..., N-1 (in +QAPI schema order), where N is the number of values. There is an +additional enumeration constant PREFIX__MAX with value N. + +Do not use string or an integer type when an enumeration type can do +the job satisfactorily. + +The optional 'if' member specifies a conditional. See "Configuring +the schema" below for more on this. + + +=3D=3D=3D Type references and array types =3D=3D=3D + +Syntax: + TYPE-REF =3D STRING | ARRAY-TYPE + ARRAY-TYPE =3D [ STRING ] + +A string denotes the type named by the string. + +A one-element array containing a string denotes an array of the type +named by the string. Example: ['int'] denotes an array of 'int'. + =20 =3D=3D=3D Struct types =3D=3D=3D =20 -Usage: { 'struct': STRING, 'data': DICT, '*base': STRUCT-NAME } +Syntax: + STRUCT =3D { 'struct': STRING, + 'data': MEMBERS, + '*base': STRING, + '*if': COND, + '*features': FEATURES } + MEMBERS =3D { MEMBER, ... } + MEMBER =3D STRING : TYPE-REF + | STRING : { 'type': TYPE-REF, '*if': COND } =20 -A struct is a dictionary containing a single 'data' key whose value is -a dictionary; the dictionary may be empty. This corresponds to a -struct in C or an Object in JSON. Each value of the 'data' dictionary -must be the name of a type, or a one-element array containing a type -name. An example of a struct is: +Member 'struct' names the struct type. + +Each MEMBER of the 'data' object defines a member of the struct type. + +The MEMBER's STRING name consists of an optional '*' prefix and the +struct member name. If '*' is present, the member is optional. + +The MEMBER's value defines its properties, in particular its type. +The form TYPE-REF is shorthand for { 'type': TYPE-REF }. + +Example: =20 { 'struct': 'MyType', - 'data': { 'member1': 'str', 'member2': 'int', '*member3': 'str' } } + 'data': { 'member1': 'str', 'member2': ['int'], '*member3': 'str' } } =20 -The use of '*' as a prefix to the name means the member is optional in -the corresponding JSON protocol usage. +A struct type corresponds to a struct in C, and an object in JSON. +The C struct's members are generated in QAPI schema order. =20 -A struct definition can specify another struct as its base. -In this case, the members of the base type are included as top-level membe= rs -of the new struct's dictionary in the Client JSON Protocol wire -format. An example definition is: +The optional 'base' member names a struct type whose members are to be +included in this type. They go first in the C struct. =20 - { 'struct': 'BlockdevOptionsGenericFormat', 'data': { 'file': 'str' } } +Example: + + { 'struct': 'BlockdevOptionsGenericFormat', + 'data': { 'file': 'str' } } { 'struct': 'BlockdevOptionsGenericCOWFormat', 'base': 'BlockdevOptionsGenericFormat', 'data': { '*backing': 'str' } } @@ -204,19 +261,40 @@ both members like this: { "file": "/some/place/my-image", "backing": "/some/place/my-backing-file" } =20 +The optional 'if' member specifies a conditional. See "Configuring +the schema" below for more on this. + +The optional 'features' member specifies features. See "Features" +below for more on this. + =20 =3D=3D=3D Union types =3D=3D=3D =20 -Usage: { 'union': STRING, 'data': DICT } -or: { 'union': STRING, 'data': DICT, 'base': STRUCT-NAME-OR-DICT, - 'discriminator': ENUM-MEMBER-OF-BASE } - -Union types are used to let the user choose between several different -variants for an object. There are two flavors: simple (no -discriminator or base), and flat (both discriminator and base). A union -type is defined using a data dictionary as explained in the following -paragraphs. The data dictionary for either type of union must not -be empty. +Syntax: + UNION =3D { 'union': STRING, + 'data': BRANCHES, + '*if': COND } + | { 'union': STRING, + 'data': BRANCHES, + 'base': ( MEMBERS | STRING ), + 'discriminator': STRING, + '*if': COND } + BRANCHES =3D { BRANCH, ... } + BRANCH =3D STRING : TYPE-REF + | STRING : { 'type': TYPE-REF, '*if': COND } + +Member 'union' names the union type. + +There are two flavors of union types: simple (no discriminator or +base), and flat (both discriminator and base). + +Each BRANCH of the 'data' object defines a branch of the union. A +union must have at least one branch. + +The BRANCH's STRING name is the branch name. + +The BRANCH's value defines the branch's properties, in particular its +type. The form TYPE-REF is shorthand for { 'type': TYPE-REF }. =20 A simple union type defines a mapping from automatic discriminator values to data types like in this example: @@ -229,8 +307,8 @@ values to data types like in this example: 'data': { 'file': 'BlockdevOptionsFile', 'qcow2': 'BlockdevOptionsQcow2' } } =20 -In the Client JSON Protocol, a simple union is represented by a -dictionary that contains the 'type' member as a discriminator, and a +In the Client JSON Protocol, a simple union is represented by an +object that contains the 'type' member as a discriminator, and a 'data' member that is of the specified data type corresponding to the discriminator value, as in these examples: =20 @@ -238,21 +316,27 @@ discriminator value, as in these examples: { "type": "qcow2", "data": { "backing": "/some/place/my-image", "lazy-refcounts": true } } =20 -The generated C code uses a struct containing a union. Additionally, +The generated C code uses a struct containing a union. Additionally, an implicit C enum 'NameKind' is created, corresponding to the union 'Name', for accessing the various branches of the union. The value for each branch can be of any type. =20 -A flat union definition avoids nesting on the wire, and specifies a -set of common members that occur in all variants of the union. The -'base' key must specify either a type name (the type must be a -struct, not a union), or a dictionary representing an anonymous type. -All branches of the union must be struct types, and the top-level -members of the union dictionary on the wire will be combination of -members from both the base type and the appropriate branch type (when -merging two dictionaries, there must be no keys in common). The -'discriminator' member must be the name of a non-optional enum-typed -member of the base struct. +Flat unions permit arbitrary common members that occur in all variants +of the union, not just a discriminator. Their discriminators need not +be named 'type'. They also avoid nesting on the wire. + +The 'base' member defines the common members. If it is a MEMBERS +object, it defines common members just like a struct type's 'data' +member defines struct type members. If it is a STRING, it names a +struct type whose members are the common members. + +All flat union branches must be of struct type. + +In the Client JSON Protocol, a flat union is represented by an object +with the common members (from the base type) and the selected branch's +members. The two sets of member names must be disjoint. Member +'discriminator' must name a non-optional enum-typed member of the base +struct. =20 The following example enhances the above simple union example by adding an optional common member 'read-only', renaming the @@ -276,12 +360,13 @@ Resulting in these JSON objects: Notice that in a flat union, the discriminator name is controlled by the user, but because it must map to a base member with enum type, the code generator ensures that branches match the existing values of the -enum. The order of the keys need not match the declaration of the enum. -The keys need not cover all possible enum values. Omitted enum values -are still valid branches that add no additional members to the data type. -In the resulting generated C data types, a flat union is -represented as a struct with the base members included directly, and -then a union of structures for each branch of the struct. +enum. The order of branches need not match the order of the enum +values. The branches need not cover all possible enum values. +Omitted enum values are still valid branches that add no additional +members to the data type. In the resulting generated C data types, a +flat union is represented as a struct with the base members in QAPI +schema order, and then a union of structures for each branch of the +struct. =20 A simple union can always be re-written as a flat union where the base class has a single member named 'type', and where each branch of the @@ -297,26 +382,42 @@ is identical on the wire to: { 'union': 'Flat': 'base': { 'type': 'Enum' }, 'discriminator': 'type', 'data': { 'one': 'Branch1', 'two': 'Branch2' } } =20 +The optional 'if' member specifies a conditional. See "Configuring +the schema" below for more on this. + =20 =3D=3D=3D Alternate types =3D=3D=3D =20 -Usage: { 'alternate': STRING, 'data': DICT } +Syntax: + ALTERNATE =3D { 'alternate': STRING, + 'data': ALTERNATIVES, + '*if': COND } + ALTERNATIVES =3D { ALTERNATIVE, ... } + ALTERNATIVE =3D STRING : TYPE-REF + | STRING : { 'type': STRING, '*if': COND } =20 -An alternate type is one that allows a choice between two or more JSON -data types (string, integer, number, or object, but currently not -array) on the wire. The definition is similar to a simple union type, -where each branch of the union names a QAPI type. For example: +Member 'alternate' names the alternate type. + +Each ALTERNATIVE of the 'data' object defines a branch of the +alternate. An alternate must have at least one branch. + +The ALTERNATIVE's STRING name is the branch name. + +The ALTERNATIVE's value defines the branch's properties, in particular +its type. The form STRING is shorthand for { 'type': STRING }. + +Example: =20 { 'alternate': 'BlockdevRef', 'data': { 'definition': 'BlockdevOptions', 'reference': 'str' } } =20 -Unlike a union, the discriminator string is never passed on the wire -for the Client JSON Protocol. Instead, the value's JSON type serves -as an implicit discriminator, which in turn means that an alternate -can only express a choice between types represented differently in -JSON. If a branch is typed as the 'bool' built-in, the alternate -accepts true and false; if it is typed as any of the various numeric +An alternate type is like a union type, except there is no +discriminator on the wire. Instead, the value's JSON type serves as +an implicit discriminator, which in turn means that an alternate can +only express a choice between types represented differently in JSON. +If a branch is typed as the 'bool' built-in, the alternate accepts +true and false; if it is typed as any of the various numeric built-ins, it accepts a JSON number; if it is typed as a 'str' built-in or named enum type, it accepts a JSON string; if it is typed as the 'null' built-in, it accepts JSON null; and if it is typed as a @@ -332,43 +433,49 @@ following example objects: "read-only": false, "filename": "/tmp/mydisk.qcow2" } } =20 +The optional 'if' member specifies a conditional. See "Configuring +the schema" below for more on this. + =20 =3D=3D=3D Commands =3D=3D=3D =20 ---- General Command Layout --- +Syntax: + COMMAND =3D { 'command': STRING, + '*data': ( MEMBERS | STRING ), + '*boxed': true, + '*returns': TYPE-REF, + '*success-response': false, + '*gen': false, + '*allow-oob': true, + '*allow-preconfig': true, + '*if': COND } =20 -Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT, - '*returns': TYPE-NAME, '*boxed': true, - '*gen': false, '*success-response': false, - '*allow-oob': true, '*allow-preconfig': true } +Member 'command' names the command. =20 -Commands are defined by using a dictionary containing several members, -where three members are most common. The 'command' member is a -mandatory string, and determines the "execute" value passed in a -Client JSON Protocol command exchange. +Member 'data' defines the arguments. It defaults to an empty MEMBERS +object. =20 -The 'data' argument maps to the "arguments" dictionary passed in as -part of a Client JSON Protocol command. The 'data' member is optional -and defaults to {} (an empty dictionary). If present, it must be the -string name of a complex type, or a dictionary that declares an -anonymous type with the same semantics as a 'struct' expression. +If 'data' is a MEMBERS object, then MEMBERS defines arguments just +like a struct type's 'data' defines struct type members. Member +'boxed' must be absent. =20 -The 'returns' member describes what will appear in the "return" member -of a Client JSON Protocol reply on successful completion of a command. -The member is optional from the command declaration; if absent, the -"return" member will be an empty dictionary. If 'returns' is present, -it must be the string name of a complex type, or a -one-element array containing the name of a complex. -To return anything else, you have to list the command in pragma -'returns-whitelist'. If you do this, the command cannot be extended -to return additional information in the future. Use of +If 'data' is a STRING, then STRING names a complex type whose members +are the arguments. A union type requires 'boxed': true. + +Member 'returns' defines the command's return type. It defaults to an +empty struct type. It must normally be a complex type or an array of +a complex type. To return anything else, the command must be listed +in pragma 'returns-whitelist'. If you do this, extending the command +to return additional information will be harder. Use of 'returns-whitelist' for new commands is strongly discouraged. =20 -All commands in Client JSON Protocol use a dictionary to report -failure, with no way to specify that in QAPI. Where the error return -is different than the usual GenericError class in order to help the -client react differently to certain error conditions, it is worth -documenting this in the comments before the command declaration. +A command's error responses are not specified in the QAPI schema. +Error conditions should be documented in comments. + +In the Client JSON Protocol, the value of the "execute" or "exec-oob" +member is the command name. The value of the "arguments" member then +has to conform to the arguments, and the value of the success +response's "return" member will conform to the return type. =20 Some example commands: =20 @@ -386,23 +493,24 @@ which would validate this Client JSON Protocol transa= ction: =3D> { "execute": "my-second-command" } <=3D { "return": [ { "value": "one" }, { } ] } =20 -The generator emits a prototype for the user's function implementing -the command. Normally, 'data' is a dictionary for an anonymous type, -or names a struct type (possibly empty, but not a union), and its -members are passed as separate arguments to this function. If the -command definition includes a key 'boxed' with the boolean value true, -then 'data' is instead the name of any non-empty complex type (struct -or union), and a pointer to that QAPI type is passed as a single -argument. +The generator emits a prototype for the C function implementing the +command. The function itself needs to be written by hand. See +section "Code generated for commands" for examples. + +The function returns the return type. When member 'boxed' is absent, +it takes the command arguments as arguments one by one, in QAPI schema +order. Else it takes them wrapped in the C struct generated for the +complex argument type. In either case, it takes an additional Error +** argument. =20 The generator also emits a marshalling function that extracts arguments for the user's function out of an input QDict, calls the user's function, and if it succeeded, builds an output QObject from -its return value. +its return value. This is for use by the QMP monitor core. =20 In rare cases, QAPI cannot express a type-safe representation of a corresponding Client JSON Protocol command. You then have to suppress -generation of a marshalling function by including a key 'gen' with +generation of a marshalling function by including a member 'gen' with boolean value false, and instead write your own function. For example: =20 @@ -416,13 +524,12 @@ use type-safe unions. Normally, the QAPI schema is used to describe synchronous exchanges, where a response is expected. But in some cases, the action of a command is expected to change state in a way that a successful -response is not possible (although the command will still return a -normal dictionary error on failure). When a successful reply is not -possible, the command expression includes the optional key -'success-response' with boolean value false. So far, only QGA makes -use of this member. +response is not possible (although the command will still return an +error object on failure). When a successful reply is not possible, +the command expression includes the optional member 'success-response' +with boolean value false. So far, only QGA makes use of this member. =20 -Key 'allow-oob' declares whether the command supports out-of-band +Member 'allow-oob' declares whether the command supports out-of-band (OOB) execution. It defaults to false. For example: =20 { 'command': 'migrate_recover', @@ -455,8 +562,8 @@ other "slow" lock. =20 When in doubt, do not implement OOB execution support. =20 -Key 'allow-preconfig' declares whether the command is available before -the machine is built. It defaults to false. For example: +Member 'allow-preconfig' declares whether the command is available +before the machine is built. It defaults to false. For example: =20 { 'command': 'qmp_capabilities', 'data': { '*enable': [ 'QMPCapability' ] }, @@ -465,16 +572,30 @@ the machine is built. It defaults to false. For exa= mple: QMP is available before the machine is built only when QEMU was started with --preconfig. =20 +The optional 'if' member specifies a conditional. See "Configuring +the schema" below for more on this. + + =3D=3D=3D Events =3D=3D=3D =20 -Usage: { 'event': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT, - '*boxed': true } - -Events are defined with the keyword 'event'. When 'data' is also -specified, additional info will be included in the event, with similar -semantics to a 'struct' expression. Finally there will be C API -generated in qapi-events.h; when called by QEMU code, a message with -timestamp will be emitted on the wire. +Syntax: + EVENT =3D { 'event': STRING, + '*data': ( MEMBERS | STRING ), + '*boxed': true, + '*if': COND } + +Member 'event' names the event. This is the event name used in the +Client JSON Protocol. + +Member 'data' defines the event-specific data. It defaults to an +empty MEMBERS object. + +If 'data' is a MEMBERS object, then MEMBERS defines event-specific +data just like a struct type's 'data' defines struct type members. +Member 'boxed' must be absent. + +If 'data' is a STRING, then STRING names a complex type whose members +are the event-specific data. A union type requires 'boxed': true. =20 An example event is: =20 @@ -487,42 +608,44 @@ Resulting in this JSON object: "data": { "b": "test string" }, "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } =20 -The generator emits a function to send the event. Normally, 'data' is -a dictionary for an anonymous type, or names a struct type (possibly -empty, but not a union), and its members are passed as separate -arguments to this function. If the event definition includes a key -'boxed' with the boolean value true, then 'data' is instead the name -of any non-empty complex type (struct or union), and a pointer to that -QAPI type is passed as a single argument. +The generator emits a function to send the event. When member 'boxed' +is absent, it takes event-specific data one by one, in QAPI schema +order. Else it takes them wrapped in the C struct generated for the +complex type. See section "Code generated for events" for examples. + +The optional 'if' member specifies a conditional. See "Configuring +the schema" below for more on this. =20 =20 =3D=3D=3D Features =3D=3D=3D =20 +Syntax: + FEATURES =3D [ FEATURE, ... ] + FEATURE =3D STRING + | { 'name': STRING, '*if': COND } + Sometimes, the behaviour of QEMU changes compatibly, but without a -change in the QMP syntax (usually by allowing values or operations that -previously resulted in an error). QMP clients may still need to know -whether the extension is available. +change in the QMP syntax (usually by allowing values or operations +that previously resulted in an error). QMP clients may still need to +know whether the extension is available. =20 For this purpose, a list of features can be specified for a struct type. This is exposed to the client as a list of string, where each string signals that this build of QEMU shows a certain behaviour. =20 -In the schema, features can be specified as simple strings, for example: +Each member of the 'features' array defines a feature. It can either +be { 'name': STRING, '*if': COND }, or STRING, which is shorthand for +{ 'name': STRING }. + +The optional 'if' member specifies a conditional. See "Configuring +the schema" below for more on this. + +Example: =20 { 'struct': 'TestType', 'data': { 'number': 'int' }, 'features': [ 'allow-negative-numbers' ] } =20 -Another option is to specify features as dictionaries, where the key -'name' specifies the feature string to be exposed to clients: - -{ 'struct': 'TestType', - 'data': { 'number': 'int' }, - 'features': [ { 'name': 'allow-negative-numbers' } ] } - -This expanded form is necessary if you want to make the feature -conditional (see below in "Configuring the schema"). - =20 =3D=3D=3D Naming rules and reserved names =3D=3D=3D =20 @@ -577,11 +700,15 @@ downstream command __com.redhat_drive-mirror. =20 =3D=3D=3D Configuring the schema =3D=3D=3D =20 -The 'struct', 'enum', 'union', 'alternate', 'command' and 'event' -top-level expressions can take an 'if' key. Its value must be a string -or a list of strings. A string is shorthand for a list containing just -that string. The code generated for the top-level expression will then -be guarded by #if COND for each COND in the list. +Syntax: + COND =3D STRING + | [ STRING, ... ] + +Top-level expressions other than include and pragma directives take an +optional 'if' member. Its value must be a string or a list of +strings. A string is shorthand for a list containing just that +string. The code generated for the expression will then be guarded by +#if COND for each COND in the list. =20 Example: a conditional struct =20 @@ -596,29 +723,33 @@ gets its generated code guarded like this: #endif /* defined(HAVE_BAR) */ #endif /* defined(CONFIG_FOO) */ =20 -Where a member can be defined with a single string value for its type, -it is also possible to supply a dictionary instead with both 'type' -and 'if' keys. +Individual members of complex types, commands arguments, and +event-specific data can also be made conditional. This requires the +longhand form of MEMBER. =20 -Example: a conditional 'bar' member +Example: a struct type with unconditional member 'foo' and conditional +member 'bar' =20 { 'struct': 'IfStruct', 'data': { 'foo': 'int', 'bar': { 'type': 'int', 'if': 'defined(IFCOND)'} } } =20 -An enum value can be replaced by a dictionary with a 'name' and a 'if' -key. +A union's discriminator may not be conditional. =20 -Example: a conditional 'bar' enum member. +Likewise, individual enumeration values be conditional. This requires +the longhand form of ENUM-VALUE. + +Example: an enum type with unconditional value 'foo' and conditional +value 'bar' =20 { 'enum': 'IfEnum', 'data': [ 'foo', { 'name' : 'bar', 'if': 'defined(IFCOND)' } ] } =20 -Similarly, features can be specified as a dictionary with a 'name' and -an 'if' key. +Likewise, features can be conditional. This requires the longhand +form of FEATURE. =20 -Example: a conditional 'allow-negative-numbers' feature +Example: a struct with conditional feature 'allow-negative-numbers' =20 { 'struct': 'TestType', 'data': { 'number': 'int' }, @@ -627,10 +758,11 @@ Example: a conditional 'allow-negative-numbers' featu= re =20 Please note that you are responsible to ensure that the C code will compile with an arbitrary combination of conditions, since the -generators are unable to check it at this point. +generator is unable to check it at this point. =20 -The presence of 'if' keys in the schema is reflected through to the -introspection output depending on the build configuration. +The conditions apply to introspection as well, i.e. introspection +shows a conditional entity only when the condition is satisfied in +this particular build. =20 =20 =3D=3D=3D Documentation comments =3D=3D=3D @@ -702,8 +834,8 @@ Example: =20 =3D=3D=3D=3D Expression documentation =3D=3D=3D=3D =20 -Expressions other than include and pragma directives may be preceded -by a documentation block. Such blocks are called expression +Top-level expressions other than include and pragma directives may be +preceded by a documentation block. Such blocks are called expression documentation blocks. =20 When documentation is required (see pragma 'doc-required'), expression @@ -861,7 +993,7 @@ If the event carries no additional information, "arg-ty= pe" names an object type without members. The event may not have a data member on the wire then. =20 -Each command or event defined with dictionary-valued 'data' in the +Each command or event defined with 'data' as MEMBERS object in the QAPI schema implicitly defines an object type. =20 Example: the SchemaInfo for EVENT_C from section Events @@ -1043,7 +1175,7 @@ receive direction compatibility. =20 Any change to types used in both contexts need to consider both. =20 -Members of enumeration types, complex types and alternate types may be +Enumeration type values and complex and alternate type members may be reordered freely. For enumerations and alternate types, this doesn't affect the wire encoding. For complex types, this might make the implementation emit JSON object members in a different order, which --=20 2.21.0