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 <mail@isaacfreund.com>
This commit is contained in:
Isaac Freund 2023-03-09 22:22:58 +01:00
parent c739b975ad
commit 5cf0063e5c
No known key found for this signature in database
GPG key ID: 86DED400DDFD7A11
2 changed files with 82 additions and 43 deletions

View file

@ -29,5 +29,6 @@
<!ATTLIST arg allow-null CDATA #IMPLIED>
<!ATTLIST arg enum CDATA #IMPLIED>
<!ATTLIST arg element-type CDATA #IMPLIED>
<!ATTLIST arg element-bits CDATA #IMPLIED>
<!ELEMENT description (#PCDATA)>
<!ATTLIST description summary CDATA #REQUIRED>

View file

@ -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);
}
}