From nobody Sun Feb 8 04:18:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.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=1605202232; cv=none; d=zohomail.com; s=zohoarc; b=Ulxkvzihi35B+tudXhYsIQupxU24OaTSCEAijsR9YRSGjxZw62lw0igfJRrQGFXtseqrjcedPkZhdWNoyD+4IAKuYEBoxStNTMgHntaZ36RLDYOnJPAigoNKhByAkg7ZAoDZ8e9uIEXjPFdMNpszVsYB0SSR+1U32aN7TPU/8hQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605202232; 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; bh=CjnQtyzPDpqRQweTOp3vyY/4W/h4Urek3MFOvEw1SHs=; b=RSvC641rTZAWqyHROoUkye04/tyEtXbeCDCgN1quAGeH4MO81S+0L7ByDudLFy5EIqZPO4Ki9LdJ2InFvugJzA5mDHn4sXtPL7Hk5f0/7mKF8fPbf01cYzYyBCDyR/Mnnx5UFlPrbYbb7OGhTZnodWroL1RNUfx8/2BvvNZTAOM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.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 1605202232141742.7960149677658; Thu, 12 Nov 2020 09:30:32 -0800 (PST) Received: from localhost ([::1]:43162 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kdGQY-0002iw-Vl for importer@patchew.org; Thu, 12 Nov 2020 12:30:31 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:57718) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kdGPE-00018L-47 for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:08 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:58922) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kdGP9-0006or-N2 for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:07 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-173-o2KILMkAPMKF2t_nlLRT3A-1; Thu, 12 Nov 2020 12:29:00 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 832FF100963D for ; Thu, 12 Nov 2020 17:28:59 +0000 (UTC) Received: from merkur.fritz.box (ovpn-115-57.ams2.redhat.com [10.36.115.57]) by smtp.corp.redhat.com (Postfix) with ESMTP id 860635D9E8; Thu, 12 Nov 2020 17:28:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605202142; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CjnQtyzPDpqRQweTOp3vyY/4W/h4Urek3MFOvEw1SHs=; b=XwcL5c9bhO/YkFoqhoJuALg7nwnIolNJBXOGGwdSSqHXZG1fMAywDebG1gJAGIrCHE5bcK vxslt3WuBeyVCB2E27+PZmhagR2Pd/U0JvMLmjuhhIMIJa3yp7c41mxCdpyBWweX6S64Ds sVbJ5qyQ8gQFPXxkDJrKW5Hl0XCzVjw= X-MC-Unique: o2KILMkAPMKF2t_nlLRT3A-1 From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH 1/6] qapi: Add interfaces for alias support to Visitor Date: Thu, 12 Nov 2020 18:28:45 +0100 Message-Id: <20201112172850.401925-2-kwolf@redhat.com> In-Reply-To: <20201112172850.401925-1-kwolf@redhat.com> References: <20201112172850.401925-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kwolf@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=216.205.24.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/12 08:00:44 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: kwolf@redhat.com, jsnow@redhat.com, armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" This adds functions to the Visitor interface that can be used to define aliases and alias scopes. Signed-off-by: Kevin Wolf --- include/qapi/visitor-impl.h | 12 ++++++++++++ include/qapi/visitor.h | 37 +++++++++++++++++++++++++++++++++++++ qapi/qapi-visit-core.c | 21 +++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 7362c043be..e30da2599c 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -113,6 +113,18 @@ struct Visitor The core takes care of the return type in the public interface. */ void (*optional)(Visitor *v, const char *name, bool *present); =20 + /* + * Optional; intended for input visitors. If not given, aliases are + * ignored. + */ + void (*define_alias)(Visitor *v, const char *alias, const char **sourc= e); + + /* Must be set if define_alias is set */ + void (*start_alias_scope)(Visitor *v); + + /* Must be set if define_alias is set */ + void (*end_alias_scope)(Visitor *v); + /* Must be set */ VisitorType type; =20 diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index ebc19ede7f..9bdc0ee03d 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -459,6 +459,43 @@ void visit_end_alternate(Visitor *v, void **obj); */ bool visit_optional(Visitor *v, const char *name, bool *present); =20 +/* + * Defines a new alias rule. + * + * If @alias is non-NULL, the member named @alias in the external + * representation of the current struct is defined as an alias for the + * member described by @source. + * + * If @alias is NULL, all members of the struct described by @source are + * considered to have alias members with the same key in the current + * struct. + * + * @source is a NULL-terminated array of names that describe the path to + * a member, starting from the currently visited struct. + * + * The alias stays valid until the current alias scope ends. + * visit_start/end_struct() implicitly start/end an alias scope. + * Additionally, visit_start/end_alias_scope() can be used to explicitly + * create a nested alias scope. + */ +void visit_define_alias(Visitor *v, const char *alias, const char **source= ); + +/* + * Begins an explicit alias scope. + * + * Alias definitions after here will only stay valid until the + * corresponding visit_end_alias_scope() is called. + */ +void visit_start_alias_scope(Visitor *v); + +/* + * Ends an explicit alias scope. + * + * Alias definitions between the correspoding visit_start_alias_scope() + * call and here go out of scope and won't apply in later code any more. + */ +void visit_end_alias_scope(Visitor *v); + /* * Visit an enum value. * diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 7e5f40e7f0..719a9f5da2 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -135,6 +135,27 @@ bool visit_optional(Visitor *v, const char *name, bool= *present) return *present; } =20 +void visit_define_alias(Visitor *v, const char *alias, const char **source) +{ + if (v->define_alias) { + v->define_alias(v, alias, source); + } +} + +void visit_start_alias_scope(Visitor *v) +{ + if (v->start_alias_scope) { + v->start_alias_scope(v); + } +} + +void visit_end_alias_scope(Visitor *v) +{ + if (v->end_alias_scope) { + v->end_alias_scope(v); + } +} + bool visit_is_input(Visitor *v) { return v->type =3D=3D VISITOR_INPUT; --=20 2.28.0 From nobody Sun Feb 8 04:18:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.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=1605202241; cv=none; d=zohomail.com; s=zohoarc; b=YXBlwo0Y4y760CUB+ciowgD7pU5Yur2zc5lBdmHXm9uDf211eNcrwTVIbwToRHRh5cDTsI+SNUV7EcMutS2wrXOLg7YxxFZKDO2N9sRokgN0luCojCZWRmorgDHLgD1HH72WKmXF80MQnGztkzfMv16eLVW+jzQMXf6AloVztiU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605202241; 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; bh=uwsAGapOhQHVbm/iIny+CACibwCIp7kJv++sEiXwlN0=; b=IWk2+U3IDZ8EVayin3aHiL2em9OVRppejauh0aw7KiEZA/e2o4H7IcL6y0p5VFlJUtR5Y/RONwPwn+EiIPLDl0YGEAxxBZXyygdwwoggJXqgRChNCJ0my77f1oauP4RU2e+GLU/p7NA5wg9qsSgDqbJa27RR8MtWOvuLZcnyQec= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.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 160520224148486.0713992248136; Thu, 12 Nov 2020 09:30:41 -0800 (PST) Received: from localhost ([::1]:43640 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kdGQi-0002us-90 for importer@patchew.org; Thu, 12 Nov 2020 12:30:40 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:57770) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kdGPH-0001CW-BR for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:11 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:23592) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kdGPF-0006rC-Cf for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:11 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-308-efXt_QPaPvKfUWSLFGRLyQ-1; Thu, 12 Nov 2020 12:29:01 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C4E9F1074662 for ; Thu, 12 Nov 2020 17:29:00 +0000 (UTC) Received: from merkur.fritz.box (ovpn-115-57.ams2.redhat.com [10.36.115.57]) by smtp.corp.redhat.com (Postfix) with ESMTP id CB6055D9E4; Thu, 12 Nov 2020 17:28:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605202148; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uwsAGapOhQHVbm/iIny+CACibwCIp7kJv++sEiXwlN0=; b=WOnbn/s9qOKbpd0DJ8/V8pEFSptyyovUbNLNNigLLkgN/o7fnsgjBdiOAjcrqxVmNiC+vK TMwbuAXdHCz5upsw90/ZRKYUmT1/5ROnU2UvTiVONxpqetrnlKy9hQa6Eenu9rruJpU2oS aLOhO3P4gqwQ/S3irJZE7Bmicb5Yqj4= X-MC-Unique: efXt_QPaPvKfUWSLFGRLyQ-1 From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH 2/6] qapi: Remember alias definitions in qobject-input-visitor Date: Thu, 12 Nov 2020 18:28:46 +0100 Message-Id: <20201112172850.401925-3-kwolf@redhat.com> In-Reply-To: <20201112172850.401925-1-kwolf@redhat.com> References: <20201112172850.401925-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kwolf@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=63.128.21.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/12 00:52:29 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: kwolf@redhat.com, jsnow@redhat.com, armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" This makes qobject-input-visitor remember the currently valid aliases in each StackObject. It doesn't actually allow using the aliases yet. Signed-off-by: Kevin Wolf --- qapi/qobject-input-visitor.c | 115 +++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 23843b242e..a00ac32682 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -29,6 +29,29 @@ #include "qemu/cutils.h" #include "qemu/option.h" =20 +typedef struct InputVisitorAlias { + /* Alias name. NULL for any (wildcard alias). */ + const char *alias; + + /* + * NULL terminated array representing a path. + * Must contain at least one non-NULL element if alias is not NULL. + */ + const char **src; + + /* StackObject in which the alias should be looked for */ + struct StackObject *alias_so; + + /* + * The alias remains valid as long as the containing StackObject has + * StackObject.alias_scope_nesting >=3D InputVisitorAlias.scope_nesting + * or until the whole StackObject is removed. + */ + int scope_nesting; + + QSLIST_ENTRY(InputVisitorAlias) next; +} InputVisitorAlias; + typedef struct StackObject { const char *name; /* Name of @obj in its parent, if any */ QObject *obj; /* QDict or QList being visited */ @@ -38,6 +61,9 @@ typedef struct StackObject { const QListEntry *entry; /* If @obj is QList: unvisited tail */ unsigned index; /* If @obj is QList: list index of @entry = */ =20 + QSLIST_HEAD(, InputVisitorAlias) aliases; + int alias_scope_nesting; /* Increase on scope start, decrease on en= d */ + QSLIST_ENTRY(StackObject) node; /* parent */ } StackObject; =20 @@ -203,6 +229,38 @@ static const char *qobject_input_get_keyval(QObjectInp= utVisitor *qiv, return qstring_get_str(qstr); } =20 +/* + * Propagates aliases from the parent StackObject @src to its direct + * child StackObject @dst, which is representing the child struct @name. + * + * Every alias whose source path begins with @name and which still + * applies in @dst (i.e. it is either a wildcard alias or has at least + * one more source path element) is propagated to @dst with the first + * element (i.e. @name) removed from the source path. + */ +static void propagate_aliases(StackObject *dst, StackObject *src, + const char *name) +{ + InputVisitorAlias *a; + + QSLIST_FOREACH(a, &src->aliases, next) { + if (!a->src[0] || strcmp(a->src[0], name)) { + continue; + } + if (a->src[1] || !a->alias) { + InputVisitorAlias *alias =3D g_new(InputVisitorAlias, 1); + + *alias =3D (InputVisitorAlias) { + .alias =3D a->alias, + .alias_so =3D a->alias_so, + .src =3D &a->src[1], + }; + + QSLIST_INSERT_HEAD(&dst->aliases, alias, next); + } + } +} + static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv, const char *name, QObject *obj, void *qapi) @@ -226,6 +284,9 @@ static const QListEntry *qobject_input_push(QObjectInpu= tVisitor *qiv, g_hash_table_insert(h, (void *)qdict_entry_key(entry), NULL); } tos->h =3D h; + if (!QSLIST_EMPTY(&qiv->stack)) { + propagate_aliases(tos, QSLIST_FIRST(&qiv->stack), name); + } } else { assert(qlist); tos->entry =3D qlist_first(qlist); @@ -257,10 +318,17 @@ static bool qobject_input_check_struct(Visitor *v, Er= ror **errp) =20 static void qobject_input_stack_object_free(StackObject *tos) { + InputVisitorAlias *a; + if (tos->h) { g_hash_table_unref(tos->h); } =20 + while ((a =3D QSLIST_FIRST(&tos->aliases))) { + QSLIST_REMOVE_HEAD(&tos->aliases, next); + g_free(a); + } + g_free(tos); } =20 @@ -274,6 +342,50 @@ static void qobject_input_pop(Visitor *v, void **obj) qobject_input_stack_object_free(tos); } =20 +static void qobject_input_start_alias_scope(Visitor *v) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + StackObject *tos =3D QSLIST_FIRST(&qiv->stack); + + tos->alias_scope_nesting++; +} + +static void qobject_input_end_alias_scope(Visitor *v) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + StackObject *tos =3D QSLIST_FIRST(&qiv->stack); + InputVisitorAlias *a, *next; + + assert(tos->alias_scope_nesting > 0); + tos->alias_scope_nesting--; + + QSLIST_FOREACH_SAFE(a, &tos->aliases, next, next) { + if (a->scope_nesting > tos->alias_scope_nesting) { + QSLIST_REMOVE(&tos->aliases, a, InputVisitorAlias, next); + g_free(a); + } + } +} + +static void qobject_input_define_alias(Visitor *v, const char *alias_name, + const char **source) +{ + QObjectInputVisitor *qiv =3D to_qiv(v); + StackObject *tos =3D QSLIST_FIRST(&qiv->stack); + InputVisitorAlias *alias =3D g_new(InputVisitorAlias, 1); + + /* The source path can only be empty for wildcard aliases */ + assert(source[0] || !alias_name); + + *alias =3D (InputVisitorAlias) { + .alias =3D alias_name, + .alias_so =3D tos, + .src =3D source, + }; + + QSLIST_INSERT_HEAD(&tos->aliases, alias, next); +} + static bool qobject_input_start_struct(Visitor *v, const char *name, void = **obj, size_t size, Error **errp) { @@ -696,6 +808,9 @@ static QObjectInputVisitor *qobject_input_visitor_base_= new(QObject *obj) v->visitor.end_list =3D qobject_input_end_list; v->visitor.start_alternate =3D qobject_input_start_alternate; v->visitor.optional =3D qobject_input_optional; + v->visitor.define_alias =3D qobject_input_define_alias; + v->visitor.start_alias_scope =3D qobject_input_start_alias_scope; + v->visitor.end_alias_scope =3D qobject_input_end_alias_scope; v->visitor.free =3D qobject_input_free; =20 v->root =3D qobject_ref(obj); --=20 2.28.0 From nobody Sun Feb 8 04:18:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.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=1605202372; cv=none; d=zohomail.com; s=zohoarc; b=bIncAp4s9jtWOkBUqVYFKGohnoCBT3HMoUvGO6bIRO05QqaSZ4Oceb0i+UrbpFcGUa62XlCnoMpdyoQa1DFAtTj3xs8shNu8q7LoUYJSEx1razd1VZz6LXVasknQEqGjjECBeasaHmSi4uGVpoF9U8pwRZQG5IbAux+CJ/GtQDQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605202372; 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; bh=T5aXtMe1jfNRMPI4R9wZ1lYUG2xTKyftwmN1cwLLpUU=; b=MvQZ92+dufYqOnxUgv7wXjJy/d6+U+gqbBnPMxhqCU+YHD6yLnIj9tn0x2ShdFeUAjh3o4iTDzAYjJCRy5zAF8UWmfab7GdIQnBNG2A3zPrcUZup/Wznkkg9M70SRvSED8mQ2GBAThMETCrLafeeCTWSgSLgfy3/bHjBugzRf6Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.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 160520237201917.55875511394015; Thu, 12 Nov 2020 09:32:52 -0800 (PST) Received: from localhost ([::1]:48864 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kdGSp-0005CL-2O for importer@patchew.org; Thu, 12 Nov 2020 12:32:51 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:57790) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kdGPJ-0001HN-R5 for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:13 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:28561) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kdGPG-0006sJ-D9 for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:13 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-257-rBX2kb0JMW6nBFwpbwn8Mw-1; Thu, 12 Nov 2020 12:29:07 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 610531074643 for ; Thu, 12 Nov 2020 17:29:05 +0000 (UTC) Received: from merkur.fritz.box (ovpn-115-57.ams2.redhat.com [10.36.115.57]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2FFFD5D9E4; Thu, 12 Nov 2020 17:29:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605202149; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=T5aXtMe1jfNRMPI4R9wZ1lYUG2xTKyftwmN1cwLLpUU=; b=RCjqIMRyDy7ufp0fZfHAK0ZS6m6U4nazZYJ7Fytgojv1D+rPi05IsMcOd6GJG9b2n4M2OQ j/bum9J68ZFDh3KrNvJ3hFgeJ1oV7drA8yKAZJk+Qke25eI268hEAGwVIN2UvPBiBpXh+9 h4LzwkLkxGDYbe+BmFYWglDjVmhrBvg= X-MC-Unique: rBX2kb0JMW6nBFwpbwn8Mw-1 From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH 3/6] qapi: Simplify full_name_nth() in qobject-input-visitor Date: Thu, 12 Nov 2020 18:28:47 +0100 Message-Id: <20201112172850.401925-4-kwolf@redhat.com> In-Reply-To: <20201112172850.401925-1-kwolf@redhat.com> References: <20201112172850.401925-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kwolf@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=216.205.24.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/12 08:00:44 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: kwolf@redhat.com, jsnow@redhat.com, armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Instead of counting how many elements from the top of the stack we need to ignore until we find the thing we're interested in, we can just directly pass the StackObject pointer because all callers already know it. We only need a different way now to tell if we want to know the name of something contained in the given StackObject or of the StackObject itself. Passing name =3D NULL is the obvious way to request the latter. This simplifies the interface and makes it easier to use in cases where we have the StackObject, but don't know how many steps down the stack it is. Signed-off-by: Kevin Wolf --- qapi/qobject-input-visitor.c | 38 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index a00ac32682..1415561828 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -87,20 +87,16 @@ static QObjectInputVisitor *to_qiv(Visitor *v) } =20 /* - * Find the full name of something @qiv is currently visiting. - * @qiv is visiting something named @name in the stack of containers - * @qiv->stack. - * If @n is zero, return its full name. - * If @n is positive, return the full name of the @n-th container - * counting from the top. The stack of containers must have at least - * @n elements. - * The returned string is valid until the next full_name_nth(@v) or - * destruction of @v. + * Find the full name of something named @name in @so which @qiv is + * currently visiting. If @name is NULL, find the full name of @so + * itself. + * + * The returned string is valid until the next full_name_so(@qiv) or + * destruction of @qiv. */ -static const char *full_name_nth(QObjectInputVisitor *qiv, const char *nam= e, - int n) +static const char *full_name_so(QObjectInputVisitor *qiv, const char *name, + StackObject *so) { - StackObject *so; char buf[32]; =20 if (qiv->errname) { @@ -109,10 +105,13 @@ static const char *full_name_nth(QObjectInputVisitor = *qiv, const char *name, qiv->errname =3D g_string_new(""); } =20 - QSLIST_FOREACH(so , &qiv->stack, node) { - if (n) { - n--; - } else if (qobject_type(so->obj) =3D=3D QTYPE_QDICT) { + if (!name && so) { + name =3D so->name; + so =3D QSLIST_NEXT(so, node); + } + + for (; so; so =3D QSLIST_NEXT(so, node)) { + if (qobject_type(so->obj) =3D=3D QTYPE_QDICT) { g_string_prepend(qiv->errname, name ?: ""); g_string_prepend_c(qiv->errname, '.'); } else { @@ -123,7 +122,6 @@ static const char *full_name_nth(QObjectInputVisitor *q= iv, const char *name, } name =3D so->name; } - assert(!n); =20 if (name) { g_string_prepend(qiv->errname, name); @@ -138,7 +136,9 @@ static const char *full_name_nth(QObjectInputVisitor *q= iv, const char *name, =20 static const char *full_name(QObjectInputVisitor *qiv, const char *name) { - return full_name_nth(qiv, name, 0); + StackObject *tos =3D QSLIST_FIRST(&qiv->stack); + + return full_name_so(qiv, name, tos); } =20 static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv, @@ -473,7 +473,7 @@ static bool qobject_input_check_list(Visitor *v, Error = **errp) =20 if (tos->entry) { error_setg(errp, "Only %u list elements expected in %s", - tos->index + 1, full_name_nth(qiv, NULL, 1)); + tos->index + 1, full_name_so(qiv, NULL, tos)); return false; } return true; --=20 2.28.0 From nobody Sun Feb 8 04:18:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.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=1605202243; cv=none; d=zohomail.com; s=zohoarc; b=Ix9mWke6S6mqlmvRCiHKgef9F3XDNC4C7YWK1UR7jgO/iQboWk7tajzFhaQRAEaUKERjMJbYn97KSoiVCbpn3TTmwun8o0ZVIIwkCq6YCVYK6oM6kaGNDUTZBCr4zufGJdFmL46Jw6VzKrW2WlWfqjQqD/hJKdrr7mrBdY234wI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605202243; 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; bh=kSi+8/J8t15Ik+ehJlrSnnY/IzaEAY/JX/NRXM3eXQs=; b=J1H2SyiTsMSxtWjo00A5SsSSNwRbOkE4NOZ4E2hbwpOfzCUn6Q7iBbMiQVWvdvaDYBZMzKiD2fr2ZwcAbz2yxYyLXzWsw4iMQOR+lyCFND5B44nRSa8UY0MIhmr5XUdxh/lUd29PG86V2yLz30q0q0Mgqo7kUvmRGCmBdtw/RsA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.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 16052022435261010.2337473457452; Thu, 12 Nov 2020 09:30:43 -0800 (PST) Received: from localhost ([::1]:43794 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kdGQk-0002yl-9c for importer@patchew.org; Thu, 12 Nov 2020 12:30:42 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:57776) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kdGPH-0001Dk-VM for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:11 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:32894) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kdGPF-0006rn-TE for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:11 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-14-XdAtEP8XNXeyszaNYg5Z4g-1; Thu, 12 Nov 2020 12:29:07 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A83DC1009E4B for ; Thu, 12 Nov 2020 17:29:06 +0000 (UTC) Received: from merkur.fritz.box (ovpn-115-57.ams2.redhat.com [10.36.115.57]) by smtp.corp.redhat.com (Postfix) with ESMTP id ADBCB5D9E4; Thu, 12 Nov 2020 17:29:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605202149; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kSi+8/J8t15Ik+ehJlrSnnY/IzaEAY/JX/NRXM3eXQs=; b=F80M+vxNzzDt8/aWcynJhqiU0Lgfzfjk4h36fub8/rGnqy4nbhEC12AxQOnyC4c2PwzvGu +NWjoaug4bpI3vtoX53VuysjiGZXtErsdJezmDHJ/+mQau7KSu75XoiuwhgsgkymKnkADO qFETT+TiD0xAq2FC1oZcePSBjlgGER4= X-MC-Unique: XdAtEP8XNXeyszaNYg5Z4g-1 From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH 4/6] qapi: Apply aliases in qobject-input-visitor Date: Thu, 12 Nov 2020 18:28:48 +0100 Message-Id: <20201112172850.401925-5-kwolf@redhat.com> In-Reply-To: <20201112172850.401925-1-kwolf@redhat.com> References: <20201112172850.401925-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kwolf@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=63.128.21.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/12 00:52:29 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: kwolf@redhat.com, jsnow@redhat.com, armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" When looking for an object in a struct in the external representation, check not only the currently visited struct, but also whether an alias in the current StackObject matches and try to fetch the value from the alias then. Providing two values for the same object through different aliases is an error. Signed-off-by: Kevin Wolf --- qapi/qobject-input-visitor.c | 169 +++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 9 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 1415561828..faca5b6b55 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -74,6 +74,8 @@ struct QObjectInputVisitor { QObject *root; bool keyval; /* Assume @root made with keyval_parse() */ =20 + QDict *empty_qdict; /* Used for implicit objects */ + /* Stack of objects being visited (all entries will be either * QDict or QList). */ QSLIST_HEAD(, StackObject) stack; @@ -141,9 +143,139 @@ static const char *full_name(QObjectInputVisitor *qiv= , const char *name) return full_name_so(qiv, name, tos); } =20 +static bool find_object_member(QObjectInputVisitor *qiv, + StackObject **so, const char **name, + bool *implicit_object, Error **errp); + +static bool alias_present(QObjectInputVisitor *qiv, + InputVisitorAlias *a, const char *name) +{ + StackObject *so =3D a->alias_so; + + /* + * The passed source @name is only relevant for wildcard aliases which + * don't have a separate name, otherwise we use the alias name. + */ + if (a->alias) { + name =3D a->alias; + } + + if (!find_object_member(qiv, &so, &name, NULL, NULL)) { + return false; + } + + /* + * Every source can be used only once. If a value in the input would e= nd up + * being used twice through aliases, we'll fail the second access. + */ + if (!g_hash_table_contains(so->h, name)) { + return false; + } + + return true; +} + +static bool alias_source_matches(QObjectInputVisitor *qiv, + StackObject *so, InputVisitorAlias *a, + const char *name, bool *implicit_object) +{ + if (a->src[0] =3D=3D NULL) { + assert(a->alias =3D=3D NULL); + return true; + } + + if (!strcmp(a->src[0], name)) { + if (a->alias && a->src[1] =3D=3D NULL) { + /* + * We're matching an exact member, the source for this alias is + * immediately in @so. + */ + return true; + } else if (implicit_object) { + /* + * We're only looking at a prefix of the source path for the a= lias. + * If the input contains no object of the requested name, we w= ill + * implicitly create an empty one so that the alias can still = be + * used. + * + * We want to create the implicit object only if the alias is + * actually used, but we can't tell here for wildcard aliases = (only + * a later visitor call will determine this). This means that + * wildcard aliases must never have optional keys in their sou= rce + * path. + */ + if (!a->alias || alias_present(qiv, a, a->alias)) { + *implicit_object =3D true; + } + } + } + + return false; +} + +static bool find_object_member(QObjectInputVisitor *qiv, + StackObject **so, const char **name, + bool *implicit_object, Error **errp) +{ + StackObject *cur_so =3D *so; + QDict *qdict =3D qobject_to(QDict, cur_so->obj); + const char *found =3D NULL; + bool found_is_wildcard =3D false; + InputVisitorAlias *a; + + if (implicit_object) { + *implicit_object =3D false; + } + + /* Directly present in the container */ + if (qdict_haskey(qdict, *name)) { + found =3D *name; + } + + /* + * Find aliases whose source path matches @name in this StackObject. W= e can + * then get the value with the key a->alias from a->alias_so. + */ + QSLIST_FOREACH(a, &cur_so->aliases, next) { + if (a->alias =3D=3D NULL && found) { + /* + * Skip wildcard aliases if we already have a match. This is + * not a conflict that should result in an error. + */ + continue; + } + + if (!alias_source_matches(qiv, cur_so, a, *name, implicit_object))= { + continue; + } + + if (!alias_present(qiv, a, *name)) { + continue; + } + + if (found && !found_is_wildcard) { + error_setg(errp, "Value for parameter %s was already given " + "through an alias", full_name_so(qiv, *name, *so)); + return false; + } else { + found =3D a->alias ?: *name; + *so =3D a->alias_so; + found_is_wildcard =3D !a->alias; + } + } + + /* Chained aliases: *so/found might be the source of another alias */ + if (found && (*so !=3D cur_so || found !=3D *name)) { + find_object_member(qiv, so, &found, NULL, errp); + } + + *name =3D found; + return found; +} + static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv, const char *name, - bool consume) + bool consume, Error **errp) { StackObject *tos; QObject *qobj; @@ -161,10 +293,24 @@ static QObject *qobject_input_try_get_object(QObjectI= nputVisitor *qiv, assert(qobj); =20 if (qobject_type(qobj) =3D=3D QTYPE_QDICT) { - assert(name); - ret =3D qdict_get(qobject_to(QDict, qobj), name); - if (tos->h && consume && ret) { - bool removed =3D g_hash_table_remove(tos->h, name); + StackObject *so =3D tos; + const char *key =3D name; + bool implicit_object; + + assert(key); + if (!find_object_member(qiv, &so, &key, &implicit_object, errp)) { + if (implicit_object) { + if (!qiv->empty_qdict) { + qiv->empty_qdict =3D qdict_new(); + } + return QOBJECT(qiv->empty_qdict); + } else { + return NULL; + } + } + ret =3D qdict_get(qobject_to(QDict, so->obj), key); + if (so->h && consume && ret) { + bool removed =3D g_hash_table_remove(so->h, key); assert(removed); } } else { @@ -190,9 +336,10 @@ static QObject *qobject_input_get_object(QObjectInputV= isitor *qiv, const char *name, bool consume, Error **errp) { - QObject *obj =3D qobject_input_try_get_object(qiv, name, consume); + ERRP_GUARD(); + QObject *obj =3D qobject_input_try_get_object(qiv, name, consume, errp= ); =20 - if (!obj) { + if (!obj && !*errp) { error_setg(errp, QERR_MISSING_PARAMETER, full_name(qiv, name)); } return obj; @@ -764,13 +911,16 @@ static bool qobject_input_type_size_keyval(Visitor *v= , const char *name, static void qobject_input_optional(Visitor *v, const char *name, bool *pre= sent) { QObjectInputVisitor *qiv =3D to_qiv(v); - QObject *qobj =3D qobject_input_try_get_object(qiv, name, false); + Error *local_err =3D NULL; + QObject *qobj =3D qobject_input_try_get_object(qiv, name, false, &loca= l_err); =20 - if (!qobj) { + /* If there was an error, let the caller try and run into the error */ + if (!qobj && !local_err) { *present =3D false; return; } =20 + error_free(local_err); *present =3D true; } =20 @@ -785,6 +935,7 @@ static void qobject_input_free(Visitor *v) qobject_input_stack_object_free(tos); } =20 + qobject_unref(qiv->empty_qdict); qobject_unref(qiv->root); if (qiv->errname) { g_string_free(qiv->errname, TRUE); --=20 2.28.0 From nobody Sun Feb 8 04:18:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.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=1605202430; cv=none; d=zohomail.com; s=zohoarc; b=UtgSa5s7rZ2NxioJmZdfDEO//lNylyneyLgytIHl1eMb22mONzDfxgsWbBjDyYPVwXKtYGhVDHKGwsqIBJJ7o6eImDdSB7UADVBQGxNi7aUOL0wCHmEWmplG8Ax55pc0jHjvVvqBoJsnxyk8YJyKTD8AV4WkiKC0i2dvUkU9csE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605202430; 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; bh=ixBYd2cDtOY/iUT803LUCen8znSZN7Hg9/38Hw7Rd/s=; b=TuNMvlwTcRuz342ug3b+y9bs14U8XlJTflpS8+Y4YUOPgLjm0Y1K4WyZhxj5FdRlNc9jxZ9D8UxWgt0pCNlKC7rbbMVOdCPldCaCDOjQTn2AD741mrmJPcFE+cveFeZplXes3aXTCldVzZCRw+Tuq2cWi7UF1YBhNSpaIMEmRuo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.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 1605202430600987.0615867063717; Thu, 12 Nov 2020 09:33:50 -0800 (PST) Received: from localhost ([::1]:51030 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kdGTl-00067g-3n for importer@patchew.org; Thu, 12 Nov 2020 12:33:49 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:57810) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kdGPL-0001Lm-V6 for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:16 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:53070) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kdGPJ-0006t7-87 for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:15 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-413-SncQjqvCOsqd8btQIJINyA-1; Thu, 12 Nov 2020 12:29:09 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2259B186DD3A for ; Thu, 12 Nov 2020 17:29:08 +0000 (UTC) Received: from merkur.fritz.box (ovpn-115-57.ams2.redhat.com [10.36.115.57]) by smtp.corp.redhat.com (Postfix) with ESMTP id F2FBC5D9E4; Thu, 12 Nov 2020 17:29:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605202152; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ixBYd2cDtOY/iUT803LUCen8znSZN7Hg9/38Hw7Rd/s=; b=LmQWyGkFMDB+pFoMHydFwslo4X92EyrAhuV8UUUXTnDKafb5xVTwf7qWFSx7v6WSF3n0N7 xD6vkLyKajYchkvzhBfpaT2pDCww8o6OPjP/8UkZfwBpRAVh14Yz8HVx1RUVlgn3+0GALd cA7X7Vr6Hws5GKE/Erql9+LBzlnV+Xo= X-MC-Unique: SncQjqvCOsqd8btQIJINyA-1 From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH 5/6] qapi: Add support for aliases Date: Thu, 12 Nov 2020 18:28:49 +0100 Message-Id: <20201112172850.401925-6-kwolf@redhat.com> In-Reply-To: <20201112172850.401925-1-kwolf@redhat.com> References: <20201112172850.401925-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kwolf@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=216.205.24.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/12 08:00:44 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: kwolf@redhat.com, jsnow@redhat.com, armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Introduce alias definitions for object types (structs and unions). This allows using the same QAPI type and visitor for many syntax variations that exist in the external representation, like between QMP and the command line. It also provides a new tool for evolving the schema while maintaining backwards compatibility during a deprecation period. Signed-off-by: Kevin Wolf --- docs/devel/qapi-code-gen.txt | 37 +++++++++++++++++++++++--- docs/sphinx/qapidoc.py | 2 +- scripts/qapi/expr.py | 34 +++++++++++++++++++++-- scripts/qapi/schema.py | 27 +++++++++++++++---- scripts/qapi/types.py | 4 ++- scripts/qapi/visit.py | 33 ++++++++++++++++++++--- tests/qapi-schema/test-qapi.py | 7 ++++- tests/qapi-schema/double-type.err | 2 +- tests/qapi-schema/unknown-expr-key.err | 2 +- 9 files changed, 130 insertions(+), 18 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 6906a06ad2..6da14d5275 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -231,7 +231,8 @@ Syntax: 'data': MEMBERS, '*base': STRING, '*if': COND, - '*features': FEATURES } + '*features': FEATURES, + '*aliases': ALIASES } MEMBERS =3D { MEMBER, ... } MEMBER =3D STRING : TYPE-REF | STRING : { 'type': TYPE-REF, @@ -286,13 +287,15 @@ Syntax: UNION =3D { 'union': STRING, 'data': BRANCHES, '*if': COND, - '*features': FEATURES } + '*features': FEATURES, + '*aliases': ALIASES } | { 'union': STRING, 'data': BRANCHES, 'base': ( MEMBERS | STRING ), 'discriminator': STRING, '*if': COND, - '*features': FEATURES } + '*features': FEATURES, + '*aliases': ALIASES } BRANCHES =3D { BRANCH, ... } BRANCH =3D STRING : TYPE-REF | STRING : { 'type': TYPE-REF, '*if': COND } @@ -837,6 +840,34 @@ shows a conditional entity only when the condition is = satisfied in this particular build. =20 =20 +=3D=3D=3D Aliases =3D=3D=3D + +Object types, including structs and unions, can contain alias +definitions. + +Aliases define alternative member names that may be used in the +external representation to provide a value for a member in the same +object or in a nested object. + +Syntax: + ALIAS =3D { '*alias': STRING, + 'source': [ STRING, ... ] } + +'source' is a list of member names representing the path to an object +member, starting from the type where the alias definition is +specified. It may refer to another alias name. It is allowed to use +a path that doesn't necessarily match an existing member in every +variant or even at all; in this case, the alias remains unused. + +If 'alias' is present, then the single member referred to by 'source' +is made accessible with the name given in 'alias' in the type where +the alias definition is specified. + +If 'alias' is not present, then all members in the object referred to +by 'source' are made accessible in the type where the alias definition +is specified with the same name as they have in 'source'. + + =3D=3D=3D Documentation comments =3D=3D=3D =20 A multi-line comment that starts and ends with a '##' line is a diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py index e03abcbb95..6c94c01148 100644 --- a/docs/sphinx/qapidoc.py +++ b/docs/sphinx/qapidoc.py @@ -310,7 +310,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor): + self._nodes_for_if_section(ifcond)) =20 def visit_object_type(self, name, info, ifcond, features, - base, members, variants): + base, members, variants, aliases): doc =3D self._cur_doc if base and base.is_implicit(): base =3D None diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py index 2fcaaa2497..21fded529b 100644 --- a/scripts/qapi/expr.py +++ b/scripts/qapi/expr.py @@ -198,6 +198,32 @@ def check_features(features, info): check_if(f, info, source) =20 =20 +def check_aliases(aliases, info): + if aliases is None: + return + if not isinstance(aliases, list): + raise QAPISemError(info, "'aliases' must be an array") + for a in aliases: + if not isinstance(a, dict): + raise QAPISemError(info, "'aliases' entries must be objects") + check_keys(a, info, "alias", ['source'], ['alias']) + + if 'alias' in a: + source =3D "alias member 'alias'" + check_name_is_str(a['alias'], info, source) + check_name_str(a['alias'], info, source) + + if not isinstance(a['source'], list): + raise QAPISemError(info, "'source' must be an array") + if not a['source']: + raise QAPISemError(info, "'source' must not be empty") + + source =3D "element of alias member 'source'" + for s in a['source']: + check_name_is_str(s, info, source) + check_name_str(s, info, source) + + def check_enum(expr, info): name =3D expr['enum'] members =3D expr['data'] @@ -228,6 +254,7 @@ def check_struct(expr, info): =20 check_type(members, info, "'data'", allow_dict=3Dname) check_type(expr.get('base'), info, "'base'") + check_aliases(expr.get('aliases'), info) =20 =20 def check_union(expr, info): @@ -245,6 +272,8 @@ def check_union(expr, info): raise QAPISemError(info, "'discriminator' requires 'base'") check_name_is_str(discriminator, info, "'discriminator'") =20 + check_aliases(expr.get('aliases'), info) + for (key, value) in members.items(): source =3D "'data' member '%s'" % key check_name_str(key, info, source) @@ -331,7 +360,7 @@ def check_exprs(exprs): elif meta =3D=3D 'union': check_keys(expr, info, meta, ['union', 'data'], - ['base', 'discriminator', 'if', 'features']) + ['base', 'discriminator', 'if', 'features', 'aliase= s']) normalize_members(expr.get('base')) normalize_members(expr['data']) check_union(expr, info) @@ -342,7 +371,8 @@ def check_exprs(exprs): check_alternate(expr, info) elif meta =3D=3D 'struct': check_keys(expr, info, meta, - ['struct', 'data'], ['base', 'if', 'features']) + ['struct', 'data'], + ['base', 'if', 'features', 'aliases']) normalize_members(expr['data']) check_struct(expr, info) elif meta =3D=3D 'command': diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index 720449feee..5daa137163 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -117,7 +117,7 @@ class QAPISchemaVisitor: pass =20 def visit_object_type(self, name, info, ifcond, features, - base, members, variants): + base, members, variants, aliases): pass =20 def visit_object_type_flat(self, name, info, ifcond, features, @@ -331,9 +331,16 @@ class QAPISchemaArrayType(QAPISchemaType): return "%s type ['%s']" % (self.meta, self._element_type_name) =20 =20 +class QAPISchemaAlias: + def __init__(self, alias, source): + assert source + self.alias =3D alias + self.source =3D source + + class QAPISchemaObjectType(QAPISchemaType): def __init__(self, name, info, doc, ifcond, features, - base, local_members, variants): + base, local_members, variants, aliases=3DNone): # struct has local_members, optional base, and no variants # flat union has base, variants, and no local_members # simple union has local_members, variants, and no base @@ -351,6 +358,7 @@ class QAPISchemaObjectType(QAPISchemaType): self.local_members =3D local_members self.variants =3D variants self.members =3D None + self.aliases =3D aliases or [] =20 def check(self, schema): # This calls another type T's .check() exactly when the C @@ -443,7 +451,7 @@ class QAPISchemaObjectType(QAPISchemaType): super().visit(visitor) visitor.visit_object_type( self.name, self.info, self.ifcond, self.features, - self.base, self.local_members, self.variants) + self.base, self.local_members, self.variants, self.aliases) visitor.visit_object_type_flat( self.name, self.info, self.ifcond, self.features, self.members, self.variants) @@ -934,6 +942,12 @@ class QAPISchema: return [QAPISchemaFeature(f['name'], info, f.get('if')) for f in features] =20 + def _make_aliases(self, aliases): + if aliases is None: + return [] + return [QAPISchemaAlias(a.get('alias'), a['source']) + for a in aliases] + def _make_enum_members(self, values, info): return [QAPISchemaEnumMember(v['name'], info, v.get('if')) for v in values] @@ -1008,11 +1022,12 @@ class QAPISchema: base =3D expr.get('base') data =3D expr['data'] ifcond =3D expr.get('if') + aliases =3D self._make_aliases(expr.get('aliases')) features =3D self._make_features(expr.get('features'), info) self._def_entity(QAPISchemaObjectType( name, info, doc, ifcond, features, base, self._make_members(data, info), - None)) + None, aliases)) =20 def _make_variant(self, case, typ, ifcond, info): return QAPISchemaVariant(case, info, typ, ifcond) @@ -1031,6 +1046,7 @@ class QAPISchema: data =3D expr['data'] base =3D expr.get('base') ifcond =3D expr.get('if') + aliases =3D self._make_aliases(expr.get('aliases')) features =3D self._make_features(expr.get('features'), info) tag_name =3D expr.get('discriminator') tag_member =3D None @@ -1055,7 +1071,8 @@ class QAPISchema: QAPISchemaObjectType(name, info, doc, ifcond, features, base, members, QAPISchemaVariants( - tag_name, info, tag_member, variants)= )) + tag_name, info, tag_member, variants), + aliases)) =20 def _def_alternate_type(self, expr, info, doc): name =3D expr['alternate'] diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py index 2b4916cdaa..e870bebb7e 100644 --- a/scripts/qapi/types.py +++ b/scripts/qapi/types.py @@ -25,6 +25,7 @@ from .common import ( from .gen import QAPISchemaModularCVisitor, ifcontext from .schema import ( QAPISchema, + QAPISchemaAlias, QAPISchemaEnumMember, QAPISchemaFeature, QAPISchemaObjectType, @@ -332,7 +333,8 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisito= r): features: List[QAPISchemaFeature], base: Optional[QAPISchemaObjectType], members: List[QAPISchemaObjectTypeMember], - variants: Optional[QAPISchemaVariants]) -> None: + variants: Optional[QAPISchemaVariants], + aliases: List[QAPISchemaAlias]) -> None: # Nothing to do for the special empty builtin if name =3D=3D 'q_empty': return diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py index 339f152152..a35921ef2c 100644 --- a/scripts/qapi/visit.py +++ b/scripts/qapi/visit.py @@ -26,6 +26,7 @@ from .common import ( from .gen import QAPISchemaModularCVisitor, ifcontext from .schema import ( QAPISchema, + QAPISchemaAlias, QAPISchemaEnumMember, QAPISchemaEnumType, QAPISchemaFeature, @@ -60,7 +61,8 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s= *obj, Error **errp); def gen_visit_object_members(name: str, base: Optional[QAPISchemaObjectType], members: List[QAPISchemaObjectTypeMember], - variants: Optional[QAPISchemaVariants]) -> st= r: + variants: Optional[QAPISchemaVariants], + aliases: List[QAPISchemaAlias]) -> str: ret =3D mcgen(''' =20 bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **er= rp) @@ -68,6 +70,25 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)= s *obj, Error **errp) ''', c_name=3Dc_name(name)) =20 + if aliases: + ret +=3D mcgen(''' + visit_start_alias_scope(v); +''') + + for a in aliases: + if a.alias: + alias =3D '"%s"' % a.alias + else: + alias =3D "NULL" + + source_list =3D ", ".join('"%s"' % x for x in a.source) + source =3D "(const char * []) { %s, NULL }" % source_list + + ret +=3D mcgen(''' + visit_define_alias(v, %(alias)s, %(source)s); +''', + alias=3Dalias, source=3Dsource) + if base: ret +=3D mcgen(''' if (!visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, errp)) { @@ -133,6 +154,11 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_nam= e)s *obj, Error **errp) } ''') =20 + if aliases: + ret +=3D mcgen(''' + visit_end_alias_scope(v); +''') + ret +=3D mcgen(''' return true; } @@ -361,14 +387,15 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVis= itor): features: List[QAPISchemaFeature], base: Optional[QAPISchemaObjectType], members: List[QAPISchemaObjectTypeMember], - variants: Optional[QAPISchemaVariants]) -> None: + variants: Optional[QAPISchemaVariants], + aliases: List[QAPISchemaAlias]) -> None: # Nothing to do for the special empty builtin if name =3D=3D 'q_empty': return with ifcontext(ifcond, self._genh, self._genc): self._genh.add(gen_visit_members_decl(name)) self._genc.add(gen_visit_object_members(name, base, - members, variants)) + members, variants, ali= ases)) # TODO Worth changing the visitor signature, so we could # directly use rather than repeat type.is_implicit()? if not name.startswith('q_'): diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index e8db9d09d9..adf8bda89a 100755 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -47,7 +47,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): self._print_if(ifcond) =20 def visit_object_type(self, name, info, ifcond, features, - base, members, variants): + base, members, variants, aliases): print('object %s' % name) if base: print(' base %s' % base.name) @@ -56,6 +56,11 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): % (m.name, m.type.name, m.optional)) self._print_if(m.ifcond, 8) self._print_features(m.features, indent=3D8) + for a in aliases: + if a.alias: + print(' alias %s -> %s' % (a.alias, '/'.join(a.source))) + else: + print(' alias * -> %s/*' % '/'.join(a.source)) self._print_variants(variants) self._print_if(ifcond) self._print_features(features) diff --git a/tests/qapi-schema/double-type.err b/tests/qapi-schema/double-t= ype.err index 71fc4dbb52..5d25d7623c 100644 --- a/tests/qapi-schema/double-type.err +++ b/tests/qapi-schema/double-type.err @@ -1,3 +1,3 @@ double-type.json: In struct 'bar': double-type.json:2: struct has unknown key 'command' -Valid keys are 'base', 'data', 'features', 'if', 'struct'. +Valid keys are 'aliases', 'base', 'data', 'features', 'if', 'struct'. diff --git a/tests/qapi-schema/unknown-expr-key.err b/tests/qapi-schema/unk= nown-expr-key.err index c5f395bf79..7429d1ff03 100644 --- a/tests/qapi-schema/unknown-expr-key.err +++ b/tests/qapi-schema/unknown-expr-key.err @@ -1,3 +1,3 @@ unknown-expr-key.json: In struct 'bar': unknown-expr-key.json:2: struct has unknown keys 'bogus', 'phony' -Valid keys are 'base', 'data', 'features', 'if', 'struct'. +Valid keys are 'aliases', 'base', 'data', 'features', 'if', 'struct'. --=20 2.28.0 From nobody Sun Feb 8 04:18:03 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.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=1605202543; cv=none; d=zohomail.com; s=zohoarc; b=knyrCLIGR347g3y4sSCvq7eN2b6xooqxvsghA2yhbJnlZ+PsmyQw/pqpMhpsc61xrDbva2IoSGvHerArxEx+Y+kSsVEvYTvCXvk6Zgo0yTHfHiMkaFL7aGOoX2e/ZUjElhTDK6dAOopxGwsPohYG4Dte4WX6UWgFQVcFB9ziFg4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605202543; 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; bh=mZ0Dkg5mqkaoLCMiJGJoQ4h8UQ7MfQ9+5Zr1+zhkCOM=; b=QSHcMoBOCF/NzhlL7gbryNFatWlEqfNoOU9Z/3kggBMHYRGOKjbENyWL4pwZnDpu82UHGBPlhIBN7YzgIAbmC0hWvXEKtPGeGhKLJYOnLSlLH/GJfAET1drOk9ByquHIqPpEdcdq77g3b/Ag2SETa4ysPBpVSCFnriQoz6poPBs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.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 1605202543701814.7415394774309; Thu, 12 Nov 2020 09:35:43 -0800 (PST) Received: from localhost ([::1]:54362 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kdGVa-0007a5-KH for importer@patchew.org; Thu, 12 Nov 2020 12:35:42 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:57812) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kdGPM-0001Ms-Ez for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:16 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:43827) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kdGPJ-0006tU-QE for qemu-devel@nongnu.org; Thu, 12 Nov 2020 12:29:16 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-322-Jbze8yjMNAOTaiDhMgZ_iQ-1; Thu, 12 Nov 2020 12:29:11 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 73EB11009E2F for ; Thu, 12 Nov 2020 17:29:09 +0000 (UTC) Received: from merkur.fritz.box (ovpn-115-57.ams2.redhat.com [10.36.115.57]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6EF165D9E4; Thu, 12 Nov 2020 17:29:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1605202153; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mZ0Dkg5mqkaoLCMiJGJoQ4h8UQ7MfQ9+5Zr1+zhkCOM=; b=Ms+rENT3g4VJzAbO0MmSdhb/ii85C3tHrIt79PaE7CitCCYqtkOfc+TVt4oWadlsSEU0a8 yLnSzi+IXbayz/BIWjVkB8mcKZcF9LypjBUcJXr3lM3D7lAX8x/v+Jq+HpX2O0pKpXTzA5 HONa9xf1RwjyMlqY80cGF3/BdmV5l6o= X-MC-Unique: Jbze8yjMNAOTaiDhMgZ_iQ-1 From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH 6/6] tests/qapi-schema: Test cases for aliases Date: Thu, 12 Nov 2020 18:28:50 +0100 Message-Id: <20201112172850.401925-7-kwolf@redhat.com> In-Reply-To: <20201112172850.401925-1-kwolf@redhat.com> References: <20201112172850.401925-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kwolf@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=63.128.21.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/12 00:52:29 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: kwolf@redhat.com, jsnow@redhat.com, armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Signed-off-by: Kevin Wolf --- tests/qapi-schema/alias-bad-type.err | 2 ++ tests/qapi-schema/alias-bad-type.json | 3 ++ tests/qapi-schema/alias-bad-type.out | 0 tests/qapi-schema/alias-missing-source.err | 2 ++ tests/qapi-schema/alias-missing-source.json | 3 ++ tests/qapi-schema/alias-missing-source.out | 0 tests/qapi-schema/alias-name-bad-type.err | 2 ++ tests/qapi-schema/alias-name-bad-type.json | 3 ++ tests/qapi-schema/alias-name-bad-type.out | 0 tests/qapi-schema/alias-source-bad-type.err | 2 ++ tests/qapi-schema/alias-source-bad-type.json | 3 ++ tests/qapi-schema/alias-source-bad-type.out | 0 .../alias-source-elem-bad-type.err | 2 ++ .../alias-source-elem-bad-type.json | 3 ++ .../alias-source-elem-bad-type.out | 0 tests/qapi-schema/alias-source-empty.err | 2 ++ tests/qapi-schema/alias-source-empty.json | 3 ++ tests/qapi-schema/alias-source-empty.out | 0 tests/qapi-schema/alias-unknown-key.err | 3 ++ tests/qapi-schema/alias-unknown-key.json | 3 ++ tests/qapi-schema/alias-unknown-key.out | 0 tests/qapi-schema/aliases-bad-type.err | 2 ++ tests/qapi-schema/aliases-bad-type.json | 3 ++ tests/qapi-schema/aliases-bad-type.out | 0 tests/qapi-schema/meson.build | 8 +++++ tests/qapi-schema/qapi-schema-test.json | 24 +++++++++++++++ tests/qapi-schema/qapi-schema-test.out | 29 +++++++++++++++++++ 27 files changed, 102 insertions(+) create mode 100644 tests/qapi-schema/alias-bad-type.err create mode 100644 tests/qapi-schema/alias-bad-type.json create mode 100644 tests/qapi-schema/alias-bad-type.out create mode 100644 tests/qapi-schema/alias-missing-source.err create mode 100644 tests/qapi-schema/alias-missing-source.json create mode 100644 tests/qapi-schema/alias-missing-source.out create mode 100644 tests/qapi-schema/alias-name-bad-type.err create mode 100644 tests/qapi-schema/alias-name-bad-type.json create mode 100644 tests/qapi-schema/alias-name-bad-type.out create mode 100644 tests/qapi-schema/alias-source-bad-type.err create mode 100644 tests/qapi-schema/alias-source-bad-type.json create mode 100644 tests/qapi-schema/alias-source-bad-type.out create mode 100644 tests/qapi-schema/alias-source-elem-bad-type.err create mode 100644 tests/qapi-schema/alias-source-elem-bad-type.json create mode 100644 tests/qapi-schema/alias-source-elem-bad-type.out create mode 100644 tests/qapi-schema/alias-source-empty.err create mode 100644 tests/qapi-schema/alias-source-empty.json create mode 100644 tests/qapi-schema/alias-source-empty.out create mode 100644 tests/qapi-schema/alias-unknown-key.err create mode 100644 tests/qapi-schema/alias-unknown-key.json create mode 100644 tests/qapi-schema/alias-unknown-key.out create mode 100644 tests/qapi-schema/aliases-bad-type.err create mode 100644 tests/qapi-schema/aliases-bad-type.json create mode 100644 tests/qapi-schema/aliases-bad-type.out diff --git a/tests/qapi-schema/alias-bad-type.err b/tests/qapi-schema/alias= -bad-type.err new file mode 100644 index 0000000000..a982d380b8 --- /dev/null +++ b/tests/qapi-schema/alias-bad-type.err @@ -0,0 +1,2 @@ +alias-bad-type.json: In struct 'AliasStruct0': +alias-bad-type.json:1: 'aliases' entries must be objects diff --git a/tests/qapi-schema/alias-bad-type.json b/tests/qapi-schema/alia= s-bad-type.json new file mode 100644 index 0000000000..0aa5d206fe --- /dev/null +++ b/tests/qapi-schema/alias-bad-type.json @@ -0,0 +1,3 @@ +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': [ 'must be an object' ] } diff --git a/tests/qapi-schema/alias-bad-type.out b/tests/qapi-schema/alias= -bad-type.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/alias-missing-source.err b/tests/qapi-schema= /alias-missing-source.err new file mode 100644 index 0000000000..1cfe8a6aa5 --- /dev/null +++ b/tests/qapi-schema/alias-missing-source.err @@ -0,0 +1,2 @@ +alias-missing-source.json: In struct 'AliasStruct0': +alias-missing-source.json:1: alias misses key 'source' diff --git a/tests/qapi-schema/alias-missing-source.json b/tests/qapi-schem= a/alias-missing-source.json new file mode 100644 index 0000000000..4ae22c2221 --- /dev/null +++ b/tests/qapi-schema/alias-missing-source.json @@ -0,0 +1,3 @@ +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': [ { 'alias': 'bar' } ] } diff --git a/tests/qapi-schema/alias-missing-source.out b/tests/qapi-schema= /alias-missing-source.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/alias-name-bad-type.err b/tests/qapi-schema/= alias-name-bad-type.err new file mode 100644 index 0000000000..83b9fe0b65 --- /dev/null +++ b/tests/qapi-schema/alias-name-bad-type.err @@ -0,0 +1,2 @@ +alias-name-bad-type.json: In struct 'AliasStruct0': +alias-name-bad-type.json:1: alias member 'alias' requires a string name diff --git a/tests/qapi-schema/alias-name-bad-type.json b/tests/qapi-schema= /alias-name-bad-type.json new file mode 100644 index 0000000000..6d993be332 --- /dev/null +++ b/tests/qapi-schema/alias-name-bad-type.json @@ -0,0 +1,3 @@ +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': [ { 'alias': ['bar'], 'source': ['foo'] } ] } diff --git a/tests/qapi-schema/alias-name-bad-type.out b/tests/qapi-schema/= alias-name-bad-type.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/alias-source-bad-type.err b/tests/qapi-schem= a/alias-source-bad-type.err new file mode 100644 index 0000000000..e3b949ff77 --- /dev/null +++ b/tests/qapi-schema/alias-source-bad-type.err @@ -0,0 +1,2 @@ +alias-source-bad-type.json: In struct 'AliasStruct0': +alias-source-bad-type.json:1: 'source' must be an array diff --git a/tests/qapi-schema/alias-source-bad-type.json b/tests/qapi-sche= ma/alias-source-bad-type.json new file mode 100644 index 0000000000..0099a6439e --- /dev/null +++ b/tests/qapi-schema/alias-source-bad-type.json @@ -0,0 +1,3 @@ +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': [ { 'alias': 'bar', 'source': 'foo' } ] } diff --git a/tests/qapi-schema/alias-source-bad-type.out b/tests/qapi-schem= a/alias-source-bad-type.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/alias-source-elem-bad-type.err b/tests/qapi-= schema/alias-source-elem-bad-type.err new file mode 100644 index 0000000000..44d219e352 --- /dev/null +++ b/tests/qapi-schema/alias-source-elem-bad-type.err @@ -0,0 +1,2 @@ +alias-source-elem-bad-type.json: In struct 'AliasStruct0': +alias-source-elem-bad-type.json:1: element of alias member 'source' requir= es a string name diff --git a/tests/qapi-schema/alias-source-elem-bad-type.json b/tests/qapi= -schema/alias-source-elem-bad-type.json new file mode 100644 index 0000000000..28cb1c37c5 --- /dev/null +++ b/tests/qapi-schema/alias-source-elem-bad-type.json @@ -0,0 +1,3 @@ +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': [ { 'alias': 'bar', 'source': ['foo', true] } ] } diff --git a/tests/qapi-schema/alias-source-elem-bad-type.out b/tests/qapi-= schema/alias-source-elem-bad-type.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/alias-source-empty.err b/tests/qapi-schema/a= lias-source-empty.err new file mode 100644 index 0000000000..f7687e404c --- /dev/null +++ b/tests/qapi-schema/alias-source-empty.err @@ -0,0 +1,2 @@ +alias-source-empty.json: In struct 'AliasStruct0': +alias-source-empty.json:1: 'source' must not be empty diff --git a/tests/qapi-schema/alias-source-empty.json b/tests/qapi-schema/= alias-source-empty.json new file mode 100644 index 0000000000..9d2d2f109f --- /dev/null +++ b/tests/qapi-schema/alias-source-empty.json @@ -0,0 +1,3 @@ +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': [ { 'alias': 'bar', 'source': [] } ] } diff --git a/tests/qapi-schema/alias-source-empty.out b/tests/qapi-schema/a= lias-source-empty.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/alias-unknown-key.err b/tests/qapi-schema/al= ias-unknown-key.err new file mode 100644 index 0000000000..d4dc5e4611 --- /dev/null +++ b/tests/qapi-schema/alias-unknown-key.err @@ -0,0 +1,3 @@ +alias-unknown-key.json: In struct 'AliasStruct0': +alias-unknown-key.json:1: alias has unknown key 'known' +Valid keys are 'alias', 'source'. diff --git a/tests/qapi-schema/alias-unknown-key.json b/tests/qapi-schema/a= lias-unknown-key.json new file mode 100644 index 0000000000..444f80ca30 --- /dev/null +++ b/tests/qapi-schema/alias-unknown-key.json @@ -0,0 +1,3 @@ +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': [ { 'alias': 'bar', 'source': ['foo'], 'known': false } ] } diff --git a/tests/qapi-schema/alias-unknown-key.out b/tests/qapi-schema/al= ias-unknown-key.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/aliases-bad-type.err b/tests/qapi-schema/ali= ases-bad-type.err new file mode 100644 index 0000000000..7ffe789ec0 --- /dev/null +++ b/tests/qapi-schema/aliases-bad-type.err @@ -0,0 +1,2 @@ +aliases-bad-type.json: In struct 'AliasStruct0': +aliases-bad-type.json:1: 'aliases' must be an array diff --git a/tests/qapi-schema/aliases-bad-type.json b/tests/qapi-schema/al= iases-bad-type.json new file mode 100644 index 0000000000..4bbf6d6b20 --- /dev/null +++ b/tests/qapi-schema/aliases-bad-type.json @@ -0,0 +1,3 @@ +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': 'this must be an array' } diff --git a/tests/qapi-schema/aliases-bad-type.out b/tests/qapi-schema/ali= ases-bad-type.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build index 304ef939bd..710cd60b61 100644 --- a/tests/qapi-schema/meson.build +++ b/tests/qapi-schema/meson.build @@ -3,6 +3,14 @@ test_env.set('PYTHONPATH', meson.source_root() / 'scripts') test_env.set('PYTHONIOENCODING', 'utf-8') =20 schemas =3D [ + 'alias-bad-type.json', + 'aliases-bad-type.json', + 'alias-missing-source.json', + 'alias-name-bad-type.json', + 'alias-source-bad-type.json', + 'alias-source-elem-bad-type.json', + 'alias-source-empty.json', + 'alias-unknown-key.json', 'alternate-any.json', 'alternate-array.json', 'alternate-base.json', diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qa= pi-schema-test.json index 63f92adf68..cc2497b2a2 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -325,3 +325,27 @@ =20 { 'event': 'TEST-EVENT-FEATURES1', 'features': [ 'deprecated' ] } + +# test 'aliases' + +{ 'struct': 'AliasStruct0', + 'data': { 'foo': 'int' }, + 'aliases': [] } +{ 'struct': 'AliasStruct1', + 'data': { 'foo': 'int' }, + 'aliases': [ { 'alias': 'bar', 'source': ['foo'] } ] } +{ 'struct': 'AliasStruct2', + 'data': { 'nested': 'AliasStruct1' }, + 'aliases': [ { 'alias': 'bar', 'source': ['nested', 'foo'] } ] } +{ 'struct': 'AliasStruct3', + 'data': { 'nested': 'AliasStruct1' }, + 'aliases': [ { 'source': ['nested'] } ] } + +{ 'union': 'AliasFlatUnion', + 'base': { 'tag': 'FeatureEnum1' }, + 'discriminator': 'tag', + 'data': { 'eins': 'FeatureStruct1' }, + 'aliases': [ { 'alias': 'bar', 'source': ['foo'] } ] } +{ 'union': 'AliasSimpleUnion', + 'data': { 'eins': 'AliasStruct1' }, + 'aliases': [ { 'source': ['data'] } ] } diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qap= i-schema-test.out index 8868ca0dca..8ed88a257d 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -443,6 +443,35 @@ command test-command-cond-features3 None -> None event TEST-EVENT-FEATURES1 None boxed=3DFalse feature deprecated +object AliasStruct0 + member foo: int optional=3DFalse +object AliasStruct1 + member foo: int optional=3DFalse + alias bar -> foo +object AliasStruct2 + member nested: AliasStruct1 optional=3DFalse + alias bar -> nested/foo +object AliasStruct3 + member nested: AliasStruct1 optional=3DFalse + alias * -> nested/* +object q_obj_AliasFlatUnion-base + member tag: FeatureEnum1 optional=3DFalse +object AliasFlatUnion + base q_obj_AliasFlatUnion-base + alias bar -> foo + tag tag + case eins: FeatureStruct1 + case zwei: q_empty + case drei: q_empty +object q_obj_AliasStruct1-wrapper + member data: AliasStruct1 optional=3DFalse +enum AliasSimpleUnionKind + member eins +object AliasSimpleUnion + member type: AliasSimpleUnionKind optional=3DFalse + alias * -> data/* + tag type + case eins: q_obj_AliasStruct1-wrapper module include/sub-module.json include sub-sub-module.json object SecondArrayRef --=20 2.28.0