blob: aaaf551202ab604f31655b199117b0bd3c4847ad [file] [log] [blame]
Kristian Høgsberga1f3f602010-08-03 09:26:44 -04001/*
2 * Copyright © 2010 Intel Corporation
3 *
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.
8 *
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.
13 *
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.
17 */
18
19#include <stdio.h>
20#include <string.h>
21#include <errno.h>
22#include <ctype.h>
23#include <expat.h>
24
25#include "wayland-util.h"
26
27static const char copyright[] =
28 "/*\n"
29 " * Copyright © 2010 Kristian Høgsberg\n"
30 " *\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"
40 " *\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"
48 " */\n";
49
50static int
51usage(int ret)
52{
53 fprintf(stderr, "usage: ./scanner [header|code]\n");
54 exit(ret);
55}
56
57#define XML_BUFFER_SIZE 4096
58
59struct protocol {
Kristian Høgsberg2cd51442010-09-14 15:52:43 -040060 char *name;
61 char *uppercase_name;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -040062 struct wl_list interface_list;
63};
64
65struct interface {
66 char *name;
67 char *uppercase_name;
68 int version;
69 struct wl_list request_list;
70 struct wl_list event_list;
71 struct wl_list link;
72};
73
74struct message {
75 char *name;
76 char *uppercase_name;
77 struct wl_list arg_list;
78 struct wl_list link;
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -040079 int destructor;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -040080};
81
82enum arg_type {
83 NEW_ID,
84 INT,
85 UNSIGNED,
86 STRING,
87 OBJECT,
Kristian Høgsbergaebeee02010-08-26 21:49:44 -040088 ARRAY,
89 FD
Kristian Høgsberga1f3f602010-08-03 09:26:44 -040090};
91
92struct arg {
93 char *name;
94 enum arg_type type;
Kristian Høgsberg3862e432010-08-09 21:25:50 -040095 char *interface_name;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -040096 struct wl_list link;
97};
98
99struct parse_context {
100 struct protocol *protocol;
101 struct interface *interface;
102 struct message *message;
103};
104
105static char *
106uppercase_dup(const char *src)
107{
108 char *u;
109 int i;
110
111 u = strdup(src);
112 for (i = 0; u[i]; i++)
113 u[i] = toupper(u[i]);
114 u[i] = '\0';
115
116 return u;
117}
118
119static void
120start_element(void *data, const char *element_name, const char **atts)
121{
122 struct parse_context *ctx = data;
123 struct interface *interface;
124 struct message *message;
125 struct arg *arg;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400126 const char *name, *type, *interface_name;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400127 int i, version;
128
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400129 name = NULL;
130 type = NULL;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400131 version = 0;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400132 interface_name = NULL;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400133 for (i = 0; atts[i]; i += 2) {
134 if (strcmp(atts[i], "name") == 0)
135 name = atts[i + 1];
136 if (strcmp(atts[i], "version") == 0)
137 version = atoi(atts[i + 1]);
138 if (strcmp(atts[i], "type") == 0)
139 type = atts[i + 1];
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400140 if (strcmp(atts[i], "interface") == 0)
141 interface_name = atts[i + 1];
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400142 }
143
Kristian Høgsberg2cd51442010-09-14 15:52:43 -0400144 if (strcmp(element_name, "protocol") == 0) {
145 if (name == NULL) {
146 fprintf(stderr, "no protocol name given\n");
147 exit(EXIT_FAILURE);
148 }
149
150 ctx->protocol->name = strdup(name);
151 ctx->protocol->uppercase_name = uppercase_dup(name);
152 } else if (strcmp(element_name, "interface") == 0) {
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400153 if (name == NULL) {
154 fprintf(stderr, "no interface name given\n");
155 exit(EXIT_FAILURE);
156 }
157
158 if (version == 0) {
159 fprintf(stderr, "no interface version given\n");
160 exit(EXIT_FAILURE);
161 }
162
163 interface = malloc(sizeof *interface);
164 interface->name = strdup(name);
165 interface->uppercase_name = uppercase_dup(name);
166 interface->version = version;
167 wl_list_init(&interface->request_list);
168 wl_list_init(&interface->event_list);
169 wl_list_insert(ctx->protocol->interface_list.prev,
170 &interface->link);
171 ctx->interface = interface;
172 } else if (strcmp(element_name, "request") == 0 ||
173 strcmp(element_name, "event") == 0) {
174 if (name == NULL) {
175 fprintf(stderr, "no request name given\n");
176 exit(EXIT_FAILURE);
177 }
178
179 message = malloc(sizeof *message);
180 message->name = strdup(name);
181 message->uppercase_name = uppercase_dup(name);
182 wl_list_init(&message->arg_list);
183
184 if (strcmp(element_name, "request") == 0)
185 wl_list_insert(ctx->interface->request_list.prev,
186 &message->link);
187 else
188 wl_list_insert(ctx->interface->event_list.prev,
189 &message->link);
190
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400191 if (type != NULL && strcmp(type, "destructor") == 0)
192 message->destructor = 1;
193 else
194 message->destructor = 0;
195
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400196 ctx->message = message;
197 } else if (strcmp(element_name, "arg") == 0) {
198 arg = malloc(sizeof *arg);
199 arg->name = strdup(name);
200
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400201 if (strcmp(type, "int") == 0)
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400202 arg->type = INT;
203 else if (strcmp(type, "uint") == 0)
204 arg->type = UNSIGNED;
205 else if (strcmp(type, "string") == 0)
206 arg->type = STRING;
207 else if (strcmp(type, "array") == 0)
208 arg->type = ARRAY;
Kristian Høgsbergaebeee02010-08-26 21:49:44 -0400209 else if (strcmp(type, "fd") == 0)
210 arg->type = FD;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400211 else if (strcmp(type, "new_id") == 0) {
212 if (interface_name == NULL) {
213 fprintf(stderr, "no interface name given\n");
214 exit(EXIT_FAILURE);
215 }
216 arg->type = NEW_ID;
217 arg->interface_name = strdup(interface_name);
218 } else if (strcmp(type, "object") == 0) {
219 if (interface_name == NULL) {
220 fprintf(stderr, "no interface name given\n");
221 exit(EXIT_FAILURE);
222 }
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400223 arg->type = OBJECT;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400224 arg->interface_name = strdup(interface_name);
225 } else {
226 fprintf(stderr, "unknown type: %s\n", type);
227 exit(EXIT_FAILURE);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400228 }
229
230 wl_list_insert(ctx->message->arg_list.prev,
231 &arg->link);
232 }
233}
234
235static void
236emit_opcodes(struct wl_list *message_list, struct interface *interface)
237{
238 struct message *m;
239 int opcode;
240
241 if (wl_list_empty(message_list))
242 return;
243
244 opcode = 0;
245 wl_list_for_each(m, message_list, link)
246 printf("#define WL_%s_%s\t%d\n",
247 interface->uppercase_name, m->uppercase_name, opcode++);
248
249 printf("\n");
250}
251
252static void
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400253emit_type(struct arg *a)
254{
255 switch (a->type) {
256 default:
257 case INT:
Kristian Høgsbergaebeee02010-08-26 21:49:44 -0400258 case FD:
259 printf("int ");
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400260 break;
261 case NEW_ID:
262 case UNSIGNED:
263 printf("uint32_t ");
264 break;
265 case STRING:
266 printf("const char *");
267 break;
268 case OBJECT:
269 printf("struct wl_%s *", a->interface_name);
270 break;
271 case ARRAY:
272 printf("struct wl_array *");
273 break;
274 }
275}
276
277static void
278emit_stubs(struct wl_list *message_list, struct interface *interface)
279{
280 struct message *m;
281 struct arg *a, *ret;
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400282 int has_destructor, has_destroy;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400283
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400284 /* We provide a hand written constructor for the display object */
285 if (strcmp(interface->name, "display") != 0)
286 printf("static inline struct wl_%s *\n"
287 "wl_%s_create(struct wl_display *display, uint32_t id)\n"
288 "{\n"
289 "\treturn (struct wl_%s *)\n"
290 "\t\twl_proxy_create_for_id(display, &wl_%s_interface, id);\n"
291 "}\n\n",
292 interface->name,
293 interface->name,
294 interface->name,
295 interface->name);
296
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400297 printf("static inline void\n"
298 "wl_%s_set_user_data(struct wl_%s *%s, void *user_data)\n"
299 "{\n"
300 "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n"
301 "}\n\n",
302 interface->name, interface->name, interface->name,
303 interface->name);
304
305 printf("static inline void *\n"
306 "wl_%s_get_user_data(struct wl_%s *%s)\n"
307 "{\n"
308 "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n"
309 "}\n\n",
310 interface->name, interface->name, interface->name,
311 interface->name);
312
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400313 has_destructor = 0;
314 has_destroy = 0;
315 wl_list_for_each(m, message_list, link) {
316 if (m->destructor)
317 has_destructor = 1;
318 if (strcmp(m->name, "destroy)") == 0)
319 has_destroy = 1;
320 }
321
322 if (!has_destructor && has_destroy) {
323 fprintf(stderr,
324 "interface %s has method named destroy but"
325 "no destructor", interface->name);
326 exit(EXIT_FAILURE);
327 }
328
329 /* And we have a hand-written display destructor */
330 if (!has_destructor && strcmp(interface->name, "display") != 0)
331 printf("static inline void\n"
332 "wl_%s_destroy(struct wl_%s *%s)\n"
333 "{\n"
334 "\twl_proxy_destroy("
335 "(struct wl_proxy *) %s);\n"
336 "}\n\n",
337 interface->name, interface->name, interface->name,
338 interface->name);
339
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400340 if (wl_list_empty(message_list))
341 return;
342
343 wl_list_for_each(m, message_list, link) {
344 ret = NULL;
345 wl_list_for_each(a, &m->arg_list, link) {
346 if (a->type == NEW_ID)
347 ret = a;
348 }
349
350 if (ret)
351 printf("static inline struct wl_%s *\n",
352 ret->interface_name);
353 else
354 printf("static inline void\n");
355
356 printf("wl_%s_%s(struct wl_%s *%s",
357 interface->name, m->name,
358 interface->name, interface->name);
359
360 wl_list_for_each(a, &m->arg_list, link) {
361 if (a->type == NEW_ID)
362 continue;
363 printf(", ");
364 emit_type(a);
365 printf("%s", a->name);
366 }
367
368 printf(")\n"
369 "{\n");
370 if (ret)
371 printf("\tstruct wl_proxy *%s;\n\n"
372 "\t%s = wl_proxy_create("
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400373 "(struct wl_proxy *) %s,\n"
374 "\t\t\t &wl_%s_interface);\n"
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400375 "\tif (!%s)\n"
376 "\t\treturn NULL;\n\n",
377 ret->name,
378 ret->name,
379 interface->name, ret->interface_name,
380 ret->name);
381
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400382 printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n"
383 "\t\t\t WL_%s_%s",
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400384 interface->name,
385 interface->uppercase_name,
386 m->uppercase_name);
387
388 wl_list_for_each(a, &m->arg_list, link) {
389 printf(", ");
390 printf("%s", a->name);
391 }
392 printf(");\n");
393
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400394 if (m->destructor)
395 printf("\n\twl_proxy_destroy("
396 "(struct wl_proxy *) %s);\n",
397 interface->name);
398
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400399 if (ret)
400 printf("\n\treturn (struct wl_%s *) %s;\n",
401 ret->interface_name, ret->name);
402
403 printf("}\n\n");
404 }
405}
406
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400407static const char *indent(int n)
408{
409 const char *whitespace[] = {
410 "\t\t\t\t\t\t\t\t\t\t\t\t",
411 "\t\t\t\t\t\t\t\t\t\t\t\t ",
412 "\t\t\t\t\t\t\t\t\t\t\t\t ",
413 "\t\t\t\t\t\t\t\t\t\t\t\t ",
414 "\t\t\t\t\t\t\t\t\t\t\t\t ",
415 "\t\t\t\t\t\t\t\t\t\t\t\t ",
416 "\t\t\t\t\t\t\t\t\t\t\t\t ",
417 "\t\t\t\t\t\t\t\t\t\t\t\t "
418 };
419
420 return whitespace[n % 8] + 12 - n / 8;
421}
422
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400423static void
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400424emit_structs(struct wl_list *message_list, struct interface *interface)
425{
426 struct message *m;
427 struct arg *a;
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400428 int is_interface, n;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400429
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400430 if (wl_list_empty(message_list))
431 return;
432
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400433 is_interface = message_list == &interface->request_list;
434 printf("struct wl_%s_%s {\n", interface->name,
435 is_interface ? "interface" : "listener");
436
437 wl_list_for_each(m, message_list, link) {
438 printf("\tvoid (*%s)(", m->name);
439
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400440 n = strlen(m->name) + 17;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400441 if (is_interface) {
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400442 printf("struct wl_client *client,\n"
443 "%sstruct wl_%s *%s",
444 indent(n),
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400445 interface->name, interface->name);
446 } else {
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400447 printf("void *data,\n"),
448 printf("%sstruct wl_%s *%s",
449 indent(n), interface->name, interface->name);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400450 }
451
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400452 wl_list_for_each(a, &m->arg_list, link) {
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400453 printf(",\n%s", indent(n));
454
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400455 emit_type(a);
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400456 printf("%s", a->name);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400457 }
458
459 printf(");\n");
460 }
461
462 printf("};\n\n");
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400463
464 if (!is_interface) {
465 printf("static inline int\n"
466 "wl_%s_add_listener(struct wl_%s *%s,\n"
467 "%sconst struct wl_%s_listener *listener, void *data)\n"
468 "{\n"
469 "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n"
470 "%s(void (**)(void)) listener, data);\n"
471 "}\n\n",
472 interface->name, interface->name, interface->name,
473 indent(17 + strlen(interface->name)),
474 interface->name,
475 interface->name,
476 indent(37));
477 }
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400478}
479
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400480static const char client_prototypes[] =
481 "struct wl_proxy;\n\n"
482
483 "extern void\n"
484 "wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);\n"
485
486 "extern struct wl_proxy *\n"
487 "wl_proxy_create(struct wl_proxy *factory,\n"
488 "\t\tconst struct wl_interface *interface);\n"
489
490 "extern struct wl_proxy *\n"
491 "wl_proxy_create_for_id(struct wl_display *display,\n"
492 "\t\t const struct wl_interface *interface, uint32_t id);\n"
493
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400494 "extern void\n"
495 "wl_proxy_destroy(struct wl_proxy *proxy);\n\n"
496
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400497 "extern int\n"
498 "wl_proxy_add_listener(struct wl_proxy *proxy,\n"
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400499 "\t\t void (**implementation)(void), void *data);\n\n"
500
501 "extern void\n"
502 "wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data);\n\n"
503
504 "extern void *\n"
505 "wl_proxy_get_user_data(struct wl_proxy *proxy);\n\n";
506
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400507
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400508static void
509emit_header(struct protocol *protocol, int server)
510{
511 struct interface *i;
Kristian Høgsberg2cd51442010-09-14 15:52:43 -0400512 const char *s = server ? "SERVER" : "CLIENT";
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400513
514 printf("%s\n\n"
Kristian Høgsberg2cd51442010-09-14 15:52:43 -0400515 "#ifndef %s_%s_PROTOCOL_H\n"
516 "#define %s_%s_PROTOCOL_H\n"
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400517 "\n"
518 "#ifdef __cplusplus\n"
519 "extern \"C\" {\n"
520 "#endif\n"
521 "\n"
522 "#include <stdint.h>\n"
523 "#include \"wayland-util.h\"\n\n"
Kristian Høgsberg2cd51442010-09-14 15:52:43 -0400524 "struct wl_client;\n\n",
525 copyright,
526 protocol->uppercase_name, s,
527 protocol->uppercase_name, s);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400528
529 wl_list_for_each(i, &protocol->interface_list, link)
530 printf("struct wl_%s;\n", i->name);
531 printf("\n");
532
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400533 if (!server)
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400534 printf(client_prototypes);
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400535
536 wl_list_for_each(i, &protocol->interface_list, link) {
537 printf("extern const struct wl_interface "
538 "wl_%s_interface;\n",
539 i->name);
540 }
541 printf("\n");
542
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400543 wl_list_for_each(i, &protocol->interface_list, link) {
544
545 if (server) {
546 emit_structs(&i->request_list, i);
547 emit_opcodes(&i->event_list, i);
548 } else {
549 emit_structs(&i->event_list, i);
550 emit_opcodes(&i->request_list, i);
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400551 emit_stubs(&i->request_list, i);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400552 }
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400553 }
554
555 printf("#ifdef __cplusplus\n"
556 "}\n"
557 "#endif\n"
558 "\n"
559 "#endif\n");
560}
561
562static void
563emit_messages(struct wl_list *message_list,
564 struct interface *interface, const char *suffix)
565{
566 struct message *m;
567 struct arg *a;
568
569 if (wl_list_empty(message_list))
570 return;
571
572 printf("static const struct wl_message "
573 "%s_%s[] = {\n",
574 interface->name, suffix);
575
576 wl_list_for_each(m, message_list, link) {
577 printf("\t{ \"%s\", \"", m->name);
578 wl_list_for_each(a, &m->arg_list, link) {
579 switch (a->type) {
580 default:
581 case INT:
582 printf("i");
583 break;
584 case NEW_ID:
585 printf("n");
586 break;
587 case UNSIGNED:
588 printf("u");
589 break;
590 case STRING:
591 printf("s");
592 break;
593 case OBJECT:
594 printf("o");
595 break;
596 case ARRAY:
597 printf("a");
598 break;
Kristian Høgsbergaebeee02010-08-26 21:49:44 -0400599 case FD:
600 printf("h");
601 break;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400602 }
603 }
604 printf("\" },\n");
605 }
606
607 printf("};\n\n");
608}
609
610static void
611emit_code(struct protocol *protocol)
612{
613 struct interface *i;
614
615 printf("%s\n\n"
616 "#include <stdlib.h>\n"
617 "#include <stdint.h>\n"
618 "#include \"wayland-util.h\"\n\n",
619 copyright);
620
621 wl_list_for_each(i, &protocol->interface_list, link) {
622
623 emit_messages(&i->request_list, i, "requests");
624 emit_messages(&i->event_list, i, "events");
625
626 printf("WL_EXPORT const struct wl_interface "
627 "wl_%s_interface = {\n"
628 "\t\"%s\", %d,\n",
629 i->name, i->name, i->version);
630
631 if (!wl_list_empty(&i->request_list))
632 printf("\tARRAY_LENGTH(%s_requests), %s_requests,\n",
633 i->name, i->name);
634 else
635 printf("\t0, NULL,\n");
636
637 if (!wl_list_empty(&i->event_list))
638 printf("\tARRAY_LENGTH(%s_events), %s_events,\n",
639 i->name, i->name);
640 else
641 printf("\t0, NULL,\n");
642
643 printf("};\n\n");
644 }
645}
646
647int main(int argc, char *argv[])
648{
649 struct parse_context ctx;
650 struct protocol protocol;
651 XML_Parser parser;
652 int len;
653 void *buf;
654
655 if (argc != 2)
656 usage(EXIT_FAILURE);
657
658 wl_list_init(&protocol.interface_list);
659 ctx.protocol = &protocol;
660
661 parser = XML_ParserCreate(NULL);
662 XML_SetUserData(parser, &ctx);
663 if (parser == NULL) {
664 fprintf(stderr, "failed to create parser\n");
665 exit(EXIT_FAILURE);
666 }
667
668 XML_SetElementHandler(parser, start_element, NULL);
669 do {
670 buf = XML_GetBuffer(parser, XML_BUFFER_SIZE);
671 len = fread(buf, 1, XML_BUFFER_SIZE, stdin);
672 if (len < 0) {
673 fprintf(stderr, "fread: %s\n", strerror(errno));
674 exit(EXIT_FAILURE);
675 }
676 XML_ParseBuffer(parser, len, len == 0);
677
678 } while (len > 0);
679
680 XML_ParserFree(parser);
681
682 if (strcmp(argv[1], "client-header") == 0) {
683 emit_header(&protocol, 0);
684 } else if (strcmp(argv[1], "server-header") == 0) {
685 emit_header(&protocol, 1);
686 } else if (strcmp(argv[1], "code") == 0) {
687 emit_code(&protocol);
688 }
689
690 return 0;
691}