Move protocol metadata to wayland-protocol.[ch].

This lets us share the metadata between server and client and we
can now use a va_arg marshalling function for sending client
requets.
diff --git a/Makefile.in b/Makefile.in
index 0f269a3..5910911 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -13,7 +13,8 @@
 	wayland.o				\
 	event-loop.o				\
 	connection.o				\
-	wayland-util.o
+	wayland-util.o				\
+	wayland-protocol.o
 
 libwayland-server.so : CFLAGS += @FFI_CFLAGS@
 libwayland-server.so : LDLIBS += @FFI_LIBS@ -ldl -rdynamic
@@ -21,7 +22,8 @@
 libwayland.so :					\
 	wayland-client.o			\
 	connection.o				\
-	wayland-util.o
+	wayland-util.o				\
+	wayland-protocol.o
 
 $(libs) : CFLAGS += -fPIC
 $(libs) :
diff --git a/connection.c b/connection.c
index 9d63f82..5430963 100644
--- a/connection.c
+++ b/connection.c
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <sys/uio.h>
 
+#include "wayland-util.h"
 #include "connection.h"
 
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
diff --git a/connection.h b/connection.h
index a9a0d71..68d6396 100644
--- a/connection.h
+++ b/connection.h
@@ -23,6 +23,8 @@
 #ifndef _CONNECTION_H_
 #define _CONNECTION_H_
 
+#include <stdarg.h>
+
 struct wl_connection;
 
 #define WL_CONNECTION_READABLE 0x01
@@ -39,5 +41,7 @@
 void wl_connection_consume(struct wl_connection *connection, size_t size);
 int wl_connection_data(struct wl_connection *connection, uint32_t mask);
 void wl_connection_write(struct wl_connection *connection, const void *data, size_t count);
+void wl_connection_vmarshal(struct wl_connection *connection, uint32_t id,
+			    uint32_t opcode, const char *signature, va_list ap);
 
 #endif
diff --git a/wayland-client.c b/wayland-client.c
index d6471ac..a898fd2 100644
--- a/wayland-client.c
+++ b/wayland-client.c
@@ -30,8 +30,10 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <ctype.h>
+#include <assert.h>
 #include <sys/poll.h>
 
+#include "wayland-protocol.h"
 #include "connection.h"
 #include "wayland-util.h"
 #include "wayland-client.h"
@@ -46,8 +48,9 @@
 };
 
 struct wl_proxy {
-	struct wl_display *display;
+	const struct wl_interface *interface;
 	uint32_t id;
+	struct wl_display *display;
 };
 
 struct wl_display {
@@ -166,8 +169,9 @@
 	wl_list_init(&display->global_list);
 	wl_list_init(&display->visual_list);
 
-	display->proxy.display = display;
+	display->proxy.interface = &wl_display_interface;
 	display->proxy.id = wl_display_get_object_id(display, "display");
+	display->proxy.display = display;
 
 	display->connection = wl_connection_create(display->fd,
 						   connection_update,
@@ -217,11 +221,6 @@
 	return display->fd;
 }
 
-#define WL_DISPLAY_INVALID_OBJECT 0
-#define WL_DISPLAY_INVALID_METHOD 1
-#define WL_DISPLAY_NO_MEMORY 2
-#define WL_DISPLAY_GLOBAL 3
-
 static void
 handle_global(struct wl_display *display, uint32_t *p, uint32_t size)
 {
@@ -324,33 +323,80 @@
 		return NULL;
 
 	compositor = malloc(sizeof *compositor);
-	compositor->proxy.display = display;
+	compositor->proxy.interface = &wl_compositor_interface;
 	compositor->proxy.id = id;
+	compositor->proxy.display = display;
 
 	return compositor;
 }
 
-#define WL_COMPOSITOR_CREATE_SURFACE	0
-#define WL_COMPOSITOR_COMMIT		1
+static void
+wl_proxy_vmarshal(struct wl_proxy *target, uint32_t opcode, va_list ap)
+{
+	struct wl_proxy *proxy;
+	uint32_t args[32], length, *p, size;
+	const char *s, *signature;
+	int i, count;
+
+	signature = target->interface->methods[opcode].signature;
+	count = strlen(signature);
+	/* FIXME: Make sure we don't overwrite args array. */
+
+	p = &args[2];
+	for (i = 0; i < count; i++) {
+		switch (signature[i]) {
+		case 'u':
+		case 'i':
+			*p++ = va_arg(ap, uint32_t);
+			break;
+		case 's':
+			s = va_arg(ap, const char *);
+			length = strlen(s);
+			*p++ = length;
+			memcpy(p, s, length);
+			p += DIV_ROUNDUP(length, sizeof(*p));
+			break;
+		case 'n':
+		case 'o':
+			proxy = va_arg(ap, struct wl_proxy *);
+			*p++ = proxy->id;
+			break;
+		default:
+			assert(0);
+			break;
+		}
+	}
+
+	size = (p - args) * sizeof *p;
+	args[0] = target->id;
+	args[1] = opcode | (size << 16);
+	wl_connection_write(target->display->connection, args, size);
+}
+
+static void
+wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
+{
+	va_list ap;
+
+	va_start(ap, opcode);
+	wl_proxy_vmarshal(proxy, opcode, ap);
+	va_end(ap);
+}
 
 WL_EXPORT struct wl_surface *
 wl_compositor_create_surface(struct wl_compositor *compositor)
 {
 	struct wl_surface *surface;
-	uint32_t request[3];
 
 	surface = malloc(sizeof *surface);
 	if (surface == NULL)
 		return NULL;
 
+	surface->proxy.interface = &wl_surface_interface;
 	surface->proxy.id = wl_display_allocate_id(compositor->proxy.display);
 	surface->proxy.display = compositor->proxy.display;
-
-	request[0] = compositor->proxy.id;
-	request[1] = WL_COMPOSITOR_CREATE_SURFACE | ((sizeof request) << 16);
-	request[2] = surface->proxy.id;
-	wl_connection_write(compositor->proxy.display->connection,
-			    request, sizeof request);
+	wl_proxy_marshal(&compositor->proxy,
+			  WL_COMPOSITOR_CREATE_SURFACE, surface);
 
 	return surface;
 }
@@ -358,31 +404,13 @@
 WL_EXPORT void
 wl_compositor_commit(struct wl_compositor *compositor, uint32_t key)
 {
-	uint32_t request[3];
-
-	request[0] = compositor->proxy.id;
-	request[1] = WL_COMPOSITOR_COMMIT | ((sizeof request) << 16);
-	request[2] = key;
-	wl_connection_write(compositor->proxy.display->connection,
-			    request, sizeof request);
+	wl_proxy_marshal(&compositor->proxy, WL_COMPOSITOR_COMMIT, key);
 }
 
-#define WL_SURFACE_DESTROY	0
-#define WL_SURFACE_ATTACH	1
-#define WL_SURFACE_MAP		2
-#define WL_SURFACE_COPY		3
-#define WL_SURFACE_DAMAGE	4
-
 WL_EXPORT void
 wl_surface_destroy(struct wl_surface *surface)
 {
-	uint32_t request[2];
-
-	request[0] = surface->proxy.id;
-	request[1] = WL_SURFACE_DESTROY | ((sizeof request) << 16);
-
-	wl_connection_write(surface->proxy.display->connection,
-			    request, sizeof request);
+	wl_proxy_marshal(&surface->proxy, WL_SURFACE_DESTROY);
 }
 
 WL_EXPORT void
@@ -390,35 +418,16 @@
 		  int32_t width, int32_t height, uint32_t stride,
 		  struct wl_visual *visual)
 {
-	uint32_t request[7];
-
-	request[0] = surface->proxy.id;
-	request[1] = WL_SURFACE_ATTACH | ((sizeof request) << 16);
-	request[2] = name;
-	request[3] = width;
-	request[4] = height;
-	request[5] = stride;
-	request[6] = visual->proxy.id;
-
-	wl_connection_write(surface->proxy.display->connection,
-			    request, sizeof request);
+	wl_proxy_marshal(&surface->proxy, WL_SURFACE_ATTACH,
+			 name, width, height, stride, visual);
 }
 
 WL_EXPORT void
 wl_surface_map(struct wl_surface *surface,
 	       int32_t x, int32_t y, int32_t width, int32_t height)
 {
-	uint32_t request[6];
-
-	request[0] = surface->proxy.id;
-	request[1] = WL_SURFACE_MAP | ((sizeof request) << 16);
-	request[2] = x;
-	request[3] = y;
-	request[4] = width;
-	request[5] = height;
-
-	wl_connection_write(surface->proxy.display->connection,
-			    request, sizeof request);
+	wl_proxy_marshal(&surface->proxy,
+			 WL_SURFACE_MAP, x, y, width, height);
 }
 
 WL_EXPORT void
@@ -426,36 +435,14 @@
 		uint32_t name, uint32_t stride,
 		int32_t x, int32_t y, int32_t width, int32_t height)
 {
-	uint32_t request[10];
-
-	request[0] = surface->proxy.id;
-	request[1] = WL_SURFACE_COPY | ((sizeof request) << 16);
-	request[2] = dst_x;
-	request[3] = dst_y;
-	request[4] = name;
-	request[5] = stride;
-	request[6] = x;
-	request[7] = y;
-	request[8] = width;
-	request[9] = height;
-
-	wl_connection_write(surface->proxy.display->connection,
-			    request, sizeof request);
+	wl_proxy_marshal(&surface->proxy, WL_SURFACE_COPY,
+			 dst_x, dst_y, name, stride, 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)
 {
-	uint32_t request[6];
-
-	request[0] = surface->proxy.id;
-	request[1] = WL_SURFACE_DAMAGE | ((sizeof request) << 16);
-	request[2] = x;
-	request[3] = y;
-	request[4] = width;
-	request[5] = height;
-
-	wl_connection_write(surface->proxy.display->connection,
-			    request, sizeof request);
+	wl_proxy_marshal(&surface->proxy,
+			 WL_SURFACE_DAMAGE, x, y, width, height);
 }
diff --git a/wayland-protocol.c b/wayland-protocol.c
new file mode 100644
index 0000000..3af3c62
--- /dev/null
+++ b/wayland-protocol.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+#include "wayland-protocol.h"
+
+static const struct wl_event display_events[] = {
+	{ "invalid_object", "u" },
+	{ "invalid_method", "uu" },
+	{ "no_memory", "" },
+	{ "global", "osu" },
+};
+
+WL_EXPORT const struct wl_interface wl_display_interface = {
+	"display", 1,
+	0, NULL,
+	ARRAY_LENGTH(display_events), display_events,
+};
+
+
+static const struct wl_method compositor_methods[] = {
+	{ "create_surface", "n" },
+	{ "commit", "u" }
+};
+
+static const struct wl_event compositor_events[] = {
+	{ "acknowledge", "uu" },
+	{ "frame", "uu" }
+};
+
+WL_EXPORT const struct wl_interface wl_compositor_interface = {
+	"compositor", 1,
+	ARRAY_LENGTH(compositor_methods), compositor_methods,
+	ARRAY_LENGTH(compositor_events), compositor_events,
+};
+
+
+static const struct wl_method surface_methods[] = {
+	{ "destroy", "" },
+	{ "attach", "uuuuo" },
+	{ "map", "iiii" },
+	{ "copy", "iiuuiiii" },
+	{ "damage", "iiii" }
+};
+
+WL_EXPORT const struct wl_interface wl_surface_interface = {
+	"surface", 1,
+	ARRAY_LENGTH(surface_methods), surface_methods,
+	0, NULL,
+};
+
+
+static const struct wl_event input_device_events[] = {
+	{ "motion", "iiii" },
+	{ "button", "uuiiii" },
+	{ "key", "uu" },
+};
+
+WL_EXPORT const struct wl_interface wl_input_device_interface = {
+	"input_device", 1,
+	0, NULL,
+	ARRAY_LENGTH(input_device_events), input_device_events,
+};
diff --git a/wayland-protocol.h b/wayland-protocol.h
new file mode 100644
index 0000000..a5c97c0
--- /dev/null
+++ b/wayland-protocol.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef WAYLAND_PROTOCOL_H
+#define WAYLAND_PROTOCOL_H
+
+#include <stdint.h>
+
+struct wl_argument {
+	uint32_t type;
+	void *data;
+};
+
+struct wl_method {
+	const char *name;
+	const char *signature;
+	const void **types;
+};
+
+struct wl_event {
+	const char *name;
+	const char *signature;
+};
+
+struct wl_interface {
+	const char *name;
+	int version;
+	int method_count;
+	const struct wl_method *methods;
+	int event_count;
+	const struct wl_event *events;
+};
+
+#define WL_DISPLAY_INVALID_OBJECT	0
+#define WL_DISPLAY_INVALID_METHOD	1
+#define WL_DISPLAY_NO_MEMORY		2
+#define WL_DISPLAY_GLOBAL		3
+
+extern const struct wl_interface wl_display_interface;
+
+
+#define WL_COMPOSITOR_CREATE_SURFACE	0
+#define WL_COMPOSITOR_COMMIT		1
+
+#define WL_COMPOSITOR_ACKNOWLEDGE	0
+#define WL_COMPOSITOR_FRAME		1
+
+extern const struct wl_interface wl_compositor_interface;
+
+
+#define WL_SURFACE_DESTROY	0
+#define WL_SURFACE_ATTACH	1
+#define WL_SURFACE_MAP		2
+#define WL_SURFACE_COPY		3
+#define WL_SURFACE_DAMAGE	4
+
+extern const struct wl_interface wl_surface_interface;
+
+
+#define WL_INPUT_MOTION	0
+#define WL_INPUT_BUTTON	1
+#define WL_INPUT_KEY	2
+
+extern const struct wl_interface wl_input_device_interface;
+
+#endif
diff --git a/wayland-system-compositor.c b/wayland-system-compositor.c
index ef4dca2..073386f 100644
--- a/wayland-system-compositor.c
+++ b/wayland-system-compositor.c
@@ -46,6 +46,7 @@
 #include <eagle.h>
 
 #include "wayland.h"
+#include "wayland-protocol.h"
 #include "cairo-util.h"
 #include "wayland-system-compositor.h"
 
@@ -695,12 +696,12 @@
 		return;
 
 	memset(device, 0, sizeof *device);
-	device->base.interface = wl_input_device_get_interface();
+	device->base.interface = &wl_input_device_interface;
 	wl_display_add_object(ec->wl_display, &device->base);
 	device->x = 100;
 	device->y = 100;
-	device->pointer_surface = pointer_create(ec,
-						 device->x, device->y, 64, 64);
+	device->pointer_surface =
+		pointer_create(ec, device->x, device->y, 64, 64);
 	device->ec = ec;
 
 	dir = opendir(by_path_dir);
@@ -947,6 +948,8 @@
 		wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, ec);
 	ec->enter_vt_source =
 		wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, ec);
+
+	return 0;
 }
 
 static struct egl_compositor *
diff --git a/wayland.c b/wayland.c
index fe5f9db..45b4fae 100644
--- a/wayland.c
+++ b/wayland.c
@@ -34,6 +34,7 @@
 #include <assert.h>
 #include <ffi.h>
 
+#include "wayland-protocol.h"
 #include "wayland.h"
 #include "connection.h"
 
@@ -203,11 +204,6 @@
 	ffi_call(&cif, func, &result, args);
 }
 
-#define WL_DISPLAY_INVALID_OBJECT 0
-#define WL_DISPLAY_INVALID_METHOD 1
-#define WL_DISPLAY_NO_MEMORY 2
-#define WL_DISPLAY_GLOBAL 3
-
 static void
 wl_client_connection_data(int fd, uint32_t mask, void *data)
 {
@@ -348,20 +344,6 @@
 	free(client);
 }
 
-static const struct wl_method surface_methods[] = {
-	{ "destroy", "" },
-	{ "attach", "uuuuo" },
-	{ "map", "iiii" },
-	{ "copy", "iiuuiiii" },
-	{ "damage", "iiii" }
-};
-
-static const struct wl_interface surface_interface = {
-	"surface", 1,
-	ARRAY_LENGTH(surface_methods),
-	surface_methods,
-};
-
 WL_EXPORT int
 wl_client_add_surface(struct wl_client *client,
 		      struct wl_surface *surface,
@@ -372,7 +354,7 @@
 	struct wl_object_ref *ref;
 
 	surface->base.id = id;
-	surface->base.interface = &surface_interface;
+	surface->base.interface = &wl_surface_interface;
 	surface->base.implementation = (void (**)(void)) implementation;
 	surface->client = client;
 
@@ -390,9 +372,6 @@
 	return 0;
 }
 
-#define WL_COMPOSITOR_ACKNOWLEDGE 0
-#define WL_COMPOSITOR_FRAME 1
-
 WL_EXPORT void
 wl_client_send_acknowledge(struct wl_client *client,
 			   struct wl_compositor *compositor,
@@ -405,28 +384,12 @@
 			  WL_COMPOSITOR_ACKNOWLEDGE, key, frame);
 }
 
-static const struct wl_method compositor_methods[] = {
-	{ "create_surface", "n" },
-	{ "commit", "u" }
-};
-
-static const struct wl_event compositor_events[] = {
-	{ "acknowledge", "uu" },
-	{ "frame", "uu" }
-};
-
-static const struct wl_interface compositor_interface = {
-	"compositor", 1,
-	ARRAY_LENGTH(compositor_methods), compositor_methods,
-	ARRAY_LENGTH(compositor_events), compositor_events,
-};
-
 WL_EXPORT int
 wl_display_set_compositor(struct wl_display *display,
 			  struct wl_compositor *compositor,
 			  const struct wl_compositor_interface *implementation)
 {
-	compositor->base.interface = &compositor_interface;
+	compositor->base.interface = &wl_compositor_interface;
 	compositor->base.implementation = (void (**)(void)) implementation;
 
 	wl_display_add_object(display, &compositor->base);
@@ -436,19 +399,6 @@
 	return 0;
 }
 
-static const struct wl_event display_events[] = {
-	{ "invalid_object", "u" },
-	{ "invalid_method", "uu" },
-	{ "no_memory", "" },
-	{ "global", "osu" },
-};
-
-static const struct wl_interface display_interface = {
-	"display", 1,
-	0, NULL,
-	ARRAY_LENGTH(display_events), display_events,
-};
-
 WL_EXPORT struct wl_display *
 wl_display_create(void)
 {
@@ -476,7 +426,7 @@
 	display->client_id_range = 256; /* Gah, arbitrary... */
 
 	display->id = 1;
-	display->base.interface = &display_interface;
+	display->base.interface = &wl_display_interface;
 	display->base.implementation = NULL;
 	wl_display_add_object(display, &display->base);
 	if (wl_display_add_global(display, &display->base)) {
@@ -522,34 +472,6 @@
 	va_end(ap);
 }
 
-struct wl_input_device {
-	struct wl_object base;
-	struct wl_display *display;
-};
-
-static const struct wl_method input_device_methods[] = {
-};
-
-static const struct wl_event input_device_events[] = {
-	{ "motion", "iiii" },
-	{ "button", "uuiiii" },
-	{ "key", "uu" },
-};
-
-static const struct wl_interface input_device_interface = {
-	"input_device", 1,
-	ARRAY_LENGTH(input_device_methods),
-	input_device_methods,
-	ARRAY_LENGTH(input_device_events),
-	input_device_events,
-};
-
-WL_EXPORT const struct wl_interface *
-wl_input_device_get_interface(void)
-{
-	return &input_device_interface;
-}
-
 WL_EXPORT void
 wl_display_post_frame(struct wl_display *display,
 		      struct wl_compositor *compositor,
diff --git a/wayland.h b/wayland.h
index ecf0c7e..ff43572 100644
--- a/wayland.h
+++ b/wayland.h
@@ -66,38 +66,6 @@
 
 struct wl_client;
 
-enum {
-	WL_ARGUMENT_UINT32,
-	WL_ARGUMENT_STRING,
-	WL_ARGUMENT_OBJECT,
-	WL_ARGUMENT_NEW_ID
-};
-
-struct wl_argument {
-	uint32_t type;
-	void *data;
-};
-
-struct wl_method {
-	const char *name;
-	const char *signature;
-	const void **types;
-};
-
-struct wl_event {
-	const char *name;
-	const char *signature;
-};
-
-struct wl_interface {
-	const char *name;
-	int version;
-	int method_count;
-	const struct wl_method *methods;
-	int event_count;
-	const struct wl_event *events;
-};
-
 struct wl_object {
 	const struct wl_interface *interface;
 	void (**implementation)(void);
@@ -116,17 +84,8 @@
 int wl_display_add_socket(struct wl_display *display, const char *name, size_t name_size);
 void wl_display_run(struct wl_display *display);
 
-void
-wl_display_add_object(struct wl_display *display, struct wl_object *object);
-int
-wl_display_add_global(struct wl_display *display, struct wl_object *object);
-
-const struct wl_interface *
-wl_input_device_get_interface(void);
-
-#define WL_INPUT_MOTION 0
-#define WL_INPUT_BUTTON 1
-#define WL_INPUT_KEY 2
+void wl_display_add_object(struct wl_display *display, struct wl_object *object);
+int wl_display_add_global(struct wl_display *display, struct wl_object *object);
 
 struct wl_compositor {
 	struct wl_object base;