Introduce enum wl_arg_type

This is less cryptic to read than letters, and allows the compiler
to check switch statements exhaustiveness.

Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
Simon Ser 2024-02-15 10:37:34 +01:00
parent 47de87263c
commit 155dd63b58
4 changed files with 111 additions and 92 deletions

View file

@ -441,14 +441,14 @@ get_next_argument(const char *signature, struct argument_details *details)
details->nullable = 0; details->nullable = 0;
for(; *signature; ++signature) { for(; *signature; ++signature) {
switch(*signature) { switch(*signature) {
case 'i': case WL_ARG_INT:
case 'u': case WL_ARG_UINT:
case 'f': case WL_ARG_FIXED:
case 's': case WL_ARG_STRING:
case 'o': case WL_ARG_OBJECT:
case 'n': case WL_ARG_NEW_ID:
case 'a': case WL_ARG_ARRAY:
case 'h': case WL_ARG_FD:
details->type = *signature; details->type = *signature;
return signature + 1; return signature + 1;
case '?': case '?':
@ -465,14 +465,14 @@ arg_count_for_signature(const char *signature)
int count = 0; int count = 0;
for(; *signature; ++signature) { for(; *signature; ++signature) {
switch(*signature) { switch(*signature) {
case 'i': case WL_ARG_INT:
case 'u': case WL_ARG_UINT:
case 'f': case WL_ARG_FIXED:
case 's': case WL_ARG_STRING:
case 'o': case WL_ARG_OBJECT:
case 'n': case WL_ARG_NEW_ID:
case 'a': case WL_ARG_ARRAY:
case 'h': case WL_ARG_FD:
++count; ++count;
} }
} }
@ -505,32 +505,30 @@ wl_argument_from_va_list(const char *signature, union wl_argument *args,
sig_iter = get_next_argument(sig_iter, &arg); sig_iter = get_next_argument(sig_iter, &arg);
switch(arg.type) { switch(arg.type) {
case 'i': case WL_ARG_INT:
args[i].i = va_arg(ap, int32_t); args[i].i = va_arg(ap, int32_t);
break; break;
case 'u': case WL_ARG_UINT:
args[i].u = va_arg(ap, uint32_t); args[i].u = va_arg(ap, uint32_t);
break; break;
case 'f': case WL_ARG_FIXED:
args[i].f = va_arg(ap, wl_fixed_t); args[i].f = va_arg(ap, wl_fixed_t);
break; break;
case 's': case WL_ARG_STRING:
args[i].s = va_arg(ap, const char *); args[i].s = va_arg(ap, const char *);
break; break;
case 'o': case WL_ARG_OBJECT:
args[i].o = va_arg(ap, struct wl_object *); args[i].o = va_arg(ap, struct wl_object *);
break; break;
case 'n': case WL_ARG_NEW_ID:
args[i].o = va_arg(ap, struct wl_object *); args[i].o = va_arg(ap, struct wl_object *);
break; break;
case 'a': case WL_ARG_ARRAY:
args[i].a = va_arg(ap, struct wl_array *); args[i].a = va_arg(ap, struct wl_array *);
break; break;
case 'h': case WL_ARG_FD:
args[i].h = va_arg(ap, int32_t); args[i].h = va_arg(ap, int32_t);
break; break;
case '\0':
return;
} }
} }
} }
@ -544,7 +542,7 @@ wl_closure_clear_fds(struct wl_closure *closure)
for (i = 0; i < closure->count; i++) { for (i = 0; i < closure->count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
if (arg.type == 'h') if (arg.type == WL_ARG_FD)
closure->args[i].h = -1; closure->args[i].h = -1;
} }
} }
@ -622,30 +620,30 @@ wl_closure_marshal(struct wl_object *sender, uint32_t opcode,
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'f': case WL_ARG_FIXED:
case 'u': case WL_ARG_UINT:
case 'i': case WL_ARG_INT:
break; break;
case 's': case WL_ARG_STRING:
if (!arg.nullable && args[i].s == NULL) if (!arg.nullable && args[i].s == NULL)
goto err_null; goto err_null;
break; break;
case 'o': case WL_ARG_OBJECT:
if (!arg.nullable && args[i].o == NULL) if (!arg.nullable && args[i].o == NULL)
goto err_null; goto err_null;
break; break;
case 'n': case WL_ARG_NEW_ID:
object = args[i].o; object = args[i].o;
if (object == NULL) if (object == NULL)
goto err_null; goto err_null;
closure->args[i].n = object ? object->id : 0; closure->args[i].n = object ? object->id : 0;
break; break;
case 'a': case WL_ARG_ARRAY:
if (args[i].a == NULL) if (args[i].a == NULL)
goto err_null; goto err_null;
break; break;
case 'h': case WL_ARG_FD:
fd = args[i].h; fd = args[i].h;
dup_fd = wl_os_dupfd_cloexec(fd, 0); dup_fd = wl_os_dupfd_cloexec(fd, 0);
if (dup_fd < 0) { if (dup_fd < 0) {
@ -731,7 +729,7 @@ wl_connection_demarshal(struct wl_connection *connection,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
if (arg.type != 'h' && p + 1 > end) { if (arg.type != WL_ARG_FD && p + 1 > end) {
wl_log("message too short, " wl_log("message too short, "
"object (%d), message %s(%s)\n", "object (%d), message %s(%s)\n",
closure->sender_id, message->name, closure->sender_id, message->name,
@ -741,16 +739,16 @@ wl_connection_demarshal(struct wl_connection *connection,
} }
switch (arg.type) { switch (arg.type) {
case 'u': case WL_ARG_UINT:
closure->args[i].u = *p++; closure->args[i].u = *p++;
break; break;
case 'i': case WL_ARG_INT:
closure->args[i].i = *p++; closure->args[i].i = *p++;
break; break;
case 'f': case WL_ARG_FIXED:
closure->args[i].f = *p++; closure->args[i].f = *p++;
break; break;
case 's': case WL_ARG_STRING:
length = *p++; length = *p++;
if (length == 0 && !arg.nullable) { if (length == 0 && !arg.nullable) {
@ -789,7 +787,7 @@ wl_connection_demarshal(struct wl_connection *connection,
closure->args[i].s = s; closure->args[i].s = s;
p = next; p = next;
break; break;
case 'o': case WL_ARG_OBJECT:
id = *p++; id = *p++;
closure->args[i].n = id; closure->args[i].n = id;
@ -801,7 +799,7 @@ wl_connection_demarshal(struct wl_connection *connection,
goto err; goto err;
} }
break; break;
case 'n': case WL_ARG_NEW_ID:
id = *p++; id = *p++;
closure->args[i].n = id; closure->args[i].n = id;
@ -824,7 +822,7 @@ wl_connection_demarshal(struct wl_connection *connection,
} }
break; break;
case 'a': case WL_ARG_ARRAY:
length = *p++; length = *p++;
length_in_u32 = div_roundup(length, sizeof *p); length_in_u32 = div_roundup(length, sizeof *p);
@ -845,7 +843,7 @@ wl_connection_demarshal(struct wl_connection *connection,
closure->args[i].a = array_extra++; closure->args[i].a = array_extra++;
p = next; p = next;
break; break;
case 'h': case WL_ARG_FD:
if (connection->fds_in.tail == connection->fds_in.head) { if (connection->fds_in.tail == connection->fds_in.head) {
wl_log("file descriptor expected, " wl_log("file descriptor expected, "
"object (%d), message %s(%s)\n", "object (%d), message %s(%s)\n",
@ -909,7 +907,7 @@ wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects)
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'o': case WL_ARG_OBJECT:
id = closure->args[i].n; id = closure->args[i].n;
closure->args[i].o = NULL; closure->args[i].o = NULL;
@ -936,6 +934,9 @@ wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects)
return -1; return -1;
} }
closure->args[i].o = object; closure->args[i].o = object;
break;
default:
break;
} }
} }
@ -956,27 +957,27 @@ convert_arguments_to_ffi(const char *signature, uint32_t flags,
sig_iter = get_next_argument(sig_iter, &arg); sig_iter = get_next_argument(sig_iter, &arg);
switch(arg.type) { switch(arg.type) {
case 'i': case WL_ARG_INT:
ffi_types[i] = &ffi_type_sint32; ffi_types[i] = &ffi_type_sint32;
ffi_args[i] = &args[i].i; ffi_args[i] = &args[i].i;
break; break;
case 'u': case WL_ARG_UINT:
ffi_types[i] = &ffi_type_uint32; ffi_types[i] = &ffi_type_uint32;
ffi_args[i] = &args[i].u; ffi_args[i] = &args[i].u;
break; break;
case 'f': case WL_ARG_FIXED:
ffi_types[i] = &ffi_type_sint32; ffi_types[i] = &ffi_type_sint32;
ffi_args[i] = &args[i].f; ffi_args[i] = &args[i].f;
break; break;
case 's': case WL_ARG_STRING:
ffi_types[i] = &ffi_type_pointer; ffi_types[i] = &ffi_type_pointer;
ffi_args[i] = &args[i].s; ffi_args[i] = &args[i].s;
break; break;
case 'o': case WL_ARG_OBJECT:
ffi_types[i] = &ffi_type_pointer; ffi_types[i] = &ffi_type_pointer;
ffi_args[i] = &args[i].o; ffi_args[i] = &args[i].o;
break; break;
case 'n': case WL_ARG_NEW_ID:
if (flags & WL_CLOSURE_INVOKE_CLIENT) { if (flags & WL_CLOSURE_INVOKE_CLIENT) {
ffi_types[i] = &ffi_type_pointer; ffi_types[i] = &ffi_type_pointer;
ffi_args[i] = &args[i].o; ffi_args[i] = &args[i].o;
@ -985,11 +986,11 @@ convert_arguments_to_ffi(const char *signature, uint32_t flags,
ffi_args[i] = &args[i].n; ffi_args[i] = &args[i].n;
} }
break; break;
case 'a': case WL_ARG_ARRAY:
ffi_types[i] = &ffi_type_pointer; ffi_types[i] = &ffi_type_pointer;
ffi_args[i] = &args[i].a; ffi_args[i] = &args[i].a;
break; break;
case 'h': case WL_ARG_FD:
ffi_types[i] = &ffi_type_sint32; ffi_types[i] = &ffi_type_sint32;
ffi_args[i] = &args[i].h; ffi_args[i] = &args[i].h;
break; break;
@ -1056,7 +1057,7 @@ copy_fds_to_connection(struct wl_closure *closure,
count = arg_count_for_signature(signature); count = arg_count_for_signature(signature);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
if (arg.type != 'h') if (arg.type != WL_ARG_FD)
continue; continue;
fd = closure->args[i].h; fd = closure->args[i].h;
@ -1087,16 +1088,16 @@ buffer_size_for_closure(struct wl_closure *closure)
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'h': case WL_ARG_FD:
break; break;
case 'u': case WL_ARG_UINT:
case 'i': case WL_ARG_INT:
case 'f': case WL_ARG_FIXED:
case 'o': case WL_ARG_OBJECT:
case 'n': case WL_ARG_NEW_ID:
buffer_size++; buffer_size++;
break; break;
case 's': case WL_ARG_STRING:
if (closure->args[i].s == NULL) { if (closure->args[i].s == NULL) {
buffer_size++; buffer_size++;
break; break;
@ -1105,7 +1106,7 @@ buffer_size_for_closure(struct wl_closure *closure)
size = strlen(closure->args[i].s) + 1; size = strlen(closure->args[i].s) + 1;
buffer_size += 1 + div_roundup(size, sizeof(uint32_t)); buffer_size += 1 + div_roundup(size, sizeof(uint32_t));
break; break;
case 'a': case WL_ARG_ARRAY:
if (closure->args[i].a == NULL) { if (closure->args[i].a == NULL) {
buffer_size++; buffer_size++;
break; break;
@ -1143,29 +1144,29 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
if (arg.type == 'h') if (arg.type == WL_ARG_FD)
continue; continue;
if (p + 1 > end) if (p + 1 > end)
goto overflow; goto overflow;
switch (arg.type) { switch (arg.type) {
case 'u': case WL_ARG_UINT:
*p++ = closure->args[i].u; *p++ = closure->args[i].u;
break; break;
case 'i': case WL_ARG_INT:
*p++ = closure->args[i].i; *p++ = closure->args[i].i;
break; break;
case 'f': case WL_ARG_FIXED:
*p++ = closure->args[i].f; *p++ = closure->args[i].f;
break; break;
case 'o': case WL_ARG_OBJECT:
*p++ = closure->args[i].o ? closure->args[i].o->id : 0; *p++ = closure->args[i].o ? closure->args[i].o->id : 0;
break; break;
case 'n': case WL_ARG_NEW_ID:
*p++ = closure->args[i].n; *p++ = closure->args[i].n;
break; break;
case 's': case WL_ARG_STRING:
if (closure->args[i].s == NULL) { if (closure->args[i].s == NULL) {
*p++ = 0; *p++ = 0;
break; break;
@ -1180,7 +1181,7 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
memcpy(p, closure->args[i].s, size); memcpy(p, closure->args[i].s, size);
p += div_roundup(size, sizeof *p); p += div_roundup(size, sizeof *p);
break; break;
case 'a': case WL_ARG_ARRAY:
if (closure->args[i].a == NULL) { if (closure->args[i].a == NULL) {
*p++ = 0; *p++ = 0;
break; break;
@ -1196,7 +1197,7 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
memcpy(p, closure->args[i].a->data, size); memcpy(p, closure->args[i].a->data, size);
p += div_roundup(size, sizeof *p); p += div_roundup(size, sizeof *p);
break; break;
default: case WL_ARG_FD:
break; break;
} }
} }
@ -1320,13 +1321,13 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
fprintf(f, ", "); fprintf(f, ", ");
switch (arg.type) { switch (arg.type) {
case 'u': case WL_ARG_UINT:
fprintf(f, "%u", closure->args[i].u); fprintf(f, "%u", closure->args[i].u);
break; break;
case 'i': case WL_ARG_INT:
fprintf(f, "%d", closure->args[i].i); fprintf(f, "%d", closure->args[i].i);
break; break;
case 'f': case WL_ARG_FIXED:
/* The magic number 390625 is 1e8 / 256 */ /* The magic number 390625 is 1e8 / 256 */
if (closure->args[i].f >= 0) { if (closure->args[i].f >= 0) {
fprintf(f, "%d.%08d", fprintf(f, "%d.%08d",
@ -1339,13 +1340,13 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
-390625 * (closure->args[i].f % 256)); -390625 * (closure->args[i].f % 256));
} }
break; break;
case 's': case WL_ARG_STRING:
if (closure->args[i].s) if (closure->args[i].s)
fprintf(f, "\"%s\"", closure->args[i].s); fprintf(f, "\"%s\"", closure->args[i].s);
else else
fprintf(f, "nil"); fprintf(f, "nil");
break; break;
case 'o': case WL_ARG_OBJECT:
if (closure->args[i].o) if (closure->args[i].o)
fprintf(f, "%s#%u", fprintf(f, "%s#%u",
closure->args[i].o->interface->name, closure->args[i].o->interface->name,
@ -1353,7 +1354,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
else else
fprintf(f, "nil"); fprintf(f, "nil");
break; break;
case 'n': case WL_ARG_NEW_ID:
if (n_parse) if (n_parse)
nval = n_parse(&closure->args[i]); nval = n_parse(&closure->args[i]);
else else
@ -1368,10 +1369,10 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
else else
fprintf(f, "nil"); fprintf(f, "nil");
break; break;
case 'a': case WL_ARG_ARRAY:
fprintf(f, "array[%zu]", closure->args[i].a->size); fprintf(f, "array[%zu]", closure->args[i].a->size);
break; break;
case 'h': case WL_ARG_FD:
fprintf(f, "fd %d", closure->args[i].h); fprintf(f, "fd %d", closure->args[i].h);
break; break;
} }
@ -1394,7 +1395,7 @@ wl_closure_close_fds(struct wl_closure *closure)
for (i = 0; i < closure->count; i++) { for (i = 0; i < closure->count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
if (arg.type == 'h' && closure->args[i].h != -1) if (arg.type == WL_ARG_FD && closure->args[i].h != -1)
close(closure->args[i].h); close(closure->args[i].h);
} }

View file

@ -258,8 +258,8 @@ validate_closure_objects(struct wl_closure *closure)
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'n': case WL_ARG_NEW_ID:
case 'o': case WL_ARG_OBJECT:
proxy = (struct wl_proxy *) closure->args[i].o; proxy = (struct wl_proxy *) closure->args[i].o;
if (proxy && proxy->flags & WL_PROXY_FLAG_DESTROYED) if (proxy && proxy->flags & WL_PROXY_FLAG_DESTROYED)
closure->args[i].o = NULL; closure->args[i].o = NULL;
@ -286,8 +286,8 @@ destroy_queued_closure(struct wl_closure *closure)
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'n': case WL_ARG_NEW_ID:
case 'o': case WL_ARG_OBJECT:
proxy = (struct wl_proxy *) closure->args[i].o; proxy = (struct wl_proxy *) closure->args[i].o;
if (proxy) if (proxy)
wl_proxy_unref(proxy); wl_proxy_unref(proxy);
@ -421,7 +421,7 @@ message_count_fds(const char *signature)
count = arg_count_for_signature(signature); count = arg_count_for_signature(signature);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
if (arg.type == 'h') if (arg.type == WL_ARG_FD)
fds++; fds++;
} }
@ -735,13 +735,15 @@ create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message,
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'n': case WL_ARG_NEW_ID:
new_proxy = proxy_create(proxy, interface, version); new_proxy = proxy_create(proxy, interface, version);
if (new_proxy == NULL) if (new_proxy == NULL)
return NULL; return NULL;
args[i].o = &new_proxy->object; args[i].o = &new_proxy->object;
break; break;
default:
break;
} }
} }
@ -1490,7 +1492,7 @@ create_proxies(struct wl_proxy *sender, struct wl_closure *closure)
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'n': case WL_ARG_NEW_ID:
id = closure->args[i].n; id = closure->args[i].n;
if (id == 0) { if (id == 0) {
closure->args[i].o = NULL; closure->args[i].o = NULL;
@ -1523,8 +1525,8 @@ increase_closure_args_refcount(struct wl_closure *closure)
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'n': case WL_ARG_NEW_ID:
case 'o': case WL_ARG_OBJECT:
proxy = (struct wl_proxy *) closure->args[i].o; proxy = (struct wl_proxy *) closure->args[i].o;
if (proxy) if (proxy)
proxy->refcount++; proxy->refcount++;

View file

@ -48,6 +48,20 @@
#define WL_MAP_MAX_OBJECTS 0x00f00000 #define WL_MAP_MAX_OBJECTS 0x00f00000
#define WL_CLOSURE_MAX_ARGS 20 #define WL_CLOSURE_MAX_ARGS 20
/**
* Argument types used in signatures.
*/
enum wl_arg_type {
WL_ARG_INT = 'i',
WL_ARG_UINT = 'u',
WL_ARG_FIXED = 'f',
WL_ARG_STRING = 's',
WL_ARG_OBJECT = 'o',
WL_ARG_NEW_ID = 'n',
WL_ARG_ARRAY = 'a',
WL_ARG_FD = 'h',
};
struct wl_object { struct wl_object {
const struct wl_interface *interface; const struct wl_interface *interface;
const void *implementation; const void *implementation;
@ -149,7 +163,7 @@ struct wl_closure {
}; };
struct argument_details { struct argument_details {
char type; enum wl_arg_type type;
int nullable; int nullable;
}; };

View file

@ -191,8 +191,8 @@ verify_objects(struct wl_resource *resource, uint32_t opcode,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg); signature = get_next_argument(signature, &arg);
switch (arg.type) { switch (arg.type) {
case 'n': case WL_ARG_NEW_ID:
case 'o': case WL_ARG_OBJECT:
res = (struct wl_resource *) (args[i].o); res = (struct wl_resource *) (args[i].o);
if (res && res->client != resource->client) { if (res && res->client != resource->client) {
wl_log("compositor bug: The compositor " wl_log("compositor bug: The compositor "
@ -202,6 +202,8 @@ verify_objects(struct wl_resource *resource, uint32_t opcode,
object->interface->events[opcode].name); object->interface->events[opcode].name);
return false; return false;
} }
default:
break;
} }
} }
return true; return true;