* [PULL 0/6] QAPI patches patches for 2025-02-10
@ 2025-02-10 8:39 Markus Armbruster
2025-02-10 8:39 ` [PULL 1/6] qapi: fix colon in Since tag section Markus Armbruster
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Markus Armbruster @ 2025-02-10 8:39 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha
The following changes since commit 04d3d0e9f54d4c42759f3810aa135ce314d98dc4:
Merge tag 'hppa-system-for-v10-diva-artist-pull-request' of https://github.com/hdeller/qemu-hppa into staging (2025-02-08 09:00:57 -0500)
are available in the Git repository at:
https://repo.or.cz/qemu/armbru.git tags/pull-qapi-2025-02-10
for you to fetch changes up to 9c339601b652edf91d74a626999285e3245b2589:
qapi: expose all schema features to code (2025-02-10 09:14:14 +0100)
----------------------------------------------------------------
QAPI patches patches for 2025-02-10
----------------------------------------------------------------
Daniel P. Berrangé (4):
qapi: cope with feature names containing a '-'
qapi: change 'unsigned special_features' to 'uint64_t features'
qapi: rename 'special_features' to 'features'
qapi: expose all schema features to code
Victor Toso (1):
qapi: fix colon in Since tag section
Zhang Boyang (1):
qapi/ui: Fix documentation of upper bound value in InputMoveEvent
meson.build | 1 +
qapi/cxl.json | 4 +--
qapi/ui.json | 2 +-
include/qapi/compat-policy.h | 2 +-
include/qapi/qmp/dispatch.h | 4 +--
include/qapi/util.h | 2 +-
include/qapi/visitor-impl.h | 4 +--
include/qapi/visitor.h | 12 ++++----
qapi/qapi-forward-visitor.c | 8 +++---
qapi/qapi-util.c | 6 ++--
qapi/qapi-visit-core.c | 12 ++++----
qapi/qmp-dispatch.c | 2 +-
qapi/qmp-registry.c | 4 +--
qapi/qobject-input-visitor.c | 4 +--
qapi/qobject-output-visitor.c | 6 ++--
scripts/qapi/commands.py | 5 ++--
scripts/qapi/features.py | 48 ++++++++++++++++++++++++++++++++
scripts/qapi/gen.py | 9 +++---
scripts/qapi/main.py | 2 ++
scripts/qapi/schema.py | 31 ++++++++++++++++++++-
scripts/qapi/types.py | 23 ++++++++-------
scripts/qapi/visit.py | 21 ++++++--------
tests/meson.build | 2 ++
tests/qapi-schema/features-too-many.err | 2 ++
tests/qapi-schema/features-too-many.json | 13 +++++++++
tests/qapi-schema/features-too-many.out | 0
tests/qapi-schema/meson.build | 1 +
27 files changed, 163 insertions(+), 67 deletions(-)
create mode 100644 scripts/qapi/features.py
create mode 100644 tests/qapi-schema/features-too-many.err
create mode 100644 tests/qapi-schema/features-too-many.json
create mode 100644 tests/qapi-schema/features-too-many.out
--
2.48.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PULL 1/6] qapi: fix colon in Since tag section
2025-02-10 8:39 [PULL 0/6] QAPI patches patches for 2025-02-10 Markus Armbruster
@ 2025-02-10 8:39 ` Markus Armbruster
2025-02-10 8:39 ` [PULL 2/6] qapi/ui: Fix documentation of upper bound value in InputMoveEvent Markus Armbruster
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2025-02-10 8:39 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, Victor Toso
From: Victor Toso <victortoso@redhat.com>
As described in docs/devel/qapi-code-gen.rst line 998,
there should be no space between "Since" and ":".
Signed-off-by: Victor Toso <victortoso@redhat.com>
Message-ID: <20241217091504.16416-1-victortoso@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
qapi/cxl.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/qapi/cxl.json b/qapi/cxl.json
index 9f65589bce..dd947d3bbc 100644
--- a/qapi/cxl.json
+++ b/qapi/cxl.json
@@ -460,7 +460,7 @@
#
# @unstable: For now this command is subject to change.
#
-# Since : 9.1
+# Since: 9.1
##
{ 'command': 'cxl-add-dynamic-capacity',
'data': { 'path': 'str',
@@ -539,7 +539,7 @@
#
# @unstable: For now this command is subject to change.
#
-# Since : 9.1
+# Since: 9.1
##
{ 'command': 'cxl-release-dynamic-capacity',
'data': { 'path': 'str',
--
2.48.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PULL 2/6] qapi/ui: Fix documentation of upper bound value in InputMoveEvent
2025-02-10 8:39 [PULL 0/6] QAPI patches patches for 2025-02-10 Markus Armbruster
2025-02-10 8:39 ` [PULL 1/6] qapi: fix colon in Since tag section Markus Armbruster
@ 2025-02-10 8:39 ` Markus Armbruster
2025-02-10 8:39 ` [PULL 3/6] qapi: cope with feature names containing a '-' Markus Armbruster
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2025-02-10 8:39 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, Zhang Boyang
From: Zhang Boyang <zhangboyang.id@gmail.com>
The upper bound of pointer position in InputMoveEvent should be 0x7fff,
according to INPUT_EVENT_ABS_MAX.
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Message-ID: <20250116104433.12114-1-zhangboyang.id@gmail.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
[Phrasing tweak squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
qapi/ui.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qapi/ui.json b/qapi/ui.json
index 460a26b981..c536d4e524 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1133,7 +1133,7 @@
# @axis: Which axis is referenced by @value.
#
# @value: Pointer position. For absolute coordinates the valid range
-# is 0 -> 0x7ffff
+# is 0 to 0x7fff.
#
# Since: 2.0
##
--
2.48.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PULL 3/6] qapi: cope with feature names containing a '-'
2025-02-10 8:39 [PULL 0/6] QAPI patches patches for 2025-02-10 Markus Armbruster
2025-02-10 8:39 ` [PULL 1/6] qapi: fix colon in Since tag section Markus Armbruster
2025-02-10 8:39 ` [PULL 2/6] qapi/ui: Fix documentation of upper bound value in InputMoveEvent Markus Armbruster
@ 2025-02-10 8:39 ` Markus Armbruster
2025-02-10 8:39 ` [PULL 4/6] qapi: change 'unsigned special_features' to 'uint64_t features' Markus Armbruster
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2025-02-10 8:39 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, Daniel P. Berrangé
From: Daniel P. Berrangé <berrange@redhat.com>
When we shortly expose all feature names to code, it will be valid to
include a '-', which must be translated to a '_' for the enum constants.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20250205123550.2754387-2-berrange@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/gen.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py
index 6a8abe0041..c53ca72950 100644
--- a/scripts/qapi/gen.py
+++ b/scripts/qapi/gen.py
@@ -24,6 +24,7 @@
)
from .common import (
+ c_enum_const,
c_fname,
c_name,
guardend,
@@ -41,7 +42,7 @@
def gen_special_features(features: Sequence[QAPISchemaFeature]) -> str:
- special_features = [f"1u << QAPI_{feat.name.upper()}"
+ special_features = [f"1u << {c_enum_const('qapi', feat.name)}"
for feat in features if feat.is_special()]
return ' | '.join(special_features) or '0'
--
2.48.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PULL 4/6] qapi: change 'unsigned special_features' to 'uint64_t features'
2025-02-10 8:39 [PULL 0/6] QAPI patches patches for 2025-02-10 Markus Armbruster
` (2 preceding siblings ...)
2025-02-10 8:39 ` [PULL 3/6] qapi: cope with feature names containing a '-' Markus Armbruster
@ 2025-02-10 8:39 ` Markus Armbruster
2025-02-10 8:39 ` [PULL 5/6] qapi: rename 'special_features' to 'features' Markus Armbruster
2025-02-10 8:39 ` [PULL 6/6] qapi: expose all schema features to code Markus Armbruster
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2025-02-10 8:39 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, Daniel P. Berrangé, Philippe Mathieu-Daudé
From: Daniel P. Berrangé <berrange@redhat.com>
The "special_features" field / parameter holds the subset of schema
features that are for internal code use. Specifically 'DEPRECATED'
and 'UNSTABLE'.
This special casing of internal features is going to be removed, so
prepare for that by renaming to 'features'. Using a fixed size type
is also best practice for bit fields.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20250205123550.2754387-3-berrange@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
include/qapi/compat-policy.h | 2 +-
include/qapi/qmp/dispatch.h | 4 ++--
include/qapi/util.h | 2 +-
include/qapi/visitor-impl.h | 4 ++--
include/qapi/visitor.h | 12 ++++++------
qapi/qapi-forward-visitor.c | 8 ++++----
qapi/qapi-util.c | 6 +++---
qapi/qapi-visit-core.c | 12 ++++++------
qapi/qmp-dispatch.c | 2 +-
qapi/qmp-registry.c | 4 ++--
qapi/qobject-input-visitor.c | 4 ++--
qapi/qobject-output-visitor.c | 6 +++---
scripts/qapi/types.py | 2 +-
13 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/include/qapi/compat-policy.h b/include/qapi/compat-policy.h
index 8b7b25c0b5..ea65e10744 100644
--- a/include/qapi/compat-policy.h
+++ b/include/qapi/compat-policy.h
@@ -18,7 +18,7 @@
extern CompatPolicy compat_policy;
-bool compat_policy_input_ok(unsigned special_features,
+bool compat_policy_input_ok(uint64_t features,
const CompatPolicy *policy,
ErrorClass error_class,
const char *kind, const char *name,
diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index f2e956813a..e0ee1ad3ac 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -33,7 +33,7 @@ typedef struct QmpCommand
/* Runs in coroutine context if QCO_COROUTINE is set */
QmpCommandFunc *fn;
QmpCommandOptions options;
- unsigned special_features;
+ uint64_t features;
QTAILQ_ENTRY(QmpCommand) node;
bool enabled;
const char *disable_reason;
@@ -43,7 +43,7 @@ typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList;
void qmp_register_command(QmpCommandList *cmds, const char *name,
QmpCommandFunc *fn, QmpCommandOptions options,
- unsigned special_features);
+ uint64_t features);
const QmpCommand *qmp_find_command(const QmpCommandList *cmds,
const char *name);
void qmp_disable_command(QmpCommandList *cmds, const char *name,
diff --git a/include/qapi/util.h b/include/qapi/util.h
index b8254247b8..29bc4eb865 100644
--- a/include/qapi/util.h
+++ b/include/qapi/util.h
@@ -18,7 +18,7 @@ typedef enum {
typedef struct QEnumLookup {
const char *const *array;
- const unsigned char *const special_features;
+ const uint64_t *const features;
const int size;
} QEnumLookup;
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 2badec5ba4..7beb0dbfa5 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -115,11 +115,11 @@ struct Visitor
/* Optional */
bool (*policy_reject)(Visitor *v, const char *name,
- unsigned special_features, Error **errp);
+ uint64_t features, Error **errp);
/* Optional */
bool (*policy_skip)(Visitor *v, const char *name,
- unsigned special_features);
+ uint64_t features);
/* Must be set */
VisitorType type;
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 27b85d4700..f6a9b0743f 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -463,29 +463,29 @@ bool visit_optional(Visitor *v, const char *name, bool *present);
/*
* Should we reject member @name due to policy?
*
- * @special_features is the member's special features encoded as a
- * bitset of QapiSpecialFeature.
+ * @features is the member's special features encoded as a
+ * bitset of QapiFeature.
*
* @name must not be NULL. This function is only useful between
* visit_start_struct() and visit_end_struct(), since only objects
* have deprecated members.
*/
bool visit_policy_reject(Visitor *v, const char *name,
- unsigned special_features, Error **errp);
+ uint64_t features, Error **errp);
/*
*
* Should we skip member @name due to policy?
*
- * @special_features is the member's special features encoded as a
- * bitset of QapiSpecialFeature.
+ * @features is the member's special features encoded as a
+ * bitset of QapiFeature.
*
* @name must not be NULL. This function is only useful between
* visit_start_struct() and visit_end_struct(), since only objects
* have deprecated members.
*/
bool visit_policy_skip(Visitor *v, const char *name,
- unsigned special_features);
+ uint64_t features);
/*
* Set policy for handling deprecated management interfaces.
diff --git a/qapi/qapi-forward-visitor.c b/qapi/qapi-forward-visitor.c
index e36d9bc9ba..6e9a784a9f 100644
--- a/qapi/qapi-forward-visitor.c
+++ b/qapi/qapi-forward-visitor.c
@@ -246,7 +246,7 @@ static void forward_field_optional(Visitor *v, const char *name, bool *present)
}
static bool forward_field_policy_reject(Visitor *v, const char *name,
- unsigned special_features,
+ uint64_t features,
Error **errp)
{
ForwardFieldVisitor *ffv = to_ffv(v);
@@ -254,18 +254,18 @@ static bool forward_field_policy_reject(Visitor *v, const char *name,
if (!forward_field_translate_name(ffv, &name, errp)) {
return true;
}
- return visit_policy_reject(ffv->target, name, special_features, errp);
+ return visit_policy_reject(ffv->target, name, features, errp);
}
static bool forward_field_policy_skip(Visitor *v, const char *name,
- unsigned special_features)
+ uint64_t features)
{
ForwardFieldVisitor *ffv = to_ffv(v);
if (!forward_field_translate_name(ffv, &name, NULL)) {
return true;
}
- return visit_policy_skip(ffv->target, name, special_features);
+ return visit_policy_skip(ffv->target, name, features);
}
static void forward_field_complete(Visitor *v, void *opaque)
diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
index 65a7d18437..3d849fe034 100644
--- a/qapi/qapi-util.c
+++ b/qapi/qapi-util.c
@@ -37,19 +37,19 @@ static bool compat_policy_input_ok1(const char *adjective,
}
}
-bool compat_policy_input_ok(unsigned special_features,
+bool compat_policy_input_ok(uint64_t features,
const CompatPolicy *policy,
ErrorClass error_class,
const char *kind, const char *name,
Error **errp)
{
- if ((special_features & 1u << QAPI_DEPRECATED)
+ if ((features & 1u << QAPI_DEPRECATED)
&& !compat_policy_input_ok1("Deprecated",
policy->deprecated_input,
error_class, kind, name, errp)) {
return false;
}
- if ((special_features & (1u << QAPI_UNSTABLE))
+ if ((features & (1u << QAPI_UNSTABLE))
&& !compat_policy_input_ok1("Unstable",
policy->unstable_input,
error_class, kind, name, errp)) {
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 6c13510a2b..706c61e026 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -141,21 +141,21 @@ bool visit_optional(Visitor *v, const char *name, bool *present)
}
bool visit_policy_reject(Visitor *v, const char *name,
- unsigned special_features, Error **errp)
+ uint64_t features, Error **errp)
{
trace_visit_policy_reject(v, name);
if (v->policy_reject) {
- return v->policy_reject(v, name, special_features, errp);
+ return v->policy_reject(v, name, features, errp);
}
return false;
}
bool visit_policy_skip(Visitor *v, const char *name,
- unsigned special_features)
+ uint64_t features)
{
trace_visit_policy_skip(v, name);
if (v->policy_skip) {
- return v->policy_skip(v, name, special_features);
+ return v->policy_skip(v, name, features);
}
return false;
}
@@ -409,8 +409,8 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
return false;
}
- if (lookup->special_features
- && !compat_policy_input_ok(lookup->special_features[value],
+ if (lookup->features
+ && !compat_policy_input_ok(lookup->features[value],
&v->compat_policy,
ERROR_CLASS_GENERIC_ERROR,
"value", enum_str, errp)) {
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 176b549473..d411eebf4e 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -173,7 +173,7 @@ QDict *coroutine_mixed_fn qmp_dispatch(const QmpCommandList *cmds, QObject *requ
"The command %s has not been found", command);
goto out;
}
- if (!compat_policy_input_ok(cmd->special_features, &compat_policy,
+ if (!compat_policy_input_ok(cmd->features, &compat_policy,
ERROR_CLASS_COMMAND_NOT_FOUND,
"command", command, &err)) {
goto out;
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 485bc5e6fc..bfcabec526 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -17,7 +17,7 @@
void qmp_register_command(QmpCommandList *cmds, const char *name,
QmpCommandFunc *fn, QmpCommandOptions options,
- unsigned special_features)
+ uint64_t features)
{
QmpCommand *cmd = g_malloc0(sizeof(*cmd));
@@ -28,7 +28,7 @@ void qmp_register_command(QmpCommandList *cmds, const char *name,
cmd->fn = fn;
cmd->enabled = true;
cmd->options = options;
- cmd->special_features = special_features;
+ cmd->features = features;
QTAILQ_INSERT_TAIL(cmds, cmd, node);
}
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index f110a804b2..ff9c726de3 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -664,10 +664,10 @@ static void qobject_input_optional(Visitor *v, const char *name, bool *present)
}
static bool qobject_input_policy_reject(Visitor *v, const char *name,
- unsigned special_features,
+ uint64_t features,
Error **errp)
{
- return !compat_policy_input_ok(special_features, &v->compat_policy,
+ return !compat_policy_input_ok(features, &v->compat_policy,
ERROR_CLASS_GENERIC_ERROR,
"parameter", name, errp);
}
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
index 74770edd73..8902287caa 100644
--- a/qapi/qobject-output-visitor.c
+++ b/qapi/qobject-output-visitor.c
@@ -210,13 +210,13 @@ static bool qobject_output_type_null(Visitor *v, const char *name,
}
static bool qobject_output_policy_skip(Visitor *v, const char *name,
- unsigned special_features)
+ uint64_t features)
{
CompatPolicy *pol = &v->compat_policy;
- return ((special_features & 1u << QAPI_DEPRECATED)
+ return ((features & 1u << QAPI_DEPRECATED)
&& pol->deprecated_output == COMPAT_POLICY_OUTPUT_HIDE)
- || ((special_features & 1u << QAPI_UNSTABLE)
+ || ((features & 1u << QAPI_UNSTABLE)
&& pol->unstable_output == COMPAT_POLICY_OUTPUT_HIDE);
}
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 0dd0b00ada..7bc3f8241f 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -71,7 +71,7 @@ def gen_enum_lookup(name: str,
if feats:
ret += mcgen('''
},
- .special_features = (const unsigned char[%(max_index)s]) {
+ .features = (const uint64_t[%(max_index)s]) {
''',
max_index=max_index)
ret += feats
--
2.48.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PULL 5/6] qapi: rename 'special_features' to 'features'
2025-02-10 8:39 [PULL 0/6] QAPI patches patches for 2025-02-10 Markus Armbruster
` (3 preceding siblings ...)
2025-02-10 8:39 ` [PULL 4/6] qapi: change 'unsigned special_features' to 'uint64_t features' Markus Armbruster
@ 2025-02-10 8:39 ` Markus Armbruster
2025-02-10 8:39 ` [PULL 6/6] qapi: expose all schema features to code Markus Armbruster
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2025-02-10 8:39 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, Daniel P. Berrangé
From: Daniel P. Berrangé <berrange@redhat.com>
This updates the QAPI code generation to refer to 'features' instead
of 'special_features', in preparation for generalizing their exposure.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20250205123550.2754387-4-berrange@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Imports tidied up with isort]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
scripts/qapi/commands.py | 4 ++--
scripts/qapi/gen.py | 8 ++++----
scripts/qapi/types.py | 14 +++++---------
scripts/qapi/visit.py | 18 +++++++-----------
4 files changed, 18 insertions(+), 26 deletions(-)
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 79951a841f..d629d2d97e 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -25,7 +25,7 @@
QAPIGenC,
QAPISchemaModularCVisitor,
build_params,
- gen_special_features,
+ gen_features,
ifcontext,
)
from .schema import (
@@ -298,7 +298,7 @@ def gen_register_command(name: str,
''',
name=name, c_name=c_name(name),
opts=' | '.join(options) or 0,
- feats=gen_special_features(features))
+ feats=gen_features(features))
return ret
diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py
index c53ca72950..b51f8d955e 100644
--- a/scripts/qapi/gen.py
+++ b/scripts/qapi/gen.py
@@ -41,10 +41,10 @@
from .source import QAPISourceInfo
-def gen_special_features(features: Sequence[QAPISchemaFeature]) -> str:
- special_features = [f"1u << {c_enum_const('qapi', feat.name)}"
- for feat in features if feat.is_special()]
- return ' | '.join(special_features) or '0'
+def gen_features(features: Sequence[QAPISchemaFeature]) -> str:
+ featenum = [f"1u << {c_enum_const('qapi', feat.name)}"
+ for feat in features if feat.is_special()]
+ return ' | '.join(featenum) or '0'
class QAPIGen:
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 7bc3f8241f..e4a1bb9f85 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -16,11 +16,7 @@
from typing import List, Optional
from .common import c_enum_const, c_name, mcgen
-from .gen import (
- QAPISchemaModularCVisitor,
- gen_special_features,
- ifcontext,
-)
+from .gen import QAPISchemaModularCVisitor, gen_features, ifcontext
from .schema import (
QAPISchema,
QAPISchemaAlternatives,
@@ -61,12 +57,12 @@ def gen_enum_lookup(name: str,
index=index, name=memb.name)
ret += memb.ifcond.gen_endif()
- special_features = gen_special_features(memb.features)
- if special_features != '0':
+ features = gen_features(memb.features)
+ if features != '0':
feats += mcgen('''
- [%(index)s] = %(special_features)s,
+ [%(index)s] = %(features)s,
''',
- index=index, special_features=special_features)
+ index=index, features=features)
if feats:
ret += mcgen('''
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 12f92e429f..928273b9bb 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -21,11 +21,7 @@
indent,
mcgen,
)
-from .gen import (
- QAPISchemaModularCVisitor,
- gen_special_features,
- ifcontext,
-)
+from .gen import QAPISchemaModularCVisitor, gen_features, ifcontext
from .schema import (
QAPISchema,
QAPISchemaAlternatives,
@@ -103,15 +99,15 @@ def gen_visit_object_members(name: str,
''',
name=memb.name, has=has)
indent.increase()
- special_features = gen_special_features(memb.features)
- if special_features != '0':
+ features = gen_features(memb.features)
+ if features != '0':
ret += mcgen('''
- if (visit_policy_reject(v, "%(name)s", %(special_features)s, errp)) {
+ if (visit_policy_reject(v, "%(name)s", %(features)s, errp)) {
return false;
}
- if (!visit_policy_skip(v, "%(name)s", %(special_features)s)) {
+ if (!visit_policy_skip(v, "%(name)s", %(features)s)) {
''',
- name=memb.name, special_features=special_features)
+ name=memb.name, features=features)
indent.increase()
ret += mcgen('''
if (!visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, errp)) {
@@ -120,7 +116,7 @@ def gen_visit_object_members(name: str,
''',
c_type=memb.type.c_name(), name=memb.name,
c_name=c_name(memb.name))
- if special_features != '0':
+ if features != '0':
indent.decrease()
ret += mcgen('''
}
--
2.48.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PULL 6/6] qapi: expose all schema features to code
2025-02-10 8:39 [PULL 0/6] QAPI patches patches for 2025-02-10 Markus Armbruster
` (4 preceding siblings ...)
2025-02-10 8:39 ` [PULL 5/6] qapi: rename 'special_features' to 'features' Markus Armbruster
@ 2025-02-10 8:39 ` Markus Armbruster
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2025-02-10 8:39 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, Daniel P. Berrangé
From: Daniel P. Berrangé <berrange@redhat.com>
This replaces use of the constants from the QapiSpecialFeatures
enum, with constants from the auto-generate QapiFeatures enum
in qapi-features.h
The 'deprecated' and 'unstable' features still have a little bit of
special handling, being force defined to be the 1st + 2nd features
in the enum, regardless of whether they're used in the schema. This
retains compatibility with common code that references the features
via the QapiSpecialFeatures constants.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20250205123550.2754387-5-berrange@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Imports tidied up with isort]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
meson.build | 1 +
scripts/qapi/commands.py | 1 +
scripts/qapi/features.py | 48 ++++++++++++++++++++++++
scripts/qapi/gen.py | 6 +--
scripts/qapi/main.py | 2 +
scripts/qapi/schema.py | 31 ++++++++++++++-
scripts/qapi/types.py | 7 +++-
scripts/qapi/visit.py | 3 +-
tests/meson.build | 2 +
tests/qapi-schema/features-too-many.err | 2 +
tests/qapi-schema/features-too-many.json | 13 +++++++
tests/qapi-schema/features-too-many.out | 0
tests/qapi-schema/meson.build | 1 +
13 files changed, 110 insertions(+), 7 deletions(-)
create mode 100644 scripts/qapi/features.py
create mode 100644 tests/qapi-schema/features-too-many.err
create mode 100644 tests/qapi-schema/features-too-many.json
create mode 100644 tests/qapi-schema/features-too-many.out
diff --git a/meson.build b/meson.build
index 131b2225ab..ee59d647e4 100644
--- a/meson.build
+++ b/meson.build
@@ -3444,6 +3444,7 @@ qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
meson.current_source_dir() / 'scripts/qapi/schema.py',
meson.current_source_dir() / 'scripts/qapi/source.py',
meson.current_source_dir() / 'scripts/qapi/types.py',
+ meson.current_source_dir() / 'scripts/qapi/features.py',
meson.current_source_dir() / 'scripts/qapi/visit.py',
meson.current_source_dir() / 'scripts/qapi-gen.py'
]
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index d629d2d97e..bf88bfc442 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -355,6 +355,7 @@ def visit_begin(self, schema: QAPISchema) -> None:
#include "qemu/osdep.h"
#include "%(prefix)sqapi-commands.h"
#include "%(prefix)sqapi-init-commands.h"
+#include "%(prefix)sqapi-features.h"
void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
{
diff --git a/scripts/qapi/features.py b/scripts/qapi/features.py
new file mode 100644
index 0000000000..57563207a8
--- /dev/null
+++ b/scripts/qapi/features.py
@@ -0,0 +1,48 @@
+"""
+QAPI features generator
+
+Copyright 2024 Red Hat
+
+This work is licensed under the terms of the GNU GPL, version 2.
+# See the COPYING file in the top-level directory.
+"""
+
+from typing import ValuesView
+
+from .common import c_enum_const, c_name
+from .gen import QAPISchemaMonolithicCVisitor
+from .schema import QAPISchema, QAPISchemaFeature
+
+
+class QAPISchemaGenFeatureVisitor(QAPISchemaMonolithicCVisitor):
+
+ def __init__(self, prefix: str):
+ super().__init__(
+ prefix, 'qapi-features',
+ ' * Schema-defined QAPI features',
+ __doc__)
+
+ self.features: ValuesView[QAPISchemaFeature]
+
+ def visit_begin(self, schema: QAPISchema) -> None:
+ self.features = schema.features()
+ self._genh.add("#include \"qapi/util.h\"\n\n")
+
+ def visit_end(self) -> None:
+ self._genh.add("typedef enum {\n")
+ for f in self.features:
+ self._genh.add(f" {c_enum_const('qapi_feature', f.name)}")
+ if f.name in QAPISchemaFeature.SPECIAL_NAMES:
+ self._genh.add(f" = {c_enum_const('qapi', f.name)},\n")
+ else:
+ self._genh.add(",\n")
+
+ self._genh.add("} " + c_name('QapiFeature') + ";\n")
+
+
+def gen_features(schema: QAPISchema,
+ output_dir: str,
+ prefix: str) -> None:
+ vis = QAPISchemaGenFeatureVisitor(prefix)
+ schema.visit(vis)
+ vis.write(output_dir)
diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py
index b51f8d955e..d3c56d45c8 100644
--- a/scripts/qapi/gen.py
+++ b/scripts/qapi/gen.py
@@ -42,9 +42,9 @@
def gen_features(features: Sequence[QAPISchemaFeature]) -> str:
- featenum = [f"1u << {c_enum_const('qapi', feat.name)}"
- for feat in features if feat.is_special()]
- return ' | '.join(featenum) or '0'
+ feats = [f"1u << {c_enum_const('qapi_feature', feat.name)}"
+ for feat in features]
+ return ' | '.join(feats) or '0'
class QAPIGen:
diff --git a/scripts/qapi/main.py b/scripts/qapi/main.py
index 316736b6a2..324081b9fc 100644
--- a/scripts/qapi/main.py
+++ b/scripts/qapi/main.py
@@ -15,6 +15,7 @@
from .common import must_match
from .error import QAPIError
from .events import gen_events
+from .features import gen_features
from .introspect import gen_introspect
from .schema import QAPISchema
from .types import gen_types
@@ -49,6 +50,7 @@ def generate(schema_file: str,
schema = QAPISchema(schema_file)
gen_types(schema, output_dir, prefix, builtins)
+ gen_features(schema, output_dir, prefix)
gen_visit(schema, output_dir, prefix, builtins)
gen_commands(schema, output_dir, prefix, gen_tracing)
gen_events(schema, output_dir, prefix)
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index e97c978d38..7f70969c09 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -29,6 +29,7 @@
List,
Optional,
Union,
+ ValuesView,
cast,
)
@@ -933,8 +934,11 @@ def connect_doc(self, doc: Optional[QAPIDoc]) -> None:
class QAPISchemaFeature(QAPISchemaMember):
role = 'feature'
+ # Features which are standardized across all schemas
+ SPECIAL_NAMES = ['deprecated', 'unstable']
+
def is_special(self) -> bool:
- return self.name in ('deprecated', 'unstable')
+ return self.name in QAPISchemaFeature.SPECIAL_NAMES
class QAPISchemaObjectTypeMember(QAPISchemaMember):
@@ -1138,6 +1142,16 @@ def __init__(self, fname: str):
self._entity_list: List[QAPISchemaEntity] = []
self._entity_dict: Dict[str, QAPISchemaDefinition] = {}
self._module_dict: Dict[str, QAPISchemaModule] = OrderedDict()
+ # NB, values in the dict will identify the first encountered
+ # usage of a named feature only
+ self._feature_dict: Dict[str, QAPISchemaFeature] = OrderedDict()
+
+ # All schemas get the names defined in the QapiSpecialFeature enum.
+ # Rely on dict iteration order matching insertion order so that
+ # the special names are emitted first when generating code.
+ for f in QAPISchemaFeature.SPECIAL_NAMES:
+ self._feature_dict[f] = QAPISchemaFeature(f, None)
+
self._schema_dir = os.path.dirname(fname)
self._make_module(QAPISchemaModule.BUILTIN_MODULE_NAME)
self._make_module(fname)
@@ -1147,6 +1161,9 @@ def __init__(self, fname: str):
self._def_exprs(exprs)
self.check()
+ def features(self) -> ValuesView[QAPISchemaFeature]:
+ return self._feature_dict.values()
+
def _def_entity(self, ent: QAPISchemaEntity) -> None:
self._entity_list.append(ent)
@@ -1258,6 +1275,12 @@ def _make_features(
) -> List[QAPISchemaFeature]:
if features is None:
return []
+
+ for f in features:
+ feat = QAPISchemaFeature(f['name'], info)
+ if feat.name not in self._feature_dict:
+ self._feature_dict[feat.name] = feat
+
return [QAPISchemaFeature(f['name'], info,
QAPISchemaIfCond(f.get('if')))
for f in features]
@@ -1485,6 +1508,12 @@ def check(self) -> None:
for doc in self.docs:
doc.check()
+ features = list(self._feature_dict.values())
+ if len(features) > 64:
+ raise QAPISemError(
+ features[64].info,
+ "Maximum of 64 schema features is permitted")
+
def visit(self, visitor: QAPISchemaVisitor) -> None:
visitor.visit_begin(self)
for mod in self._module_dict.values():
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index e4a1bb9f85..2bf7533828 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -304,11 +304,14 @@ def _begin_user_module(self, name: str) -> None:
#include "qapi/dealloc-visitor.h"
#include "%(types)s.h"
#include "%(visit)s.h"
+#include "%(prefix)sqapi-features.h"
''',
- types=types, visit=visit))
+ types=types, visit=visit,
+ prefix=self._prefix))
self._genh.preamble_add(mcgen('''
#include "qapi/qapi-builtin-types.h"
-'''))
+''',
+ prefix=self._prefix))
def visit_begin(self, schema: QAPISchema) -> None:
# gen_object() is recursive, ensure it doesn't visit the empty type
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 928273b9bb..36e240967b 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -356,8 +356,9 @@ def _begin_user_module(self, name: str) -> None:
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "%(visit)s.h"
+#include "%(prefix)sqapi-features.h"
''',
- visit=visit))
+ visit=visit, prefix=self._prefix))
self._genh.preamble_add(mcgen('''
#include "qapi/qapi-builtin-visit.h"
#include "%(types)s.h"
diff --git a/tests/meson.build b/tests/meson.build
index f96c1be574..c59619220f 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -16,6 +16,8 @@ test_qapi_outputs = [
'test-qapi-events-sub-sub-module.h',
'test-qapi-events.c',
'test-qapi-events.h',
+ 'test-qapi-features.c',
+ 'test-qapi-features.h',
'test-qapi-init-commands.c',
'test-qapi-init-commands.h',
'test-qapi-introspect.c',
diff --git a/tests/qapi-schema/features-too-many.err b/tests/qapi-schema/features-too-many.err
new file mode 100644
index 0000000000..bbbd6e5202
--- /dev/null
+++ b/tests/qapi-schema/features-too-many.err
@@ -0,0 +1,2 @@
+features-too-many.json: In command 'go-fish':
+features-too-many.json:2: Maximum of 64 schema features is permitted
diff --git a/tests/qapi-schema/features-too-many.json b/tests/qapi-schema/features-too-many.json
new file mode 100644
index 0000000000..aab0a0b5f1
--- /dev/null
+++ b/tests/qapi-schema/features-too-many.json
@@ -0,0 +1,13 @@
+# Max 64 features, with 2 specials, so 63rd custom is invalid
+{ 'command': 'go-fish',
+ 'features': [
+ 'f00', 'f01', 'f02', 'f03', 'f04', 'f05', 'f06', 'f07',
+ 'f08', 'f09', 'f0a', 'f0b', 'f0c', 'f0d', 'f0e', 'f0f',
+ 'f10', 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17',
+ 'f18', 'f19', 'f1a', 'f1b', 'f1c', 'f1d', 'f1e', 'f1f',
+ 'f20', 'f21', 'f22', 'f23', 'f24', 'f25', 'f26', 'f27',
+ 'f28', 'f29', 'f2a', 'f2b', 'f2c', 'f2d', 'f2e', 'f2f',
+ 'f30', 'f31', 'f32', 'f33', 'f34', 'f35', 'f36', 'f37',
+ 'f38', 'f39', 'f3a', 'f3b', 'f3c', 'f3d', 'f3e'
+ ]
+}
diff --git a/tests/qapi-schema/features-too-many.out b/tests/qapi-schema/features-too-many.out
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build
index 0f479d9317..9577178b6f 100644
--- a/tests/qapi-schema/meson.build
+++ b/tests/qapi-schema/meson.build
@@ -105,6 +105,7 @@ schemas = [
'event-case.json',
'event-member-invalid-dict.json',
'event-nest-struct.json',
+ 'features-too-many.json',
'features-bad-type.json',
'features-deprecated-type.json',
'features-duplicate-name.json',
--
2.48.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-02-10 8:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-10 8:39 [PULL 0/6] QAPI patches patches for 2025-02-10 Markus Armbruster
2025-02-10 8:39 ` [PULL 1/6] qapi: fix colon in Since tag section Markus Armbruster
2025-02-10 8:39 ` [PULL 2/6] qapi/ui: Fix documentation of upper bound value in InputMoveEvent Markus Armbruster
2025-02-10 8:39 ` [PULL 3/6] qapi: cope with feature names containing a '-' Markus Armbruster
2025-02-10 8:39 ` [PULL 4/6] qapi: change 'unsigned special_features' to 'uint64_t features' Markus Armbruster
2025-02-10 8:39 ` [PULL 5/6] qapi: rename 'special_features' to 'features' Markus Armbruster
2025-02-10 8:39 ` [PULL 6/6] qapi: expose all schema features to code Markus Armbruster
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).