blob: 613e12b9e1ec3dc7e4cecdb1255cba662023eef8 [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 {
60 struct wl_list interface_list;
61};
62
63struct interface {
64 char *name;
65 char *uppercase_name;
66 int version;
67 struct wl_list request_list;
68 struct wl_list event_list;
69 struct wl_list link;
70};
71
72struct message {
73 char *name;
74 char *uppercase_name;
75 struct wl_list arg_list;
76 struct wl_list link;
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -040077 int destructor;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -040078};
79
80enum arg_type {
81 NEW_ID,
82 INT,
83 UNSIGNED,
84 STRING,
85 OBJECT,
Kristian Høgsbergaebeee02010-08-26 21:49:44 -040086 ARRAY,
87 FD
Kristian Høgsberga1f3f602010-08-03 09:26:44 -040088};
89
90struct arg {
91 char *name;
92 enum arg_type type;
Kristian Høgsberg3862e432010-08-09 21:25:50 -040093 char *interface_name;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -040094 struct wl_list link;
95};
96
97struct parse_context {
98 struct protocol *protocol;
99 struct interface *interface;
100 struct message *message;
101};
102
103static char *
104uppercase_dup(const char *src)
105{
106 char *u;
107 int i;
108
109 u = strdup(src);
110 for (i = 0; u[i]; i++)
111 u[i] = toupper(u[i]);
112 u[i] = '\0';
113
114 return u;
115}
116
117static void
118start_element(void *data, const char *element_name, const char **atts)
119{
120 struct parse_context *ctx = data;
121 struct interface *interface;
122 struct message *message;
123 struct arg *arg;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400124 const char *name, *type, *interface_name;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400125 int i, version;
126
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400127 name = NULL;
128 type = NULL;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400129 version = 0;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400130 interface_name = NULL;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400131 for (i = 0; atts[i]; i += 2) {
132 if (strcmp(atts[i], "name") == 0)
133 name = atts[i + 1];
134 if (strcmp(atts[i], "version") == 0)
135 version = atoi(atts[i + 1]);
136 if (strcmp(atts[i], "type") == 0)
137 type = atts[i + 1];
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400138 if (strcmp(atts[i], "interface") == 0)
139 interface_name = atts[i + 1];
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400140 }
141
142 if (strcmp(element_name, "interface") == 0) {
143 if (name == NULL) {
144 fprintf(stderr, "no interface name given\n");
145 exit(EXIT_FAILURE);
146 }
147
148 if (version == 0) {
149 fprintf(stderr, "no interface version given\n");
150 exit(EXIT_FAILURE);
151 }
152
153 interface = malloc(sizeof *interface);
154 interface->name = strdup(name);
155 interface->uppercase_name = uppercase_dup(name);
156 interface->version = version;
157 wl_list_init(&interface->request_list);
158 wl_list_init(&interface->event_list);
159 wl_list_insert(ctx->protocol->interface_list.prev,
160 &interface->link);
161 ctx->interface = interface;
162 } else if (strcmp(element_name, "request") == 0 ||
163 strcmp(element_name, "event") == 0) {
164 if (name == NULL) {
165 fprintf(stderr, "no request name given\n");
166 exit(EXIT_FAILURE);
167 }
168
169 message = malloc(sizeof *message);
170 message->name = strdup(name);
171 message->uppercase_name = uppercase_dup(name);
172 wl_list_init(&message->arg_list);
173
174 if (strcmp(element_name, "request") == 0)
175 wl_list_insert(ctx->interface->request_list.prev,
176 &message->link);
177 else
178 wl_list_insert(ctx->interface->event_list.prev,
179 &message->link);
180
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400181 if (type != NULL && strcmp(type, "destructor") == 0)
182 message->destructor = 1;
183 else
184 message->destructor = 0;
185
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400186 ctx->message = message;
187 } else if (strcmp(element_name, "arg") == 0) {
188 arg = malloc(sizeof *arg);
189 arg->name = strdup(name);
190
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400191 if (strcmp(type, "int") == 0)
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400192 arg->type = INT;
193 else if (strcmp(type, "uint") == 0)
194 arg->type = UNSIGNED;
195 else if (strcmp(type, "string") == 0)
196 arg->type = STRING;
197 else if (strcmp(type, "array") == 0)
198 arg->type = ARRAY;
Kristian Høgsbergaebeee02010-08-26 21:49:44 -0400199 else if (strcmp(type, "fd") == 0)
200 arg->type = FD;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400201 else if (strcmp(type, "new_id") == 0) {
202 if (interface_name == NULL) {
203 fprintf(stderr, "no interface name given\n");
204 exit(EXIT_FAILURE);
205 }
206 arg->type = NEW_ID;
207 arg->interface_name = strdup(interface_name);
208 } else if (strcmp(type, "object") == 0) {
209 if (interface_name == NULL) {
210 fprintf(stderr, "no interface name given\n");
211 exit(EXIT_FAILURE);
212 }
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400213 arg->type = OBJECT;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400214 arg->interface_name = strdup(interface_name);
215 } else {
216 fprintf(stderr, "unknown type: %s\n", type);
217 exit(EXIT_FAILURE);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400218 }
219
220 wl_list_insert(ctx->message->arg_list.prev,
221 &arg->link);
222 }
223}
224
225static void
226emit_opcodes(struct wl_list *message_list, struct interface *interface)
227{
228 struct message *m;
229 int opcode;
230
231 if (wl_list_empty(message_list))
232 return;
233
234 opcode = 0;
235 wl_list_for_each(m, message_list, link)
236 printf("#define WL_%s_%s\t%d\n",
237 interface->uppercase_name, m->uppercase_name, opcode++);
238
239 printf("\n");
240}
241
242static void
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400243emit_type(struct arg *a)
244{
245 switch (a->type) {
246 default:
247 case INT:
Kristian Høgsbergaebeee02010-08-26 21:49:44 -0400248 case FD:
249 printf("int ");
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400250 break;
251 case NEW_ID:
252 case UNSIGNED:
253 printf("uint32_t ");
254 break;
255 case STRING:
256 printf("const char *");
257 break;
258 case OBJECT:
259 printf("struct wl_%s *", a->interface_name);
260 break;
261 case ARRAY:
262 printf("struct wl_array *");
263 break;
264 }
265}
266
267static void
268emit_stubs(struct wl_list *message_list, struct interface *interface)
269{
270 struct message *m;
271 struct arg *a, *ret;
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400272 int has_destructor, has_destroy;
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400273
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400274 /* We provide a hand written constructor for the display object */
275 if (strcmp(interface->name, "display") != 0)
276 printf("static inline struct wl_%s *\n"
277 "wl_%s_create(struct wl_display *display, uint32_t id)\n"
278 "{\n"
279 "\treturn (struct wl_%s *)\n"
280 "\t\twl_proxy_create_for_id(display, &wl_%s_interface, id);\n"
281 "}\n\n",
282 interface->name,
283 interface->name,
284 interface->name,
285 interface->name);
286
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400287 printf("static inline void\n"
288 "wl_%s_set_user_data(struct wl_%s *%s, void *user_data)\n"
289 "{\n"
290 "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n"
291 "}\n\n",
292 interface->name, interface->name, interface->name,
293 interface->name);
294
295 printf("static inline void *\n"
296 "wl_%s_get_user_data(struct wl_%s *%s)\n"
297 "{\n"
298 "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n"
299 "}\n\n",
300 interface->name, interface->name, interface->name,
301 interface->name);
302
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400303 has_destructor = 0;
304 has_destroy = 0;
305 wl_list_for_each(m, message_list, link) {
306 if (m->destructor)
307 has_destructor = 1;
308 if (strcmp(m->name, "destroy)") == 0)
309 has_destroy = 1;
310 }
311
312 if (!has_destructor && has_destroy) {
313 fprintf(stderr,
314 "interface %s has method named destroy but"
315 "no destructor", interface->name);
316 exit(EXIT_FAILURE);
317 }
318
319 /* And we have a hand-written display destructor */
320 if (!has_destructor && strcmp(interface->name, "display") != 0)
321 printf("static inline void\n"
322 "wl_%s_destroy(struct wl_%s *%s)\n"
323 "{\n"
324 "\twl_proxy_destroy("
325 "(struct wl_proxy *) %s);\n"
326 "}\n\n",
327 interface->name, interface->name, interface->name,
328 interface->name);
329
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400330 if (wl_list_empty(message_list))
331 return;
332
333 wl_list_for_each(m, message_list, link) {
334 ret = NULL;
335 wl_list_for_each(a, &m->arg_list, link) {
336 if (a->type == NEW_ID)
337 ret = a;
338 }
339
340 if (ret)
341 printf("static inline struct wl_%s *\n",
342 ret->interface_name);
343 else
344 printf("static inline void\n");
345
346 printf("wl_%s_%s(struct wl_%s *%s",
347 interface->name, m->name,
348 interface->name, interface->name);
349
350 wl_list_for_each(a, &m->arg_list, link) {
351 if (a->type == NEW_ID)
352 continue;
353 printf(", ");
354 emit_type(a);
355 printf("%s", a->name);
356 }
357
358 printf(")\n"
359 "{\n");
360 if (ret)
361 printf("\tstruct wl_proxy *%s;\n\n"
362 "\t%s = wl_proxy_create("
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400363 "(struct wl_proxy *) %s,\n"
364 "\t\t\t &wl_%s_interface);\n"
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400365 "\tif (!%s)\n"
366 "\t\treturn NULL;\n\n",
367 ret->name,
368 ret->name,
369 interface->name, ret->interface_name,
370 ret->name);
371
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400372 printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n"
373 "\t\t\t WL_%s_%s",
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400374 interface->name,
375 interface->uppercase_name,
376 m->uppercase_name);
377
378 wl_list_for_each(a, &m->arg_list, link) {
379 printf(", ");
380 printf("%s", a->name);
381 }
382 printf(");\n");
383
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400384 if (m->destructor)
385 printf("\n\twl_proxy_destroy("
386 "(struct wl_proxy *) %s);\n",
387 interface->name);
388
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400389 if (ret)
390 printf("\n\treturn (struct wl_%s *) %s;\n",
391 ret->interface_name, ret->name);
392
393 printf("}\n\n");
394 }
395}
396
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400397static const char *indent(int n)
398{
399 const char *whitespace[] = {
400 "\t\t\t\t\t\t\t\t\t\t\t\t",
401 "\t\t\t\t\t\t\t\t\t\t\t\t ",
402 "\t\t\t\t\t\t\t\t\t\t\t\t ",
403 "\t\t\t\t\t\t\t\t\t\t\t\t ",
404 "\t\t\t\t\t\t\t\t\t\t\t\t ",
405 "\t\t\t\t\t\t\t\t\t\t\t\t ",
406 "\t\t\t\t\t\t\t\t\t\t\t\t ",
407 "\t\t\t\t\t\t\t\t\t\t\t\t "
408 };
409
410 return whitespace[n % 8] + 12 - n / 8;
411}
412
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400413static void
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400414emit_structs(struct wl_list *message_list, struct interface *interface)
415{
416 struct message *m;
417 struct arg *a;
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400418 int is_interface, n;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400419
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400420 if (wl_list_empty(message_list))
421 return;
422
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400423 is_interface = message_list == &interface->request_list;
424 printf("struct wl_%s_%s {\n", interface->name,
425 is_interface ? "interface" : "listener");
426
427 wl_list_for_each(m, message_list, link) {
428 printf("\tvoid (*%s)(", m->name);
429
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400430 n = strlen(m->name) + 17;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400431 if (is_interface) {
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400432 printf("struct wl_client *client,\n"
433 "%sstruct wl_%s *%s",
434 indent(n),
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400435 interface->name, interface->name);
436 } else {
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400437 printf("void *data,\n"),
438 printf("%sstruct wl_%s *%s",
439 indent(n), interface->name, interface->name);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400440 }
441
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400442 wl_list_for_each(a, &m->arg_list, link) {
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400443 printf(",\n%s", indent(n));
444
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400445 emit_type(a);
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400446 printf("%s", a->name);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400447 }
448
449 printf(");\n");
450 }
451
452 printf("};\n\n");
Kristian Høgsbergccb75862010-08-10 10:53:44 -0400453
454 if (!is_interface) {
455 printf("static inline int\n"
456 "wl_%s_add_listener(struct wl_%s *%s,\n"
457 "%sconst struct wl_%s_listener *listener, void *data)\n"
458 "{\n"
459 "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n"
460 "%s(void (**)(void)) listener, data);\n"
461 "}\n\n",
462 interface->name, interface->name, interface->name,
463 indent(17 + strlen(interface->name)),
464 interface->name,
465 interface->name,
466 indent(37));
467 }
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400468}
469
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400470static const char client_prototypes[] =
471 "struct wl_proxy;\n\n"
472
473 "extern void\n"
474 "wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);\n"
475
476 "extern struct wl_proxy *\n"
477 "wl_proxy_create(struct wl_proxy *factory,\n"
478 "\t\tconst struct wl_interface *interface);\n"
479
480 "extern struct wl_proxy *\n"
481 "wl_proxy_create_for_id(struct wl_display *display,\n"
482 "\t\t const struct wl_interface *interface, uint32_t id);\n"
483
Kristian Høgsberge9d37bd2010-09-02 20:22:42 -0400484 "extern void\n"
485 "wl_proxy_destroy(struct wl_proxy *proxy);\n\n"
486
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400487 "extern int\n"
488 "wl_proxy_add_listener(struct wl_proxy *proxy,\n"
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400489 "\t\t void (**implementation)(void), void *data);\n\n"
490
491 "extern void\n"
492 "wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data);\n\n"
493
494 "extern void *\n"
495 "wl_proxy_get_user_data(struct wl_proxy *proxy);\n\n";
496
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400497
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400498static void
499emit_header(struct protocol *protocol, int server)
500{
501 struct interface *i;
502
503 printf("%s\n\n"
504 "#ifndef WAYLAND_PROTOCOL_H\n"
505 "#define WAYLAND_PROTOCOL_H\n"
506 "\n"
507 "#ifdef __cplusplus\n"
508 "extern \"C\" {\n"
509 "#endif\n"
510 "\n"
511 "#include <stdint.h>\n"
512 "#include \"wayland-util.h\"\n\n"
513 "struct wl_client;\n\n", copyright);
514
515 wl_list_for_each(i, &protocol->interface_list, link)
516 printf("struct wl_%s;\n", i->name);
517 printf("\n");
518
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400519 if (!server)
Kristian Høgsberg4fe1a3e2010-08-10 14:02:48 -0400520 printf(client_prototypes);
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400521
522 wl_list_for_each(i, &protocol->interface_list, link) {
523 printf("extern const struct wl_interface "
524 "wl_%s_interface;\n",
525 i->name);
526 }
527 printf("\n");
528
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400529 wl_list_for_each(i, &protocol->interface_list, link) {
530
531 if (server) {
532 emit_structs(&i->request_list, i);
533 emit_opcodes(&i->event_list, i);
534 } else {
535 emit_structs(&i->event_list, i);
536 emit_opcodes(&i->request_list, i);
Kristian Høgsberg3862e432010-08-09 21:25:50 -0400537 emit_stubs(&i->request_list, i);
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400538 }
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400539 }
540
541 printf("#ifdef __cplusplus\n"
542 "}\n"
543 "#endif\n"
544 "\n"
545 "#endif\n");
546}
547
548static void
549emit_messages(struct wl_list *message_list,
550 struct interface *interface, const char *suffix)
551{
552 struct message *m;
553 struct arg *a;
554
555 if (wl_list_empty(message_list))
556 return;
557
558 printf("static const struct wl_message "
559 "%s_%s[] = {\n",
560 interface->name, suffix);
561
562 wl_list_for_each(m, message_list, link) {
563 printf("\t{ \"%s\", \"", m->name);
564 wl_list_for_each(a, &m->arg_list, link) {
565 switch (a->type) {
566 default:
567 case INT:
568 printf("i");
569 break;
570 case NEW_ID:
571 printf("n");
572 break;
573 case UNSIGNED:
574 printf("u");
575 break;
576 case STRING:
577 printf("s");
578 break;
579 case OBJECT:
580 printf("o");
581 break;
582 case ARRAY:
583 printf("a");
584 break;
Kristian Høgsbergaebeee02010-08-26 21:49:44 -0400585 case FD:
586 printf("h");
587 break;
Kristian Høgsberga1f3f602010-08-03 09:26:44 -0400588 }
589 }
590 printf("\" },\n");
591 }
592
593 printf("};\n\n");
594}
595
596static void
597emit_code(struct protocol *protocol)
598{
599 struct interface *i;
600
601 printf("%s\n\n"
602 "#include <stdlib.h>\n"
603 "#include <stdint.h>\n"
604 "#include \"wayland-util.h\"\n\n",
605 copyright);
606
607 wl_list_for_each(i, &protocol->interface_list, link) {
608
609 emit_messages(&i->request_list, i, "requests");
610 emit_messages(&i->event_list, i, "events");
611
612 printf("WL_EXPORT const struct wl_interface "
613 "wl_%s_interface = {\n"
614 "\t\"%s\", %d,\n",
615 i->name, i->name, i->version);
616
617 if (!wl_list_empty(&i->request_list))
618 printf("\tARRAY_LENGTH(%s_requests), %s_requests,\n",
619 i->name, i->name);
620 else
621 printf("\t0, NULL,\n");
622
623 if (!wl_list_empty(&i->event_list))
624 printf("\tARRAY_LENGTH(%s_events), %s_events,\n",
625 i->name, i->name);
626 else
627 printf("\t0, NULL,\n");
628
629 printf("};\n\n");
630 }
631}
632
633int main(int argc, char *argv[])
634{
635 struct parse_context ctx;
636 struct protocol protocol;
637 XML_Parser parser;
638 int len;
639 void *buf;
640
641 if (argc != 2)
642 usage(EXIT_FAILURE);
643
644 wl_list_init(&protocol.interface_list);
645 ctx.protocol = &protocol;
646
647 parser = XML_ParserCreate(NULL);
648 XML_SetUserData(parser, &ctx);
649 if (parser == NULL) {
650 fprintf(stderr, "failed to create parser\n");
651 exit(EXIT_FAILURE);
652 }
653
654 XML_SetElementHandler(parser, start_element, NULL);
655 do {
656 buf = XML_GetBuffer(parser, XML_BUFFER_SIZE);
657 len = fread(buf, 1, XML_BUFFER_SIZE, stdin);
658 if (len < 0) {
659 fprintf(stderr, "fread: %s\n", strerror(errno));
660 exit(EXIT_FAILURE);
661 }
662 XML_ParseBuffer(parser, len, len == 0);
663
664 } while (len > 0);
665
666 XML_ParserFree(parser);
667
668 if (strcmp(argv[1], "client-header") == 0) {
669 emit_header(&protocol, 0);
670 } else if (strcmp(argv[1], "server-header") == 0) {
671 emit_header(&protocol, 1);
672 } else if (strcmp(argv[1], "code") == 0) {
673 emit_code(&protocol);
674 }
675
676 return 0;
677}