protocol: add support for cross-interface enum attributes
authorAuke Booij <auke@tulcod.com>
Sat, 5 Dec 2015 12:39:12 +0000 (12:39 +0000)
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>
Tue, 3 May 2016 11:54:11 +0000 (14:54 +0300)
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@tulcod.com>
Reviewed-by: Nils Christopher Brause <nilschrbrause@googlemail.com>
Reviewed-by: Bill Spitzak <spitzak@gmail.com>
[Pekka: rebased across cde251a124d41977b447098cc530fcad2834a45f]
[Pekka: wrap lines and space fixes in scanner.c]
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
doc/publican/protocol-to-docbook.xsl
protocol/wayland.xml
src/scanner.c

index 5344442..210e0db 100644 (file)
     <term><xsl:value-of select="@name"/></term>
     <listitem>
         <simpara>
-          <link linkend="protocol-spec-{../../@name}-enum-{@enum}">
-            <xsl:value-of select="../../@name"/>::<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:value-of select="@type"/>)
           <xsl:if test="@summary" >
             - <xsl:value-of select="@summary"/>
index 1555677..92e3f43 100644 (file)
       <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">
        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 -->
index 52c07a6..1317a06 100644 (file)
@@ -752,8 +752,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);
@@ -790,32 +790,68 @@ 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;
@@ -853,12 +889,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);
+               }
        }
 }