I tried to start some discussion on this topic previously, but it
apparently didn't make it through the moderator, so I'm trying again having
now joined the list.

I've recently taken an interest in the gowl
<https://github.com/sebastianskejoe/gowl> implementation of the wayland
protocol and noticed that the specification doesn't match the interface
that gets generated by the wayland scanner.

If I attempt to code-gen gowl using the wayland.xml file the wl_registry
bind interface is missing a couple arguments that weston expects, resulting
in the following runtime error:
libwayland: message too short, object (2), message bind(usun)

However, the spec indicates a bind request signature of "un".

I tracked this down into some curious logic in the scanner and have been
working on a patch to try and allow the corrected signature to be specified
in the protocol.  Unfortunately this has become more interesting then I'd
anticipated.

Attached is my naive attempt at resolving this issue.  I'm horrified by the
string->interface lookup and the wl_registry_bind api change but I'm not
sure what else one can do.  Any feedback or additional help would be
appreciated.

Note that this patch applies to the 1.5.91 tagged commit and compiles
cleanly (for wayland).  Weston didn't like having the lookup function
defined in multiple files, so maybe there would be a better place to put
such functionality.

Thanks,
Paul
From 4a5dfecc051c920835032b64434096f9403bd4f7 Mon Sep 17 00:00:00 2001
From: Paul Sbarra <sbarra.p...@gmail.com>
Date: Wed, 3 Sep 2014 22:09:52 -0500
Subject: [PATCH] explicitly specify all registry bind request arguments

---
 protocol/wayland.xml    |  5 ++++-
 src/scanner.c           | 58 +++++++++++++++++++++++++++++--------------------
 tests/test-compositor.c |  2 +-
 3 files changed, 39 insertions(+), 26 deletions(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index bb457bc..e8a14f0 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -127,9 +127,12 @@
     <request name="bind">
       <description summary="bind an object to the display">
 	Binds a new, client-created object to the server using the
-        specified name as the identifier.
+   specified name as the identifier, and it implements the
+   given version of the given interface.
       </description>
       <arg name="name" type="uint" summary="unique name for the object"/>
+      <arg name="interface" type="string" summary="name of the object's interface"/>
+      <arg name="version" type="uint" summary="version of the object's interface"/>
       <arg name="id" type="new_id"/>
     </request>
 
diff --git a/src/scanner.c b/src/scanner.c
index 72fd3e8..a11ad45 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -356,7 +356,7 @@ start_element(void *data, const char *element_name, const char **atts)
 		ctx->protocol->uppercase_name = uppercase_dup(name);
 		ctx->protocol->description = NULL;
 	} else if (strcmp(element_name, "copyright") == 0) {
-		
+
 	} else if (strcmp(element_name, "interface") == 0) {
 		if (name == NULL)
 			fail(&ctx->loc, "no interface name given");
@@ -704,11 +704,7 @@ emit_stubs(struct wl_list *message_list, struct interface *interface)
 		       interface->name, interface->name);
 
 		wl_list_for_each(a, &m->arg_list, link) {
-			if (a->type == NEW_ID && a->interface_name == NULL) {
-				printf(", const struct wl_interface *interface"
-				       ", uint32_t version");
-				continue;
-			} else if (a->type == NEW_ID)
+			if (a->type == NEW_ID)
 				continue;
 			printf(", ");
 			emit_type(a);
@@ -727,8 +723,15 @@ emit_stubs(struct wl_list *message_list, struct interface *interface)
 			       interface->uppercase_name,
 			       m->uppercase_name);
 
-			if (ret->interface_name == NULL)
-				printf("interface");
+			if (ret->interface_name == NULL) {
+				printf("string_to_interface(");
+      		wl_list_for_each(a, &m->arg_list, link) {
+      			if (a->type == STRING) {
+                  printf("%s)", a->name);
+                  break;
+               }
+            }
+         }
 			else
 				printf("&%s_interface", ret->interface_name);
 		} else {
@@ -741,8 +744,6 @@ emit_stubs(struct wl_list *message_list, struct interface *interface)
 
 		wl_list_for_each(a, &m->arg_list, link) {
 			if (a->type == NEW_ID) {
-				if (a->interface_name == NULL)
-					printf(", interface->name, version");
 				printf(", NULL");
 			} else {
 				printf(", %s", a->name);
@@ -885,12 +886,6 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid
 			  "\t * %s - ", m->name);
 		wl_list_for_each(a, &m->arg_list, link) {
 
-			if (side == SERVER && a->type == NEW_ID &&
-			    a->interface_name == NULL)
-				printf("\t * @interface: name of the objects interface\n"
-				       "\t * @version: version of the objects interface\n");
-
-
 			desc_dump(a->summary ? a->summary : "(none)",
 				  "\t * @%s: ", a->name);
 		}
@@ -920,8 +915,6 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid
 
 			if (side == SERVER && a->type == OBJECT)
 				printf("struct wl_resource *");
-			else if (side == SERVER && a->type == NEW_ID && a->interface_name == NULL)
-				printf("const char *interface, uint32_t version, uint32_t ");
 			else if (side == CLIENT && a->type == OBJECT && a->interface_name == NULL)
 				printf("void *");
 
@@ -997,7 +990,8 @@ emit_header(struct protocol *protocol, enum side side)
 	       "#include <stddef.h>\n"
 	       "#include \"%s\"\n\n"
 	       "struct wl_client;\n"
-	       "struct wl_resource;\n\n",
+	       "struct wl_resource;\n\n"
+          "extern const struct wl_interface* string_to_interface(const char* str);\n\n",
 	       protocol->uppercase_name, s,
 	       protocol->uppercase_name, s,
 	       (side == SERVER) ? "wayland-util.h" : "wayland-client.h");
@@ -1144,8 +1138,6 @@ emit_messages(struct wl_list *message_list,
 				printf("i");
 				break;
 			case NEW_ID:
-				if (a->interface_name == NULL)
-					printf("su");
 				printf("n");
 				break;
 			case UNSIGNED:
@@ -1187,14 +1179,16 @@ emit_code(struct protocol *protocol)
 {
 	struct interface *i;
 	struct wl_array types;
-	char **p, *prev;
+	char **p, *prev, first_pass;
 
 	if (protocol->copyright)
 		format_copyright(protocol->copyright);
 
 	printf("#include <stdlib.h>\n"
 	       "#include <stdint.h>\n"
-	       "#include \"wayland-util.h\"\n\n");
+          "#include <string.h>\n"
+	       "#include \"wayland-util.h\"\n\n"
+          "const struct wl_interface* string_to_interface(const char* str);\n\n");
 
 	wl_array_init(&types);
 	wl_list_for_each(i, &protocol->interface_list, link) {
@@ -1209,7 +1203,6 @@ emit_code(struct protocol *protocol)
 		printf("extern const struct wl_interface %s_interface;\n", *p);
 		prev = *p;
 	}
-	wl_array_release(&types);
 	printf("\n");
 
 	printf("static const struct wl_interface *types[] = {\n");
@@ -1220,6 +1213,23 @@ emit_code(struct protocol *protocol)
 	}
 	printf("};\n\n");
 
+   printf("const struct wl_interface* string_to_interface(const char* str) {\n");
+   printf("\tstruct wl_interface const *iface = NULL;\n\n");
+	prev = NULL;
+   first_pass = 1;
+	wl_array_for_each(p, &types) {
+		if (prev && strcmp(*p, prev) == 0)
+			continue;
+
+      printf(first_pass != 0 ? "\t" : "\telse ");
+      printf("if (strncmp(str, \"%s\", %zu) == 0)\n\t\tiface = &%s_interface;\n", *p, strlen(*p), *p);
+      first_pass = 0;
+		prev = *p;
+   }
+   printf("\treturn iface;\n}\n\n");
+	wl_array_release(&types);
+	printf("\n");
+
 	wl_list_for_each(i, &protocol->interface_list, link) {
 
 		emit_messages(&i->request_list, i, "requests");
diff --git a/tests/test-compositor.c b/tests/test-compositor.c
index 3248e2d..4382242 100644
--- a/tests/test-compositor.c
+++ b/tests/test-compositor.c
@@ -388,7 +388,7 @@ registry_handle_globals(void *data, struct wl_registry *registry,
 	if (strcmp(intf, "test") != 0)
 		return;
 
-	c->tc = wl_registry_bind(registry, id, &test_compositor_interface, ver);
+	c->tc = wl_registry_bind(registry, id, test_compositor_interface.name, ver);
 	assert(c->tc && "Failed binding to registry");
 
 	wl_proxy_add_listener((struct wl_proxy *) c->tc,
-- 
2.1.0

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to