[PATCH wayland v3] protocol: add support for cross-interface enum attributes

Auke Booij auke at tulcod.com
Sat Dec 5 04:39:12 PST 2015


The enum attribute, for which scanner support was introduced in
1771299, can be used to link message arguments to <enum>s. However,
some arguments refer to <enum>s in a different <interface>.

This adds scanner support for referring to an <enum> in a different
<interface> using dot notation. It also sets the attributes in this
style in the wayland XML protocol (wl_shm_pool::create_buffer::format
to wl_shm::format, and wl_surface::set_buffer_transform::transform to
wl_output::transform), and updates the documentation XSL so that this
new style is supported.

Changes since v2:
 - add object:: prefix for all enumerations in the documentation
 - fix whitespace in scanner.c
 - minor code fixup to return early and avoid casts in scanner.c

Changes since v1:
 - several implementation bugs fixed

Signed-off-by: Auke Booij <auke at tulcod.com>
---
 doc/publican/protocol-to-docbook.xsl | 19 +++++++++--
 protocol/wayland.xml                 |  4 +--
 src/scanner.c                        | 63 +++++++++++++++++++++++++++---------
 3 files changed, 65 insertions(+), 21 deletions(-)

diff --git a/doc/publican/protocol-to-docbook.xsl b/doc/publican/protocol-to-docbook.xsl
index fad207a..7e892c3 100644
--- a/doc/publican/protocol-to-docbook.xsl
+++ b/doc/publican/protocol-to-docbook.xsl
@@ -103,9 +103,22 @@
     <listitem>
         <simpara>
           <xsl:if test="@enum">
-            <link linkend="protocol-spec-{../../@name}-enum-{@enum}">
-              <xsl:value-of select="@enum"/>
-            </link>
+            <xsl:choose>
+              <xsl:when test="contains(@enum, '.')">
+                <link linkend="protocol-spec-{substring-before(@enum, '.')}-enum-{substring-after(@enum, '.')}">
+                  <xsl:value-of select="substring-before(@enum, '.')"/>
+                  <xsl:text>::</xsl:text>
+                  <xsl:value-of select="substring-after(@enum, '.')"/>
+                </link>
+              </xsl:when>
+              <xsl:otherwise>
+                <link linkend="protocol-spec-{../../@name}-enum-{@enum}">
+                  <xsl:value-of select="../../@name"/>
+                  <xsl:text>::</xsl:text>
+                  <xsl:value-of select="@enum"/>
+                </link>
+              </xsl:otherwise>
+            </xsl:choose>
 	    <xsl:text> </xsl:text>
           </xsl:if>
           <xsl:value-of select="@type"/>
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index f9e6d76..0873553 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -229,7 +229,7 @@
       <arg name="width" type="int"/>
       <arg name="height" type="int"/>
       <arg name="stride" type="int"/>
-      <arg name="format" type="uint"/>
+      <arg name="format" type="uint" enum="wl_shm.format"/>
     </request>
 
     <request name="destroy" type="destructor">
@@ -1292,7 +1292,7 @@
 	wl_output.transform enum the invalid_transform protocol error
 	is raised.
       </description>
-      <arg name="transform" type="int"/>
+      <arg name="transform" type="int" enum="wl_output.transform"/>
     </request>
 
     <!-- Version 3 additions -->
diff --git a/src/scanner.c b/src/scanner.c
index 406519f..85aeea7 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -747,8 +747,8 @@ start_element(void *data, const char *element_name, const char **atts)
 			enumeration->bitfield = true;
 		else
 			fail(&ctx->loc,
-                             "invalid value (%s) for bitfield attribute (only true/false are accepted)",
-                             bitfield);
+			     "invalid value (%s) for bitfield attribute (only true/false are accepted)",
+			     bitfield);
 
 		wl_list_insert(ctx->interface->enumeration_list.prev,
 			       &enumeration->link);
@@ -785,32 +785,62 @@ start_element(void *data, const char *element_name, const char **atts)
 	}
 }
 
+static struct enumeration *
+find_enumeration(struct protocol *protocol, struct interface *interface, char *enum_attribute)
+{
+	struct interface *i;
+	struct enumeration *e;
+	char *enum_name;
+	uint idx = 0, j;
+
+	for (j = 0; j + 1 < strlen(enum_attribute); j++) {
+		if (enum_attribute[j] == '.') {
+			idx = j;
+		}
+	}
+
+	if (idx > 0) {
+		enum_name = enum_attribute + idx + 1;
+
+		wl_list_for_each(i, &protocol->interface_list, link)
+			if (strncmp(i->name, enum_attribute, idx) == 0)
+				wl_list_for_each(e, &i->enumeration_list, link)
+					if(strcmp(e->name, enum_name) == 0)
+						return e;
+	} else if (interface) {
+		enum_name = enum_attribute;
+
+		wl_list_for_each(e, &interface->enumeration_list, link)
+			if(strcmp(e->name, enum_name) == 0)
+				return e;
+	}
+
+	return NULL;
+}
+
 static void
-verify_arguments(struct parse_context *ctx, struct wl_list *messages, struct wl_list *enumerations)
+verify_arguments(struct parse_context *ctx, struct interface *interface, struct wl_list *messages, struct wl_list *enumerations)
 {
 	struct message *m;
 	wl_list_for_each(m, messages, link) {
 		struct arg *a;
 		wl_list_for_each(a, &m->arg_list, link) {
-			struct enumeration *e, *f;
+			struct enumeration *e;
 
 			if (!a->enumeration_name)
 				continue;
 
-			f = NULL;
-			wl_list_for_each(e, enumerations, link) {
-				if(strcmp(e->name, a->enumeration_name) == 0)
-					f = e;
-			}
 
-			if (f == NULL)
+			e = find_enumeration(ctx->protocol, interface, a->enumeration_name);
+
+			if (e == NULL)
 				fail(&ctx->loc,
 				     "could not find enumeration %s",
 				     a->enumeration_name);
 
 			switch (a->type) {
 			case INT:
-				if (f->bitfield)
+				if (e->bitfield)
 					fail(&ctx->loc,
 					     "bitfield-style enum must only be referenced by uint");
 				break;
@@ -848,12 +878,13 @@ end_element(void *data, const XML_Char *name)
 			     ctx->enumeration->name);
 		}
 		ctx->enumeration = NULL;
-	} else if (strcmp(name, "interface") == 0) {
-		struct interface *i = ctx->interface;
-
-		verify_arguments(ctx, &i->request_list, &i->enumeration_list);
-		verify_arguments(ctx, &i->event_list, &i->enumeration_list);
+	} else if (strcmp(name, "protocol") == 0) {
+		struct interface *i;
 
+		wl_list_for_each(i, &ctx->protocol->interface_list, link) {
+			verify_arguments(ctx, i, &i->request_list, &i->enumeration_list);
+			verify_arguments(ctx, i, &i->event_list, &i->enumeration_list);
+		}
 	}
 }
 
-- 
2.6.2



More information about the wayland-devel mailing list