mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2026-03-10 05:34:16 -04:00
Merge branch 'array-arg-element-type-print' into 'main'
Draft: connection: print elements of arrays with element-type See merge request wayland/wayland!301
This commit is contained in:
commit
230b6c871a
6 changed files with 231 additions and 26 deletions
|
|
@ -28,5 +28,7 @@
|
||||||
<!ATTLIST arg interface CDATA #IMPLIED>
|
<!ATTLIST arg interface CDATA #IMPLIED>
|
||||||
<!ATTLIST arg allow-null CDATA #IMPLIED>
|
<!ATTLIST arg allow-null CDATA #IMPLIED>
|
||||||
<!ATTLIST arg enum CDATA #IMPLIED>
|
<!ATTLIST arg enum CDATA #IMPLIED>
|
||||||
|
<!ATTLIST arg element-type CDATA #IMPLIED>
|
||||||
|
<!ATTLIST arg element-bits CDATA #IMPLIED>
|
||||||
<!ELEMENT description (#PCDATA)>
|
<!ELEMENT description (#PCDATA)>
|
||||||
<!ATTLIST description summary CDATA #REQUIRED>
|
<!ATTLIST description summary CDATA #REQUIRED>
|
||||||
|
|
|
||||||
|
|
@ -2455,7 +2455,8 @@
|
||||||
</description>
|
</description>
|
||||||
<arg name="serial" type="uint" summary="serial number of the enter event"/>
|
<arg name="serial" type="uint" summary="serial number of the enter event"/>
|
||||||
<arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
|
<arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
|
||||||
<arg name="keys" type="array" summary="the currently pressed keys"/>
|
<arg name="keys" type="array" element-type="uint" element-bits="32"
|
||||||
|
summary="the currently pressed keys"/>
|
||||||
</event>
|
</event>
|
||||||
|
|
||||||
<event name="leave">
|
<event name="leave">
|
||||||
|
|
|
||||||
110
src/connection.c
110
src/connection.c
|
|
@ -435,10 +435,28 @@ wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
|
||||||
return ring_buffer_put(&connection->fds_out, &fd, sizeof fd);
|
return ring_buffer_put(&connection->fds_out, &fd, sizeof fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
parse_array_signature(const char *signature, struct argument_details *details)
|
||||||
|
{
|
||||||
|
details->type = *signature;
|
||||||
|
if (signature[1] == '[') {
|
||||||
|
details->element_type = signature[2];
|
||||||
|
signature += 3;
|
||||||
|
while (*signature != ']') {
|
||||||
|
details->element_bits *= 10;
|
||||||
|
details->element_bits += (*signature) - '0';
|
||||||
|
++signature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return signature + 1;
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
get_next_argument(const char *signature, struct argument_details *details)
|
get_next_argument(const char *signature, struct argument_details *details)
|
||||||
{
|
{
|
||||||
details->nullable = 0;
|
details->nullable = 0;
|
||||||
|
details->element_type = '\0';
|
||||||
|
details->element_bits = 0;
|
||||||
for(; *signature; ++signature) {
|
for(; *signature; ++signature) {
|
||||||
switch(*signature) {
|
switch(*signature) {
|
||||||
case 'i':
|
case 'i':
|
||||||
|
|
@ -447,10 +465,11 @@ get_next_argument(const char *signature, struct argument_details *details)
|
||||||
case 's':
|
case 's':
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'n':
|
case 'n':
|
||||||
case 'a':
|
|
||||||
case 'h':
|
case 'h':
|
||||||
details->type = *signature;
|
details->type = *signature;
|
||||||
return signature + 1;
|
return signature + 1;
|
||||||
|
case 'a':
|
||||||
|
return parse_array_signature(signature, details);
|
||||||
case '?':
|
case '?':
|
||||||
details->nullable = 1;
|
details->nullable = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -471,9 +490,14 @@ arg_count_for_signature(const char *signature)
|
||||||
case 's':
|
case 's':
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'n':
|
case 'n':
|
||||||
case 'a':
|
|
||||||
case 'h':
|
case 'h':
|
||||||
++count;
|
++count;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
++count;
|
||||||
|
if (signature[1] == '[')
|
||||||
|
while (*signature != ']') ++signature;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
|
@ -1281,6 +1305,86 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wl_closure_print_array(FILE *f, struct argument_details *arg,
|
||||||
|
struct wl_array *array)
|
||||||
|
{
|
||||||
|
int8_t *i8;
|
||||||
|
int16_t *i16;
|
||||||
|
int32_t *i32;
|
||||||
|
uint8_t *u8;
|
||||||
|
uint16_t *u16;
|
||||||
|
uint32_t *u32;
|
||||||
|
|
||||||
|
fprintf(f, "array[");
|
||||||
|
switch (arg->element_type) {
|
||||||
|
case 'i':
|
||||||
|
switch (arg->element_bits) {
|
||||||
|
case 8:
|
||||||
|
wl_array_for_each(i8, array) {
|
||||||
|
if (i8 == array->data)
|
||||||
|
fprintf(f, "%"PRId8, *i8);
|
||||||
|
else
|
||||||
|
fprintf(f, ",%"PRId8, *i8);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
wl_array_for_each(i16, array) {
|
||||||
|
if (i16 == array->data)
|
||||||
|
fprintf(f, "%"PRId16, *i16);
|
||||||
|
else
|
||||||
|
fprintf(f, ",%"PRId16, *i16);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
wl_array_for_each(i32, array) {
|
||||||
|
if (i32 == array->data)
|
||||||
|
fprintf(f, "%"PRId32, *i32);
|
||||||
|
else
|
||||||
|
fprintf(f, ",%"PRId32, *i32);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
switch (arg->element_bits) {
|
||||||
|
case 8:
|
||||||
|
wl_array_for_each(u8, array) {
|
||||||
|
if (u8 == array->data)
|
||||||
|
fprintf(f, "%"PRIu8, *u8);
|
||||||
|
else
|
||||||
|
fprintf(f, ",%"PRIu8, *u8);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
wl_array_for_each(u16, array) {
|
||||||
|
if (u16 == array->data)
|
||||||
|
fprintf(f, "%"PRIu16, *u16);
|
||||||
|
else
|
||||||
|
fprintf(f, ",%"PRIu16, *u16);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
wl_array_for_each(u32, array) {
|
||||||
|
if (u32 == array->data)
|
||||||
|
fprintf(f, "%"PRIu32, *u32);
|
||||||
|
else
|
||||||
|
fprintf(f, ",%"PRIu32, *u32);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\0':
|
||||||
|
fprintf(f, "size: %zu", array->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(f, "]");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_closure_print(struct wl_closure *closure, struct wl_object *target,
|
wl_closure_print(struct wl_closure *closure, struct wl_object *target,
|
||||||
int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg),
|
int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg),
|
||||||
|
|
@ -1369,7 +1473,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
|
||||||
fprintf(f, "nil");
|
fprintf(f, "nil");
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
fprintf(f, "array[%zu]", closure->args[i].a->size);
|
wl_closure_print_array(f, &arg, closure->args[i].a);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
fprintf(f, "fd %d", closure->args[i].h);
|
fprintf(f, "fd %d", closure->args[i].h);
|
||||||
|
|
|
||||||
138
src/scanner.c
138
src/scanner.c
|
|
@ -209,6 +209,12 @@ enum arg_type {
|
||||||
FD
|
FD
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum element_type {
|
||||||
|
ELEMENT_TYPE_NONE,
|
||||||
|
ELEMENT_TYPE_INT,
|
||||||
|
ELEMENT_TYPE_UNSIGNED,
|
||||||
|
};
|
||||||
|
|
||||||
struct arg {
|
struct arg {
|
||||||
char *name;
|
char *name;
|
||||||
enum arg_type type;
|
enum arg_type type;
|
||||||
|
|
@ -217,6 +223,8 @@ struct arg {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
char *summary;
|
char *summary;
|
||||||
char *enumeration_name;
|
char *enumeration_name;
|
||||||
|
enum element_type element_type;
|
||||||
|
int element_bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct enumeration {
|
struct enumeration {
|
||||||
|
|
@ -716,7 +724,9 @@ start_element(void *data, const char *element_name, const char **atts)
|
||||||
const char *allow_null = NULL;
|
const char *allow_null = NULL;
|
||||||
const char *enumeration_name = NULL;
|
const char *enumeration_name = NULL;
|
||||||
const char *bitfield = NULL;
|
const char *bitfield = NULL;
|
||||||
|
const char *element_type = NULL;
|
||||||
int i, version = 0;
|
int i, version = 0;
|
||||||
|
int element_bits = 0;
|
||||||
|
|
||||||
ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
|
ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
|
||||||
for (i = 0; atts[i]; i += 2) {
|
for (i = 0; atts[i]; i += 2) {
|
||||||
|
|
@ -743,6 +753,23 @@ start_element(void *data, const char *element_name, const char **atts)
|
||||||
enumeration_name = atts[i + 1];
|
enumeration_name = atts[i + 1];
|
||||||
if (strcmp(atts[i], "bitfield") == 0)
|
if (strcmp(atts[i], "bitfield") == 0)
|
||||||
bitfield = atts[i + 1];
|
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;
|
ctx->character_data_length = 0;
|
||||||
|
|
@ -841,6 +868,21 @@ start_element(void *data, const char *element_name, const char **atts)
|
||||||
else
|
else
|
||||||
arg->enumeration_name = xstrdup(enumeration_name);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg->element_bits = element_bits;
|
||||||
|
|
||||||
if (summary)
|
if (summary)
|
||||||
arg->summary = xstrdup(summary);
|
arg->summary = xstrdup(summary);
|
||||||
|
|
||||||
|
|
@ -942,6 +984,68 @@ find_enumeration(struct protocol *protocol,
|
||||||
return NULL;
|
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
|
static void
|
||||||
verify_arguments(struct parse_context *ctx,
|
verify_arguments(struct parse_context *ctx,
|
||||||
struct interface *interface,
|
struct interface *interface,
|
||||||
|
|
@ -952,27 +1056,7 @@ verify_arguments(struct parse_context *ctx,
|
||||||
wl_list_for_each(m, messages, link) {
|
wl_list_for_each(m, messages, link) {
|
||||||
struct arg *a;
|
struct arg *a;
|
||||||
wl_list_for_each(a, &m->arg_list, link) {
|
wl_list_for_each(a, &m->arg_list, link) {
|
||||||
struct enumeration *e;
|
verify_argument_attributes(ctx, interface, a);
|
||||||
|
|
||||||
if (!a->enumeration_name)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
|
||||||
e = find_enumeration(ctx->protocol, interface,
|
|
||||||
a->enumeration_name);
|
|
||||||
|
|
||||||
switch (a->type) {
|
|
||||||
case INT:
|
|
||||||
if (e && e->bitfield)
|
|
||||||
fail(&ctx->loc,
|
|
||||||
"bitfield-style enum must only be referenced by uint");
|
|
||||||
break;
|
|
||||||
case UNSIGNED:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fail(&ctx->loc,
|
|
||||||
"enumeration-style argument has wrong type");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1793,7 +1877,17 @@ emit_messages(const char *name, struct wl_list *message_list,
|
||||||
printf("o");
|
printf("o");
|
||||||
break;
|
break;
|
||||||
case ARRAY:
|
case ARRAY:
|
||||||
printf("a");
|
switch (a->element_type) {
|
||||||
|
case ELEMENT_TYPE_NONE:
|
||||||
|
printf("a");
|
||||||
|
break;
|
||||||
|
case ELEMENT_TYPE_INT:
|
||||||
|
printf("a[i%d]", a->element_bits);
|
||||||
|
break;
|
||||||
|
case ELEMENT_TYPE_UNSIGNED:
|
||||||
|
printf("a[u%d]", a->element_bits);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case FD:
|
case FD:
|
||||||
printf("h");
|
printf("h");
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,8 @@ struct wl_closure {
|
||||||
struct argument_details {
|
struct argument_details {
|
||||||
char type;
|
char type;
|
||||||
int nullable;
|
int nullable;
|
||||||
|
char element_type;
|
||||||
|
int element_bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,8 @@ struct wl_object;
|
||||||
* * `a`: array
|
* * `a`: array
|
||||||
* * `h`: fd
|
* * `h`: fd
|
||||||
* * `?`: following argument (`o` or `s`) is nullable
|
* * `?`: following argument (`o` or `s`) is nullable
|
||||||
|
* * `[i32]`: the preceding array argument has 32 bit signed integer elements
|
||||||
|
* * `[u8]`: the preceding array argument has 8 bit unsigned integer elements
|
||||||
*
|
*
|
||||||
* While demarshaling primitive arguments is straightforward, when demarshaling
|
* While demarshaling primitive arguments is straightforward, when demarshaling
|
||||||
* messages containing `object` or `new_id` arguments, the protocol
|
* messages containing `object` or `new_id` arguments, the protocol
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue