From 35a159fb282da34a24d7e6ded25ba82bf3dd3c9f Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Fri, 3 Mar 2023 22:02:33 +0100 Subject: [PATCH 1/3] scanner: allow element-type and enum on array args This allows an element type and an enum to optionally be specified on array args in protocol xml. If an enum is specified the element type is required and is subject to the same restrictions as a the type of a non-array argument with an enum specified. Signed-off-by: Isaac Freund --- protocol/wayland.dtd | 1 + src/scanner.c | 50 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/protocol/wayland.dtd b/protocol/wayland.dtd index ee062eea..6f888168 100644 --- a/protocol/wayland.dtd +++ b/protocol/wayland.dtd @@ -28,5 +28,6 @@ + diff --git a/src/scanner.c b/src/scanner.c index c512d231..45297e25 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -209,6 +209,12 @@ enum arg_type { FD }; +enum element_type { + ELEMENT_TYPE_NONE, + ELEMENT_TYPE_INT, + ELEMENT_TYPE_UNSIGNED, +}; + struct arg { char *name; enum arg_type type; @@ -217,6 +223,7 @@ struct arg { struct wl_list link; char *summary; char *enumeration_name; + enum element_type element_type; }; struct enumeration { @@ -716,6 +723,7 @@ start_element(void *data, const char *element_name, const char **atts) const char *allow_null = NULL; const char *enumeration_name = NULL; const char *bitfield = NULL; + const char *element_type = NULL; int i, version = 0; ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); @@ -743,6 +751,8 @@ start_element(void *data, const char *element_name, const char **atts) enumeration_name = atts[i + 1]; if (strcmp(atts[i], "bitfield") == 0) bitfield = atts[i + 1]; + if (strcmp(atts[i], "element-type") == 0) + element_type = atts[i + 1]; } ctx->character_data_length = 0; @@ -841,6 +851,20 @@ start_element(void *data, const char *element_name, const char **atts) else arg->enumeration_name = xstrdup(enumeration_name); + if (element_type == NULL) { + arg->element_type = ELEMENT_TYPE_NONE; + } else { + if (strcmp(element_type, "int") == 0) { + arg->element_type = ELEMENT_TYPE_INT; + } else if (strcmp(element_type, "uint") == 0) { + arg->element_type = ELEMENT_TYPE_UNSIGNED; + } else { + fail(&ctx->loc, + "invalid element type '%s', must be int or uint", + element_type); + } + } + if (summary) arg->summary = xstrdup(summary); @@ -953,15 +977,34 @@ verify_arguments(struct parse_context *ctx, struct arg *a; wl_list_for_each(a, &m->arg_list, link) { struct enumeration *e; + enum arg_type t; + + if (a->element_type != ELEMENT_TYPE_NONE && a->type != ARRAY) { + fail(&ctx->loc, + "only args of type array may specify an element-type"); + } + + switch (a->element_type) { + case ELEMENT_TYPE_NONE: + t = a->type; + break; + case ELEMENT_TYPE_INT: + t = INT; + break; + case ELEMENT_TYPE_UNSIGNED: + t = UNSIGNED; + break; + default: + abort(); + } if (!a->enumeration_name) continue; - e = find_enumeration(ctx->protocol, interface, a->enumeration_name); - switch (a->type) { + switch (t) { case INT: if (e && e->bitfield) fail(&ctx->loc, @@ -969,6 +1012,9 @@ verify_arguments(struct parse_context *ctx, break; case UNSIGNED: break; + case ARRAY: + fail(&ctx->loc, + "array arg must specify element-type if enum is specified"); default: fail(&ctx->loc, "enumeration-style argument has wrong type"); From f78acbeaddf7bb640569ba49eff4be38bad8d2a3 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Thu, 9 Mar 2023 22:22:58 +0100 Subject: [PATCH 2/3] scanner: allow element-bits on array args This attribute is optional but required if the element-type attribute is specified. This attribute specifies the size of the array elements in bits to allow for better WAYLAND_DEBUG logging and scanner code generation. Signed-off-by: Isaac Freund --- protocol/wayland.dtd | 1 + src/scanner.c | 124 ++++++++++++++++++++++++++++--------------- 2 files changed, 82 insertions(+), 43 deletions(-) diff --git a/protocol/wayland.dtd b/protocol/wayland.dtd index 6f888168..6a9c55b5 100644 --- a/protocol/wayland.dtd +++ b/protocol/wayland.dtd @@ -29,5 +29,6 @@ + diff --git a/src/scanner.c b/src/scanner.c index 45297e25..a9d8e695 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -224,6 +224,7 @@ struct arg { char *summary; char *enumeration_name; enum element_type element_type; + int element_bits; }; struct enumeration { @@ -725,6 +726,7 @@ start_element(void *data, const char *element_name, const char **atts) const char *bitfield = NULL; const char *element_type = NULL; int i, version = 0; + int element_bits = 0; ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); for (i = 0; atts[i]; i += 2) { @@ -753,6 +755,21 @@ start_element(void *data, const char *element_name, const char **atts) bitfield = atts[i + 1]; if (strcmp(atts[i], "element-type") == 0) element_type = atts[i + 1]; + if (strcmp(atts[i], "element-bits") == 0) { + element_bits = strtouint(atts[i + 1]); + switch (element_bits) { + case 8: + case 16: + case 32: + /* Note: the wire protocol only guarantees 4 byte alignment + * of array data. Therefore we cannot allow 64 bit elements + * as they require 8 byte alignment on common targets. */ + break; + default: + fail(&ctx->loc, + "invalid element-bits value (%d)", atts[i + 1]); + } + } } ctx->character_data_length = 0; @@ -864,6 +881,7 @@ start_element(void *data, const char *element_name, const char **atts) element_type); } } + arg->element_bits = element_bits; if (summary) arg->summary = xstrdup(summary); @@ -966,6 +984,68 @@ find_enumeration(struct protocol *protocol, return NULL; } +static void +verify_argument_attributes(struct parse_context *ctx, + struct interface *interface, + struct arg *a) +{ + struct enumeration *e; + enum arg_type t; + + if (a->type == ARRAY) { + if ((a->element_type != ELEMENT_TYPE_NONE) != (a->element_bits != 0)) { + fail(&ctx->loc, + "if one of element-type or element-bits is specified " + "the other must be as well"); + } + } else { + if (a->element_type != ELEMENT_TYPE_NONE) { + fail(&ctx->loc, + "only args of type array may specify an element-type"); + } + if (a->element_bits != 0) { + fail(&ctx->loc, + "only args of type array may specify element-bits"); + } + } + + switch (a->element_type) { + case ELEMENT_TYPE_NONE: + t = a->type; + break; + case ELEMENT_TYPE_INT: + t = INT; + break; + case ELEMENT_TYPE_UNSIGNED: + t = UNSIGNED; + break; + default: + abort(); + } + + if (!a->enumeration_name) + return; + + e = find_enumeration(ctx->protocol, interface, + a->enumeration_name); + + switch (t) { + case INT: + if (e && e->bitfield) + fail(&ctx->loc, + "bitfield-style enum must only be referenced by uint"); + break; + case UNSIGNED: + break; + case ARRAY: + fail(&ctx->loc, + "array arg must specify element-type if enum is specified"); + default: + fail(&ctx->loc, + "enumeration-style argument has wrong type"); + } +} + static void verify_arguments(struct parse_context *ctx, struct interface *interface, @@ -976,49 +1056,7 @@ verify_arguments(struct parse_context *ctx, wl_list_for_each(m, messages, link) { struct arg *a; wl_list_for_each(a, &m->arg_list, link) { - struct enumeration *e; - enum arg_type t; - - if (a->element_type != ELEMENT_TYPE_NONE && a->type != ARRAY) { - fail(&ctx->loc, - "only args of type array may specify an element-type"); - } - - switch (a->element_type) { - case ELEMENT_TYPE_NONE: - t = a->type; - break; - case ELEMENT_TYPE_INT: - t = INT; - break; - case ELEMENT_TYPE_UNSIGNED: - t = UNSIGNED; - break; - default: - abort(); - } - - if (!a->enumeration_name) - continue; - - e = find_enumeration(ctx->protocol, interface, - a->enumeration_name); - - switch (t) { - case INT: - if (e && e->bitfield) - fail(&ctx->loc, - "bitfield-style enum must only be referenced by uint"); - break; - case UNSIGNED: - break; - case ARRAY: - fail(&ctx->loc, - "array arg must specify element-type if enum is specified"); - default: - fail(&ctx->loc, - "enumeration-style argument has wrong type"); - } + verify_argument_attributes(ctx, interface, a); } } From a09ab2a47495641089c4480dd562d2f6425c0863 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Mon, 13 Mar 2023 12:37:30 +0100 Subject: [PATCH 3/3] protocol: specify element type/bits of arrays The only array arg in the core protocol is the keys arg of the wl_keyboard.enter event. Signed-off-by: Isaac Freund --- protocol/wayland.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocol/wayland.xml b/protocol/wayland.xml index 37a7603b..25c1d162 100644 --- a/protocol/wayland.xml +++ b/protocol/wayland.xml @@ -2441,7 +2441,8 @@ - +