Generate client side marshal stubs from protocol spec
authorKristian Høgsberg <krh@bitplanet.net>
Tue, 10 Aug 2010 01:25:50 +0000 (21:25 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 10 Aug 2010 01:25:50 +0000 (21:25 -0400)
TODO
protocol.xml
scanner.c
wayland-client.c
wayland-client.h

diff --git a/TODO b/TODO
index 84fad7c..50d0f4a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -3,8 +3,6 @@ Core wayland protocol
  - generate pointer_focus on raise/lower, move windows, all kinds of
    changes in surface stacking.
 
- - generate marshal stubs as static inline functions.
-
  - don't store globals on client side, require global_handler like
    everything else.
 
index 63927be..be2e79b 100644 (file)
@@ -13,7 +13,7 @@
     <event name="no_memory"/>
 
     <event name="global">
-      <arg name="id" type="new_id"/>
+      <arg name="id" type="new_id" interface="object"/>
       <arg name="name" type="string"/>
       <arg name="version" type="uint"/>
     </event>
@@ -25,7 +25,7 @@
 
   <interface name="compositor" version="1">
     <request name="create_surface">
-      <arg name="id" type="new_id"/>
+      <arg name="id" type="new_id" interface="surface"/>
     </request>
 
     <request name="commit">
     </request>
 
     <request name="create_buffer">
-      <arg name="id" type="new_id"/>
+      <arg name="id" type="new_id" interface="buffer"/>
       <arg name="name" type="uint"/>
       <arg name="width" type="int"/>
       <arg name="height" type="int"/>
       <arg name="stride" type="uint"/>
-      <arg name="visual" type="visual"/>
+      <arg name="visual" type="object" interface="visual"/>
     </request>
 
     <event name="device">
 
   <interface name="shell" version="1">
     <request name="move">
-      <arg name="surface" type="surface"/>
-      <arg name="input_device" type="input_device"/>
+      <arg name="surface" type="object" interface="surface"/>
+      <arg name="input_device" type="object" interface="input_device"/>
       <arg name="time" type="uint"/>
     </request>
 
     <request name="resize">
-      <arg name="surface" type="surface"/>
-      <arg name="input_device" type="input_device"/>
+      <arg name="surface" type="object" interface="surface"/>
+      <arg name="input_device" type="object" interface="input_device"/>
       <arg name="time" type="uint"/>
       <!-- edges is an enum, need to get the values in here -->
       <arg name="edges" type="uint"/>
@@ -88,7 +88,7 @@
       <arg name="time" type="uint"/>
       <!-- Same as edges except also move (16) -->
       <arg name="type" type="uint"/>
-      <arg name="surface" type="surface"/>
+      <arg name="surface" type="object" interface="surface"/>
       <arg name="x" type="int"/>
       <arg name="y" type="int"/>
       <arg name="width" type="int"/>
     <request name="destroy"/>
 
     <request name="attach">
-      <arg name="buffer" type="buffer"/>
+      <arg name="buffer" type="object" interface="buffer"/>
     </request>
 
     <request name="map">
 
     <event name="pointer_focus">
       <arg name="time" type="uint"/>
-      <arg name="surface" type="surface"/>
+      <arg name="surface" type="object" interface="surface"/>
       <arg name="x" type="int"/>
       <arg name="y" type="int"/>
       <arg name="surface_x" type="int"/>
 
     <event name="keyboard_focus">
       <arg name="time" type="uint"/>
-      <arg name="surface" type="surface"/>
+      <arg name="surface" type="object" interface="surface"/>
       <arg name="keys" type="array"/>
     </event>
   </interface>
index 47e13ee..9493f14 100644 (file)
--- a/scanner.c
+++ b/scanner.c
@@ -88,7 +88,7 @@ enum arg_type {
 struct arg {
        char *name;
        enum arg_type type;
-       char *object_name;
+       char *interface_name;
        struct wl_list link;
 };
 
@@ -119,12 +119,13 @@ start_element(void *data, const char *element_name, const char **atts)
        struct interface *interface;
        struct message *message;
        struct arg *arg;
-       const char *name, *type;
+       const char *name, *type, *interface_name;
        int i, version;
 
-       name = 0;
-       type = 0;
+       name = NULL;
+       type = NULL;
        version = 0;
+       interface_name = NULL;
        for (i = 0; atts[i]; i += 2) {
                if (strcmp(atts[i], "name") == 0)
                        name = atts[i + 1];
@@ -132,6 +133,8 @@ start_element(void *data, const char *element_name, const char **atts)
                        version = atoi(atts[i + 1]);
                if (strcmp(atts[i], "type") == 0)
                        type = atts[i + 1];
+               if (strcmp(atts[i], "interface") == 0)
+                       interface_name = atts[i + 1];
        }
 
        if (strcmp(element_name, "interface") == 0) {
@@ -178,9 +181,7 @@ start_element(void *data, const char *element_name, const char **atts)
                arg = malloc(sizeof *arg);
                arg->name = strdup(name);
 
-               if (strcmp(type, "new_id") == 0)
-                       arg->type = NEW_ID;
-               else if (strcmp(type, "int") == 0)
+               if (strcmp(type, "int") == 0)
                        arg->type = INT;
                else if (strcmp(type, "uint") == 0)
                        arg->type = UNSIGNED;
@@ -188,9 +189,23 @@ start_element(void *data, const char *element_name, const char **atts)
                        arg->type = STRING;
                else if (strcmp(type, "array") == 0)
                        arg->type = ARRAY;
-               else {
+               else if (strcmp(type, "new_id") == 0) {
+                       if (interface_name == NULL) {
+                               fprintf(stderr, "no interface name given\n");
+                               exit(EXIT_FAILURE);
+                       }
+                       arg->type = NEW_ID;
+                       arg->interface_name = strdup(interface_name);
+               } else if (strcmp(type, "object") == 0) {
+                       if (interface_name == NULL) {
+                               fprintf(stderr, "no interface name given\n");
+                               exit(EXIT_FAILURE);
+                       }
                        arg->type = OBJECT;
-                       arg->object_name = strdup(type);
+                       arg->interface_name = strdup(interface_name);
+               } else {
+                       fprintf(stderr, "unknown type: %s\n", type);
+                       exit(EXIT_FAILURE);
                }
 
                wl_list_insert(ctx->message->arg_list.prev,
@@ -216,12 +231,105 @@ emit_opcodes(struct wl_list *message_list, struct interface *interface)
 }
 
 static void
+emit_type(struct arg *a)
+{
+       switch (a->type) {
+       default:
+       case INT:
+               printf("int32_t ");
+               break;
+       case NEW_ID:
+       case UNSIGNED:
+               printf("uint32_t ");
+               break;
+       case STRING:
+               printf("const char *");
+               break;
+       case OBJECT:
+               printf("struct wl_%s *", a->interface_name);
+               break;
+       case ARRAY:
+               printf("struct wl_array *");
+               break;
+       }
+}
+
+static void
+emit_stubs(struct wl_list *message_list, struct interface *interface)
+{
+       struct message *m;
+       struct arg *a, *ret;
+
+       if (wl_list_empty(message_list))
+               return;
+
+       wl_list_for_each(m, message_list, link) {
+               ret = NULL;
+               wl_list_for_each(a, &m->arg_list, link) {
+                       if (a->type == NEW_ID)
+                               ret = a;
+               }
+
+               if (ret)
+                       printf("static inline struct wl_%s *\n",
+                              ret->interface_name);
+               else
+                       printf("static inline void\n");
+
+               printf("wl_%s_%s(struct wl_%s *%s",
+                      interface->name, m->name,
+                      interface->name, interface->name);
+
+               wl_list_for_each(a, &m->arg_list, link) {
+                       if (a->type == NEW_ID)
+                               continue;
+                       printf(", ");
+                       emit_type(a);
+                       printf("%s", a->name);
+               }
+
+               printf(")\n"
+                      "{\n");
+               if (ret)
+                       printf("\tstruct wl_proxy *%s;\n\n"
+                              "\t%s = wl_proxy_create("
+                              "(struct wl_proxy *) %s, &wl_%s_interface);\n"
+                              "\tif (!%s)\n"
+                              "\t\treturn NULL;\n\n",
+                              ret->name,
+                              ret->name,
+                              interface->name, ret->interface_name,
+                              ret->name);
+
+               printf("\twl_proxy_marshal((struct wl_proxy *) %s, WL_%s_%s",
+                      interface->name,
+                      interface->uppercase_name,
+                      m->uppercase_name);
+
+               wl_list_for_each(a, &m->arg_list, link) {
+                       printf(", ");
+                               printf("%s", a->name);
+               }
+               printf(");\n");
+
+               if (ret)
+                       printf("\n\treturn (struct wl_%s *) %s;\n",
+                              ret->interface_name, ret->name);
+
+               printf("}\n\n");
+       }
+}
+
+static void
 emit_structs(struct wl_list *message_list, struct interface *interface)
 {
        struct message *m;
        struct arg *a;
        int is_interface;
 
+       if (wl_list_empty(message_list))
+               return;
+
        is_interface = message_list == &interface->request_list;
        printf("struct wl_%s_%s {\n", interface->name,
               is_interface ? "interface" : "listener");
@@ -241,25 +349,7 @@ emit_structs(struct wl_list *message_list, struct interface *interface)
                        printf(", ");
 
                wl_list_for_each(a, &m->arg_list, link) {
-                       switch (a->type) {
-                       default:
-                       case INT:
-                               printf("int32_t ");
-                               break;
-                       case NEW_ID:
-                       case UNSIGNED:
-                               printf("uint32_t ");
-                               break;
-                       case STRING:
-                               printf("const char *");
-                               break;
-                       case OBJECT:
-                               printf("struct wl_%s *", a->object_name);
-                               break;
-                       case ARRAY:
-                               printf("struct wl_array *");
-                               break;
-                       }
+                       emit_type(a);
                        printf("%s%s",
                               a->name,
                               a->link.next == &m->arg_list ? "" : ", ");
@@ -292,6 +382,22 @@ emit_header(struct protocol *protocol, int server)
                printf("struct wl_%s;\n", i->name);
        printf("\n");
 
+       if (!server)
+               printf("struct wl_proxy;\n\n"
+                      "extern void\n"
+                      "wl_proxy_marshal(struct wl_proxy *p, "
+                      "uint32_t opcode, ...);\n"
+                      "extern struct wl_proxy *\n"
+                      "wl_proxy_create(struct wl_proxy *factory, "
+                      "const struct wl_interface *interface);\n\n");
+
+       wl_list_for_each(i, &protocol->interface_list, link) {
+               printf("extern const struct wl_interface "
+                      "wl_%s_interface;\n",
+                      i->name);
+       }
+       printf("\n");
+
        wl_list_for_each(i, &protocol->interface_list, link) {
 
                if (server) {
@@ -300,11 +406,8 @@ emit_header(struct protocol *protocol, int server)
                } else {
                        emit_structs(&i->event_list, i);
                        emit_opcodes(&i->request_list, i);
+                       emit_stubs(&i->request_list, i);
                }
-
-               printf("extern const struct wl_interface "
-                      "wl_%s_interface;\n\n",
-                      i->name);
        }
 
        printf("#ifdef  __cplusplus\n"
index 8fcc809..f2cf7a0 100644 (file)
@@ -202,6 +202,23 @@ wl_proxy_create_for_global(struct wl_display *display,
        return proxy;
 }
 
+WL_EXPORT struct wl_proxy *
+wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
+{
+       struct wl_proxy *proxy;
+
+       proxy = malloc(sizeof *proxy);
+       if (proxy == NULL)
+               return NULL;
+
+       proxy->base.interface = interface;
+       proxy->base.id = wl_display_allocate_id(factory->display);
+       proxy->display = factory->display;
+       wl_hash_table_insert(factory->display->objects, proxy->base.id, proxy);
+
+       return proxy;
+}
+
 static int
 wl_proxy_add_listener(struct wl_proxy *proxy, void (**implementation)(void), void *data)
 {
@@ -218,7 +235,7 @@ wl_proxy_add_listener(struct wl_proxy *proxy, void (**implementation)(void), voi
        return 0;
 }
 
-static void
+WL_EXPORT void
 wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
 {
        va_list ap;
@@ -248,24 +265,6 @@ wl_shell_add_listener(struct wl_shell *shell,
                                     (void (**)(void)) listener, data);
 }
 
-WL_EXPORT void
-wl_shell_move(struct wl_shell *shell,
-             struct wl_surface *surface, struct wl_input_device *device,
-             uint32_t time)
-{
-       wl_proxy_marshal(&shell->proxy,
-                        WL_SHELL_MOVE, surface, device, time);
-}
-
-WL_EXPORT void
-wl_shell_resize(struct wl_shell *shell,
-               struct wl_surface *surface, struct wl_input_device *device,
-               uint32_t time, uint32_t edges)
-{
-       wl_proxy_marshal(&shell->proxy,
-                        WL_SHELL_RESIZE, surface, device, time, edges);
-}
-
 WL_EXPORT int
 wl_drm_add_listener(struct wl_drm *drm,
                    const struct wl_drm_listener *listener,
@@ -275,40 +274,6 @@ wl_drm_add_listener(struct wl_drm *drm,
                                     (void (**)(void)) listener, data);
 }
 
-WL_EXPORT void
-wl_drm_authenticate(struct wl_drm *drm, uint32_t id)
-{
-       wl_proxy_marshal(&drm->proxy, WL_DRM_AUTHENTICATE, id);
-}
-
-WL_EXPORT struct wl_buffer *
-wl_drm_create_buffer(struct wl_drm *drm, uint32_t name,
-                    int32_t width, int32_t height,
-                    uint32_t stride, struct wl_visual *visual)
-{
-       struct wl_buffer *buffer;
-
-       buffer = malloc(sizeof *buffer);
-       if (buffer == NULL)
-               return NULL;
-
-       buffer->proxy.base.interface = &wl_buffer_interface;
-       buffer->proxy.base.id = wl_display_allocate_id(drm->proxy.display);
-       buffer->proxy.display = drm->proxy.display;
-       wl_hash_table_insert(drm->proxy.display->objects,
-                            drm->proxy.base.id, buffer);
-       wl_proxy_marshal(&drm->proxy, WL_DRM_CREATE_BUFFER,
-                        buffer, name, width, height, stride, visual);
-
-       return buffer;
-}
-
-WL_EXPORT void
-wl_buffer_destroy(struct wl_buffer *buffer)
-{
-       wl_proxy_marshal(&buffer->proxy, WL_BUFFER_DESTROY);
-}
-
 static void
 add_visual(struct wl_display *display, struct wl_global *global)
 {
@@ -610,60 +575,6 @@ wl_compositor_add_listener(struct wl_compositor *compositor,
                                     (void (**)(void)) listener, data);
 }
 
-WL_EXPORT struct wl_surface *
-wl_compositor_create_surface(struct wl_compositor *compositor)
-{
-       struct wl_surface *surface;
-
-       surface = malloc(sizeof *surface);
-       if (surface == NULL)
-               return NULL;
-
-       surface->proxy.base.interface = &wl_surface_interface;
-       surface->proxy.base.id = wl_display_allocate_id(compositor->proxy.display);
-       surface->proxy.display = compositor->proxy.display;
-       wl_hash_table_insert(compositor->proxy.display->objects,
-                            surface->proxy.base.id, surface);
-       wl_proxy_marshal(&compositor->proxy,
-                         WL_COMPOSITOR_CREATE_SURFACE, surface);
-
-       return surface;
-}
-
-WL_EXPORT void
-wl_compositor_commit(struct wl_compositor *compositor, uint32_t key)
-{
-       wl_proxy_marshal(&compositor->proxy, WL_COMPOSITOR_COMMIT, key);
-}
-
-WL_EXPORT void
-wl_surface_destroy(struct wl_surface *surface)
-{
-       wl_proxy_marshal(&surface->proxy, WL_SURFACE_DESTROY);
-}
-
-WL_EXPORT void
-wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
-{
-       wl_proxy_marshal(&surface->proxy, WL_SURFACE_ATTACH, buffer);
-}
-
-WL_EXPORT void
-wl_surface_map(struct wl_surface *surface,
-              int32_t x, int32_t y, int32_t width, int32_t height)
-{
-       wl_proxy_marshal(&surface->proxy,
-                        WL_SURFACE_MAP, x, y, width, height);
-}
-
-WL_EXPORT void
-wl_surface_damage(struct wl_surface *surface,
-                 int32_t x, int32_t y, int32_t width, int32_t height)
-{
-       wl_proxy_marshal(&surface->proxy,
-                        WL_SURFACE_DAMAGE, x, y, width, height);
-}
-
 WL_EXPORT void
 wl_surface_set_user_data(struct wl_surface *surface, void *user_data)
 {
index 572adc0..ec6a3ca 100644 (file)
@@ -66,10 +66,6 @@ wl_display_get_premultiplied_argb_visual(struct wl_display *display);
 struct wl_visual *
 wl_display_get_rgb_visual(struct wl_display *display);
 
-struct wl_surface *
-wl_compositor_create_surface(struct wl_compositor *compositor);
-void
-wl_compositor_commit(struct wl_compositor *compositor, uint32_t key);
 int
 wl_compositor_add_listener(struct wl_compositor *compostior,
                           const struct wl_compositor_listener *listener,
@@ -79,33 +75,10 @@ int
 wl_shell_add_listener(struct wl_shell *shell,
                      const struct wl_shell_listener *listener,
                      void *data);
-void
-wl_shell_move(struct wl_shell *shell,
-             struct wl_surface *surface, struct wl_input_device *device,
-             uint32_t time);
-void
-wl_shell_resize(struct wl_shell *shell,
-               struct wl_surface *surface, struct wl_input_device *device,
-               uint32_t time, uint32_t edges);
-
 int
 wl_drm_add_listener(struct wl_drm *drm,
                    const struct wl_drm_listener *listener,
                    void *data);
-void
-wl_drm_authenticate(struct wl_drm *drm, uint32_t id);
-struct wl_buffer *
-wl_drm_create_buffer(struct wl_drm *drm, uint32_t name,
-                    int32_t width, int32_t height,
-                    uint32_t stride, struct wl_visual *visual);
-void wl_buffer_destroy(struct wl_buffer *buffer);
-
-void wl_surface_destroy(struct wl_surface *surface);
-void wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer);
-void wl_surface_map(struct wl_surface *surface,
-                   int32_t x, int32_t y, int32_t width, int32_t height);
-void wl_surface_damage(struct wl_surface *surface,
-                      int32_t x, int32_t y, int32_t width, int32_t height);
 
 void wl_surface_set_user_data(struct wl_surface *surface, void *user_data);
 void *wl_surface_get_user_data(struct wl_surface *surface);