2 * Copyright © 2010 Intel Corporation
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include "wayland-util.h"
27 static const char copyright[] =
29 " * Copyright © 2010 Kristian Høgsberg\n"
31 " * Permission to use, copy, modify, distribute, and sell this software and its\n"
32 " * documentation for any purpose is hereby granted without fee, provided that\n"
33 " * the above copyright notice appear in all copies and that both that copyright\n"
34 " * notice and this permission notice appear in supporting documentation, and\n"
35 " * that the name of the copyright holders not be used in advertising or\n"
36 " * publicity pertaining to distribution of the software without specific,\n"
37 " * written prior permission. The copyright holders make no representations\n"
38 " * about the suitability of this software for any purpose. It is provided \"as\n"
39 " * is\" without express or implied warranty.\n"
41 " * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,\n"
42 " * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO\n"
43 " * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR\n"
44 " * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,\n"
45 " * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n"
46 " * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE\n"
47 " * OF THIS SOFTWARE.\n"
53 fprintf(stderr, "usage: ./scanner [header|code]\n");
57 #define XML_BUFFER_SIZE 4096
60 struct wl_list interface_list;
67 struct wl_list request_list;
68 struct wl_list event_list;
75 struct wl_list arg_list;
95 struct parse_context {
96 struct protocol *protocol;
97 struct interface *interface;
98 struct message *message;
102 uppercase_dup(const char *src)
108 for (i = 0; u[i]; i++)
109 u[i] = toupper(u[i]);
116 start_element(void *data, const char *element_name, const char **atts)
118 struct parse_context *ctx = data;
119 struct interface *interface;
120 struct message *message;
122 const char *name, *type, *interface_name;
128 interface_name = NULL;
129 for (i = 0; atts[i]; i += 2) {
130 if (strcmp(atts[i], "name") == 0)
132 if (strcmp(atts[i], "version") == 0)
133 version = atoi(atts[i + 1]);
134 if (strcmp(atts[i], "type") == 0)
136 if (strcmp(atts[i], "interface") == 0)
137 interface_name = atts[i + 1];
140 if (strcmp(element_name, "interface") == 0) {
142 fprintf(stderr, "no interface name given\n");
147 fprintf(stderr, "no interface version given\n");
151 interface = malloc(sizeof *interface);
152 interface->name = strdup(name);
153 interface->uppercase_name = uppercase_dup(name);
154 interface->version = version;
155 wl_list_init(&interface->request_list);
156 wl_list_init(&interface->event_list);
157 wl_list_insert(ctx->protocol->interface_list.prev,
159 ctx->interface = interface;
160 } else if (strcmp(element_name, "request") == 0 ||
161 strcmp(element_name, "event") == 0) {
163 fprintf(stderr, "no request name given\n");
167 message = malloc(sizeof *message);
168 message->name = strdup(name);
169 message->uppercase_name = uppercase_dup(name);
170 wl_list_init(&message->arg_list);
172 if (strcmp(element_name, "request") == 0)
173 wl_list_insert(ctx->interface->request_list.prev,
176 wl_list_insert(ctx->interface->event_list.prev,
179 ctx->message = message;
180 } else if (strcmp(element_name, "arg") == 0) {
181 arg = malloc(sizeof *arg);
182 arg->name = strdup(name);
184 if (strcmp(type, "int") == 0)
186 else if (strcmp(type, "uint") == 0)
187 arg->type = UNSIGNED;
188 else if (strcmp(type, "string") == 0)
190 else if (strcmp(type, "array") == 0)
192 else if (strcmp(type, "new_id") == 0) {
193 if (interface_name == NULL) {
194 fprintf(stderr, "no interface name given\n");
198 arg->interface_name = strdup(interface_name);
199 } else if (strcmp(type, "object") == 0) {
200 if (interface_name == NULL) {
201 fprintf(stderr, "no interface name given\n");
205 arg->interface_name = strdup(interface_name);
207 fprintf(stderr, "unknown type: %s\n", type);
211 wl_list_insert(ctx->message->arg_list.prev,
217 emit_opcodes(struct wl_list *message_list, struct interface *interface)
222 if (wl_list_empty(message_list))
226 wl_list_for_each(m, message_list, link)
227 printf("#define WL_%s_%s\t%d\n",
228 interface->uppercase_name, m->uppercase_name, opcode++);
234 emit_type(struct arg *a)
246 printf("const char *");
249 printf("struct wl_%s *", a->interface_name);
252 printf("struct wl_array *");
258 emit_stubs(struct wl_list *message_list, struct interface *interface)
263 if (wl_list_empty(message_list))
266 wl_list_for_each(m, message_list, link) {
268 wl_list_for_each(a, &m->arg_list, link) {
269 if (a->type == NEW_ID)
274 printf("static inline struct wl_%s *\n",
275 ret->interface_name);
277 printf("static inline void\n");
279 printf("wl_%s_%s(struct wl_%s *%s",
280 interface->name, m->name,
281 interface->name, interface->name);
283 wl_list_for_each(a, &m->arg_list, link) {
284 if (a->type == NEW_ID)
288 printf("%s", a->name);
294 printf("\tstruct wl_proxy *%s;\n\n"
295 "\t%s = wl_proxy_create("
296 "(struct wl_proxy *) %s,\n"
297 "\t\t\t &wl_%s_interface);\n"
299 "\t\treturn NULL;\n\n",
302 interface->name, ret->interface_name,
305 printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n"
308 interface->uppercase_name,
311 wl_list_for_each(a, &m->arg_list, link) {
313 printf("%s", a->name);
318 printf("\n\treturn (struct wl_%s *) %s;\n",
319 ret->interface_name, ret->name);
325 static const char *indent(int n)
327 const char *whitespace[] = {
328 "\t\t\t\t\t\t\t\t\t\t\t\t",
329 "\t\t\t\t\t\t\t\t\t\t\t\t ",
330 "\t\t\t\t\t\t\t\t\t\t\t\t ",
331 "\t\t\t\t\t\t\t\t\t\t\t\t ",
332 "\t\t\t\t\t\t\t\t\t\t\t\t ",
333 "\t\t\t\t\t\t\t\t\t\t\t\t ",
334 "\t\t\t\t\t\t\t\t\t\t\t\t ",
335 "\t\t\t\t\t\t\t\t\t\t\t\t "
338 return whitespace[n % 8] + 12 - n / 8;
342 emit_structs(struct wl_list *message_list, struct interface *interface)
348 if (wl_list_empty(message_list))
351 is_interface = message_list == &interface->request_list;
352 printf("struct wl_%s_%s {\n", interface->name,
353 is_interface ? "interface" : "listener");
355 wl_list_for_each(m, message_list, link) {
356 printf("\tvoid (*%s)(", m->name);
358 n = strlen(m->name) + 17;
360 printf("struct wl_client *client,\n"
361 "%sstruct wl_%s *%s",
363 interface->name, interface->name);
365 printf("void *data,\n"),
366 printf("%sstruct wl_%s *%s",
367 indent(n), interface->name, interface->name);
370 wl_list_for_each(a, &m->arg_list, link) {
371 printf(",\n%s", indent(n));
374 printf("%s", a->name);
383 printf("static inline int\n"
384 "wl_%s_add_listener(struct wl_%s *%s,\n"
385 "%sconst struct wl_%s_listener *listener, void *data)\n"
387 "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n"
388 "%s(void (**)(void)) listener, data);\n"
390 interface->name, interface->name, interface->name,
391 indent(17 + strlen(interface->name)),
399 emit_header(struct protocol *protocol, int server)
404 "#ifndef WAYLAND_PROTOCOL_H\n"
405 "#define WAYLAND_PROTOCOL_H\n"
407 "#ifdef __cplusplus\n"
411 "#include <stdint.h>\n"
412 "#include \"wayland-util.h\"\n\n"
413 "struct wl_client;\n\n", copyright);
415 wl_list_for_each(i, &protocol->interface_list, link)
416 printf("struct wl_%s;\n", i->name);
420 printf("struct wl_proxy;\n\n"
422 "wl_proxy_marshal(struct wl_proxy *p, "
423 "uint32_t opcode, ...);\n"
425 "extern struct wl_proxy *\n"
426 "wl_proxy_create(struct wl_proxy *factory,\n"
427 "\t\tconst struct wl_interface *interface);\n"
430 "wl_proxy_add_listener(struct wl_proxy *proxy,\n"
431 "\t\t void (**implementation)(void), "
434 wl_list_for_each(i, &protocol->interface_list, link) {
435 printf("extern const struct wl_interface "
436 "wl_%s_interface;\n",
441 wl_list_for_each(i, &protocol->interface_list, link) {
444 emit_structs(&i->request_list, i);
445 emit_opcodes(&i->event_list, i);
447 emit_structs(&i->event_list, i);
448 emit_opcodes(&i->request_list, i);
449 emit_stubs(&i->request_list, i);
453 printf("#ifdef __cplusplus\n"
461 emit_messages(struct wl_list *message_list,
462 struct interface *interface, const char *suffix)
467 if (wl_list_empty(message_list))
470 printf("static const struct wl_message "
472 interface->name, suffix);
474 wl_list_for_each(m, message_list, link) {
475 printf("\t{ \"%s\", \"", m->name);
476 wl_list_for_each(a, &m->arg_list, link) {
506 emit_code(struct protocol *protocol)
511 "#include <stdlib.h>\n"
512 "#include <stdint.h>\n"
513 "#include \"wayland-util.h\"\n\n",
516 wl_list_for_each(i, &protocol->interface_list, link) {
518 emit_messages(&i->request_list, i, "requests");
519 emit_messages(&i->event_list, i, "events");
521 printf("WL_EXPORT const struct wl_interface "
522 "wl_%s_interface = {\n"
524 i->name, i->name, i->version);
526 if (!wl_list_empty(&i->request_list))
527 printf("\tARRAY_LENGTH(%s_requests), %s_requests,\n",
530 printf("\t0, NULL,\n");
532 if (!wl_list_empty(&i->event_list))
533 printf("\tARRAY_LENGTH(%s_events), %s_events,\n",
536 printf("\t0, NULL,\n");
542 int main(int argc, char *argv[])
544 struct parse_context ctx;
545 struct protocol protocol;
553 wl_list_init(&protocol.interface_list);
554 ctx.protocol = &protocol;
556 parser = XML_ParserCreate(NULL);
557 XML_SetUserData(parser, &ctx);
558 if (parser == NULL) {
559 fprintf(stderr, "failed to create parser\n");
563 XML_SetElementHandler(parser, start_element, NULL);
565 buf = XML_GetBuffer(parser, XML_BUFFER_SIZE);
566 len = fread(buf, 1, XML_BUFFER_SIZE, stdin);
568 fprintf(stderr, "fread: %s\n", strerror(errno));
571 XML_ParseBuffer(parser, len, len == 0);
575 XML_ParserFree(parser);
577 if (strcmp(argv[1], "client-header") == 0) {
578 emit_header(&protocol, 0);
579 } else if (strcmp(argv[1], "server-header") == 0) {
580 emit_header(&protocol, 1);
581 } else if (strcmp(argv[1], "code") == 0) {
582 emit_code(&protocol);