Change scanner.c license to MIT
[profile/ivi/wayland.git] / wayland / scanner.c
1 /*
2  * Copyright © 2008-2011 Kristian Høgsberg
3  * Copyright © 2011 Intel Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting documentation, and
9  * that the name of the copyright holders not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no representations
12  * about the suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #include <expat.h>
29
30 #include "wayland-util.h"
31
32 static int
33 usage(int ret)
34 {
35         fprintf(stderr, "usage: ./scanner [client-header|server-header|code]\n");
36         exit(ret);
37 }
38
39 #define XML_BUFFER_SIZE 4096
40
41 struct protocol {
42         char *name;
43         char *uppercase_name;
44         struct wl_list interface_list;
45         int type_index;
46         int null_run_length;
47         char *copyright;
48 };
49
50 struct interface {
51         char *name;
52         char *uppercase_name;
53         int version;
54         struct wl_list request_list;
55         struct wl_list event_list;
56         struct wl_list enumeration_list;
57         struct wl_list link;
58 };
59
60 struct message {
61         char *name;
62         char *uppercase_name;
63         struct wl_list arg_list;
64         struct wl_list link;
65         int arg_count;
66         int type_index;
67         int all_null;
68         int destructor;
69 };
70
71 enum arg_type {
72         NEW_ID,
73         INT,
74         UNSIGNED,
75         STRING,
76         OBJECT,
77         ARRAY,
78         FD
79 };
80
81 struct arg {
82         char *name;
83         enum arg_type type;
84         char *interface_name;
85         struct wl_list link;
86 };
87
88 struct enumeration {
89         char *name;
90         char *uppercase_name;
91         struct wl_list entry_list;
92         struct wl_list link;
93 };
94
95 struct entry {
96         char *name;
97         char *uppercase_name;
98         char *value;
99         struct wl_list link;
100 };
101
102 struct parse_context {
103         const char *filename;
104         XML_Parser parser;
105         struct protocol *protocol;
106         struct interface *interface;
107         struct message *message;
108         struct enumeration *enumeration;
109         char character_data[8192];
110         int character_data_length;
111 };
112
113 static char *
114 uppercase_dup(const char *src)
115 {
116         char *u;
117         int i;
118
119         u = strdup(src);
120         for (i = 0; u[i]; i++)
121                 u[i] = toupper(u[i]);
122         u[i] = '\0';
123
124         return u;
125 }
126
127 static void
128 fail(struct parse_context *ctx, const char *msg)
129 {
130         fprintf(stderr, "%s:%ld: %s\n",
131                 ctx->filename, XML_GetCurrentLineNumber(ctx->parser), msg);
132         exit(EXIT_FAILURE);
133 }
134
135 static void
136 start_element(void *data, const char *element_name, const char **atts)
137 {
138         struct parse_context *ctx = data;
139         struct interface *interface;
140         struct message *message;
141         struct arg *arg;
142         struct enumeration *enumeration;
143         struct entry *entry;
144         const char *name, *type, *interface_name, *value;
145         int i, version;
146
147         name = NULL;
148         type = NULL;
149         version = 0;
150         interface_name = NULL;
151         value = NULL;
152         for (i = 0; atts[i]; i += 2) {
153                 if (strcmp(atts[i], "name") == 0)
154                         name = atts[i + 1];
155                 if (strcmp(atts[i], "version") == 0)
156                         version = atoi(atts[i + 1]);
157                 if (strcmp(atts[i], "type") == 0)
158                         type = atts[i + 1];
159                 if (strcmp(atts[i], "value") == 0)
160                         value = atts[i + 1];
161                 if (strcmp(atts[i], "interface") == 0)
162                         interface_name = atts[i + 1];
163         }
164
165         ctx->character_data_length = 0;
166         if (strcmp(element_name, "protocol") == 0) {
167                 if (name == NULL)
168                         fail(ctx, "no protocol name given");
169
170                 ctx->protocol->name = strdup(name);
171                 ctx->protocol->uppercase_name = uppercase_dup(name);
172         } else if (strcmp(element_name, "copyright") == 0) {
173                 
174         } else if (strcmp(element_name, "interface") == 0) {
175                 if (name == NULL)
176                         fail(ctx, "no interface name given");
177
178                 if (version == 0)
179                         fail(ctx, "no interface version given");
180
181                 interface = malloc(sizeof *interface);
182                 interface->name = strdup(name);
183                 interface->uppercase_name = uppercase_dup(name);
184                 interface->version = version;
185                 wl_list_init(&interface->request_list);
186                 wl_list_init(&interface->event_list);
187                 wl_list_init(&interface->enumeration_list);
188                 wl_list_insert(ctx->protocol->interface_list.prev,
189                                &interface->link);
190                 ctx->interface = interface;
191         } else if (strcmp(element_name, "request") == 0 ||
192                    strcmp(element_name, "event") == 0) {
193                 if (name == NULL)
194                         fail(ctx, "no request name given");
195
196                 message = malloc(sizeof *message);
197                 message->name = strdup(name);
198                 message->uppercase_name = uppercase_dup(name);
199                 wl_list_init(&message->arg_list);
200                 message->arg_count = 0;
201
202                 if (strcmp(element_name, "request") == 0)
203                         wl_list_insert(ctx->interface->request_list.prev,
204                                        &message->link);
205                 else
206                         wl_list_insert(ctx->interface->event_list.prev,
207                                        &message->link);
208
209                 if (type != NULL && strcmp(type, "destructor") == 0)
210                         message->destructor = 1;
211                 else
212                         message->destructor = 0;
213
214                 if (strcmp(name, "destroy") == 0 && !message->destructor)
215                         fail(ctx, "destroy request should be destructor type");
216
217                 ctx->message = message;
218         } else if (strcmp(element_name, "arg") == 0) {
219                 arg = malloc(sizeof *arg);
220                 arg->name = strdup(name);
221
222                 if (strcmp(type, "int") == 0)
223                         arg->type = INT;
224                 else if (strcmp(type, "uint") == 0)
225                         arg->type = UNSIGNED;
226                 else if (strcmp(type, "string") == 0)
227                         arg->type = STRING;
228                 else if (strcmp(type, "array") == 0)
229                         arg->type = ARRAY;
230                 else if (strcmp(type, "fd") == 0)
231                         arg->type = FD;
232                 else if (strcmp(type, "new_id") == 0) {
233                         if (interface_name == NULL)
234                                 fail(ctx, "no interface name given");
235                         arg->type = NEW_ID;
236                         arg->interface_name = strdup(interface_name);
237                 } else if (strcmp(type, "object") == 0) {
238                         if (interface_name == NULL)
239                                 fail(ctx, "no interface name given");
240                         arg->type = OBJECT;
241                         arg->interface_name = strdup(interface_name);
242                 } else {
243                         fail(ctx, "unknown type");
244                 }
245
246                 wl_list_insert(ctx->message->arg_list.prev, &arg->link);
247                 ctx->message->arg_count++;
248         } else if (strcmp(element_name, "enum") == 0) {
249                 if (name == NULL)
250                         fail(ctx, "no enum name given");
251
252                 enumeration = malloc(sizeof *enumeration);
253                 enumeration->name = strdup(name);
254                 enumeration->uppercase_name = uppercase_dup(name);
255                 wl_list_init(&enumeration->entry_list);
256
257                 wl_list_insert(ctx->interface->enumeration_list.prev,
258                                &enumeration->link);
259
260                 ctx->enumeration = enumeration;
261         } else if (strcmp(element_name, "entry") == 0) {
262                 entry = malloc(sizeof *entry);
263                 entry->name = strdup(name);
264                 entry->uppercase_name = uppercase_dup(name);
265                 entry->value = strdup(value);
266                 wl_list_insert(ctx->enumeration->entry_list.prev,
267                                &entry->link);
268         }
269 }
270
271 static void
272 end_element(void *data, const XML_Char *name)
273 {
274         struct parse_context *ctx = data;
275
276         if (strcmp(name, "copyright") == 0) {
277                 ctx->protocol->copyright =
278                         strndup(ctx->character_data,
279                                 ctx->character_data_length);
280         }
281 }
282
283 static void
284 character_data(void *data, const XML_Char *s, int len)
285 {
286         struct parse_context *ctx = data;
287
288         if (ctx->character_data_length + len > sizeof (ctx->character_data)) {
289                 fprintf(stderr, "too much character data");
290                 exit(EXIT_FAILURE);
291             }
292
293         memcpy(ctx->character_data + ctx->character_data_length, s, len);
294         ctx->character_data_length += len;
295 }
296
297 static void
298 emit_opcodes(struct wl_list *message_list, struct interface *interface)
299 {
300         struct message *m;
301         int opcode;
302
303         if (wl_list_empty(message_list))
304                 return;
305
306         opcode = 0;
307         wl_list_for_each(m, message_list, link)
308                 printf("#define %s_%s\t%d\n",
309                        interface->uppercase_name, m->uppercase_name, opcode++);
310
311         printf("\n");
312 }
313
314 static void
315 emit_type(struct arg *a)
316 {
317         switch (a->type) {
318         default:
319         case INT:
320         case FD:
321                 printf("int32_t ");
322                 break;
323         case NEW_ID:
324         case UNSIGNED:
325                 printf("uint32_t ");
326                 break;
327         case STRING:
328                 printf("const char *");
329                 break;
330         case OBJECT:
331                 printf("struct %s *", a->interface_name);
332                 break;
333         case ARRAY:
334                 printf("struct wl_array *");
335                 break;
336         }
337 }
338
339 static void
340 emit_stubs(struct wl_list *message_list, struct interface *interface)
341 {
342         struct message *m;
343         struct arg *a, *ret;
344         int has_destructor, has_destroy;
345
346         /* We provide a hand written constructor for the display object */
347         if (strcmp(interface->name, "wl_display") != 0)
348                 printf("static inline struct %s *\n"
349                        "%s_create(struct wl_display *display, uint32_t id, uint32_t version)\n"
350                        "{\n"
351                        "\twl_display_bind(display, id, \"%s\", version);\n\n"
352                        "\treturn (struct %s *)\n"
353                        "\t\twl_proxy_create_for_id(display, &%s_interface, id);\n"
354                        "}\n\n",
355                        interface->name,
356                        interface->name,
357                        interface->name,
358                        interface->name,
359                        interface->name);
360
361         printf("static inline void\n"
362                "%s_set_user_data(struct %s *%s, void *user_data)\n"
363                "{\n"
364                "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n"
365                "}\n\n",
366                interface->name, interface->name, interface->name,
367                interface->name);
368
369         printf("static inline void *\n"
370                "%s_get_user_data(struct %s *%s)\n"
371                "{\n"
372                "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n"
373                "}\n\n",
374                interface->name, interface->name, interface->name,
375                interface->name);
376
377         has_destructor = 0;
378         has_destroy = 0;
379         wl_list_for_each(m, message_list, link) {
380                 if (m->destructor)
381                         has_destructor = 1;
382                 if (strcmp(m->name, "destroy)") == 0)
383                         has_destroy = 1;
384         }
385
386         if (!has_destructor && has_destroy) {
387                 fprintf(stderr,
388                         "interface %s has method named destroy but"
389                         "no destructor", interface->name);
390                 exit(EXIT_FAILURE);
391         }
392
393         /* And we have a hand-written display destructor */
394         if (!has_destructor && strcmp(interface->name, "wl_display") != 0)
395                 printf("static inline void\n"
396                        "%s_destroy(struct %s *%s)\n"
397                        "{\n"
398                        "\twl_proxy_destroy("
399                        "(struct wl_proxy *) %s);\n"
400                        "}\n\n",
401                        interface->name, interface->name, interface->name,
402                        interface->name);
403
404         if (wl_list_empty(message_list))
405                 return;
406
407         wl_list_for_each(m, message_list, link) {
408                 ret = NULL;
409                 wl_list_for_each(a, &m->arg_list, link) {
410                         if (a->type == NEW_ID)
411                                 ret = a;
412                 }
413
414                 if (ret)
415                         printf("static inline struct %s *\n",
416                                ret->interface_name);
417                 else
418                         printf("static inline void\n");
419
420                 printf("%s_%s(struct %s *%s",
421                        interface->name, m->name,
422                        interface->name, interface->name);
423
424                 wl_list_for_each(a, &m->arg_list, link) {
425                         if (a->type == NEW_ID)
426                                 continue;
427                         printf(", ");
428                         emit_type(a);
429                         printf("%s", a->name);
430                 }
431
432                 printf(")\n"
433                        "{\n");
434                 if (ret)
435                         printf("\tstruct wl_proxy *%s;\n\n"
436                                "\t%s = wl_proxy_create("
437                                "(struct wl_proxy *) %s,\n"
438                                "\t\t\t     &%s_interface);\n"
439                                "\tif (!%s)\n"
440                                "\t\treturn NULL;\n\n",
441                                ret->name,
442                                ret->name,
443                                interface->name, ret->interface_name,
444                                ret->name);
445
446                 printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n"
447                        "\t\t\t %s_%s",
448                        interface->name,
449                        interface->uppercase_name,
450                        m->uppercase_name);
451
452                 wl_list_for_each(a, &m->arg_list, link) {
453                         printf(", ");
454                                 printf("%s", a->name);
455                 }
456                 printf(");\n");
457
458                 if (m->destructor)
459                         printf("\n\twl_proxy_destroy("
460                                "(struct wl_proxy *) %s);\n",
461                                interface->name);
462
463                 if (ret)
464                         printf("\n\treturn (struct %s *) %s;\n",
465                                ret->interface_name, ret->name);
466
467                 printf("}\n\n");
468         }
469 }
470
471 static const char *indent(int n)
472 {
473         const char *whitespace[] = {
474                 "\t\t\t\t\t\t\t\t\t\t\t\t",
475                 "\t\t\t\t\t\t\t\t\t\t\t\t ",
476                 "\t\t\t\t\t\t\t\t\t\t\t\t  ",
477                 "\t\t\t\t\t\t\t\t\t\t\t\t   ",
478                 "\t\t\t\t\t\t\t\t\t\t\t\t    ",
479                 "\t\t\t\t\t\t\t\t\t\t\t\t     ",
480                 "\t\t\t\t\t\t\t\t\t\t\t\t      ",
481                 "\t\t\t\t\t\t\t\t\t\t\t\t       "
482         };
483
484         return whitespace[n % 8] + 12 - n / 8;
485 }
486
487 static void
488 emit_enumerations(struct interface *interface)
489 {
490         struct enumeration *e;
491         struct entry *entry;
492
493         wl_list_for_each(e, &interface->enumeration_list, link) {
494                 printf("#ifndef %s_%s_ENUM\n",
495                        interface->uppercase_name, e->uppercase_name);
496                 printf("#define %s_%s_ENUM\n",
497                        interface->uppercase_name, e->uppercase_name);
498                 printf("enum %s_%s {\n", interface->name, e->name);
499                 wl_list_for_each(entry, &e->entry_list, link)
500                         printf("\t%s_%s_%s = %s,\n",
501                                interface->uppercase_name,
502                                e->uppercase_name,
503                                entry->uppercase_name, entry->value);
504                 printf("};\n");
505                 printf("#endif /* %s_%s_ENUM */\n\n",
506                        interface->uppercase_name, e->uppercase_name);
507         }
508 }
509
510 static void
511 emit_structs(struct wl_list *message_list, struct interface *interface)
512 {
513         struct message *m;
514         struct arg *a;
515         int is_interface, n;
516
517         if (wl_list_empty(message_list))
518                 return;
519
520         is_interface = message_list == &interface->request_list;
521         printf("struct %s_%s {\n", interface->name,
522                is_interface ? "interface" : "listener");
523
524         wl_list_for_each(m, message_list, link) {
525                 printf("\tvoid (*%s)(", m->name);
526
527                 n = strlen(m->name) + 17;
528                 if (is_interface) {
529                         printf("struct wl_client *client,\n"
530                                "%sstruct %s *%s",
531                                indent(n),
532                                interface->name, interface->name);
533                 } else {
534                         printf("void *data,\n"),
535                         printf("%sstruct %s *%s",
536                                indent(n), interface->name, interface->name);
537                 }
538
539                 wl_list_for_each(a, &m->arg_list, link) {
540                         printf(",\n%s", indent(n));
541
542                         emit_type(a);
543                         printf("%s", a->name);
544                 }
545
546                 printf(");\n");
547         }
548
549         printf("};\n\n");
550
551         if (!is_interface) {
552             printf("static inline int\n"
553                    "%s_add_listener(struct %s *%s,\n"
554                    "%sconst struct %s_listener *listener, void *data)\n"
555                    "{\n"
556                    "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n"
557                    "%s(void (**)(void)) listener, data);\n"
558                    "}\n\n",
559                    interface->name, interface->name, interface->name,
560                    indent(17 + strlen(interface->name)),
561                    interface->name,
562                    interface->name,
563                    indent(37));
564         }
565 }
566
567 static void
568 format_copyright(const char *copyright)
569 {
570         int bol = 1, start = 0, i;
571
572         for (i = 0; copyright[i]; i++) {
573                 if (bol && (copyright[i] == ' ' || copyright[i] == '\t')) {
574                         continue;
575                 } else if (bol) {
576                         bol = 0;
577                         start = i;
578                 }
579
580                 if (copyright[i] == '\n' || copyright[i] == '\0') {
581                         printf("%s %.*s\n",
582                                i == 0 ? "/*" : " *",
583                                i - start, copyright + start);
584                         bol = 1;
585                 }
586         }
587         printf(" */\n\n");
588 }
589
590 static void
591 emit_header(struct protocol *protocol, int server)
592 {
593         struct interface *i;
594         const char *s = server ? "SERVER" : "CLIENT";
595
596         if (protocol->copyright)
597                 format_copyright(protocol->copyright);
598
599         printf("#ifndef %s_%s_PROTOCOL_H\n"
600                "#define %s_%s_PROTOCOL_H\n"
601                "\n"
602                "#ifdef  __cplusplus\n"
603                "extern \"C\" {\n"
604                "#endif\n"
605                "\n"
606                "#include <stdint.h>\n"
607                "#include <stddef.h>\n"
608                "#include \"wayland-util.h\"\n\n"
609                "struct wl_client;\n\n",
610                protocol->uppercase_name, s,
611                protocol->uppercase_name, s);
612
613         wl_list_for_each(i, &protocol->interface_list, link)
614                 printf("struct %s;\n", i->name);
615         printf("\n");
616
617         wl_list_for_each(i, &protocol->interface_list, link) {
618                 printf("extern const struct wl_interface "
619                        "%s_interface;\n",
620                        i->name);
621         }
622         printf("\n");
623
624         wl_list_for_each(i, &protocol->interface_list, link) {
625
626                 emit_enumerations(i);
627
628                 if (server) {
629                         emit_structs(&i->request_list, i);
630                         emit_opcodes(&i->event_list, i);
631                 } else {
632                         emit_structs(&i->event_list, i);
633                         emit_opcodes(&i->request_list, i);
634                         emit_stubs(&i->request_list, i);
635                 }
636         }
637
638         printf("#ifdef  __cplusplus\n"
639                "}\n"
640                "#endif\n"
641                "\n"
642                "#endif\n");
643 }
644
645 static void
646 emit_types_forward_declarations(struct protocol *protocol,
647                                 struct wl_list *message_list)
648 {
649         struct message *m;
650         struct arg *a;
651         int length;
652
653         wl_list_for_each(m, message_list, link) {
654                 length = 0;
655                 m->all_null = 1;
656                 wl_list_for_each(a, &m->arg_list, link) {
657                         length++;
658                         switch (a->type) {
659                         case NEW_ID:
660                         case OBJECT:
661                                 m->all_null = 0;
662                                 printf("extern const struct wl_interface %s_interface;\n",
663                                        a->interface_name);
664                                 break;
665                         default:
666                                 break;
667                         }
668                 }
669
670                 if (m->all_null && length > protocol->null_run_length)
671                         protocol->null_run_length = length;
672         }
673 }
674
675 static void
676 emit_null_run(struct protocol *protocol)
677 {
678         int i;
679
680         for (i = 0; i < protocol->null_run_length; i++)
681                 printf("\tNULL,\n");
682 }
683
684 static void
685 emit_types(struct protocol *protocol, struct wl_list *message_list)
686 {
687         struct message *m;
688         struct arg *a;
689
690         wl_list_for_each(m, message_list, link) {
691                 if (m->all_null) {
692                         m->type_index = 0;
693                         continue;
694                 }
695
696                 m->type_index =
697                         protocol->null_run_length + protocol->type_index;
698                 protocol->type_index += m->arg_count;
699
700                 wl_list_for_each(a, &m->arg_list, link) {
701                         switch (a->type) {
702                         case NEW_ID:
703                         case OBJECT:
704                                 if (strcmp(a->interface_name,
705                                            "wl_object") != 0)
706                                         printf("\t&%s_interface,\n",
707                                                a->interface_name);
708                                 else
709                                         printf("\tNULL,\n");
710                                 break;
711                         default:
712                                 printf("\tNULL,\n");
713                                 break;
714                         }
715                 }
716         }
717 }
718
719 static void
720 emit_messages(struct wl_list *message_list,
721               struct interface *interface, const char *suffix)
722 {
723         struct message *m;
724         struct arg *a;
725
726         if (wl_list_empty(message_list))
727                 return;
728
729         printf("static const struct wl_message "
730                "%s_%s[] = {\n",
731                interface->name, suffix);
732
733         wl_list_for_each(m, message_list, link) {
734                 printf("\t{ \"%s\", \"", m->name);
735                 wl_list_for_each(a, &m->arg_list, link) {
736                         switch (a->type) {
737                         default:
738                         case INT:
739                                 printf("i");
740                                 break;
741                         case NEW_ID:
742                                 printf("n");
743                                 break;
744                         case UNSIGNED:
745                                 printf("u");
746                                 break;
747                         case STRING:
748                                 printf("s");
749                                 break;
750                         case OBJECT:
751                                 printf("o");
752                                 break;
753                         case ARRAY:
754                                 printf("a");
755                                 break;
756                         case FD:
757                                 printf("h");
758                                 break;
759                         }
760                 }
761                 printf("\", types + %d },\n", m->type_index);
762         }
763
764         printf("};\n\n");
765 }
766
767 static void
768 emit_code(struct protocol *protocol)
769 {
770         struct interface *i;
771
772         if (protocol->copyright)
773                 format_copyright(protocol->copyright);
774
775         printf("#include <stdlib.h>\n"
776                "#include <stdint.h>\n"
777                "#include \"wayland-util.h\"\n\n");
778
779         wl_list_for_each(i, &protocol->interface_list, link) {
780                 emit_types_forward_declarations(protocol, &i->request_list);
781                 emit_types_forward_declarations(protocol, &i->event_list);
782         }
783         printf("\n");
784
785         printf("static const struct wl_interface *types[] = {\n");
786         emit_null_run(protocol);
787         wl_list_for_each(i, &protocol->interface_list, link) {
788                 emit_types(protocol, &i->request_list);
789                 emit_types(protocol, &i->event_list);
790         }
791         printf("};\n\n");
792
793         wl_list_for_each(i, &protocol->interface_list, link) {
794
795                 emit_messages(&i->request_list, i, "requests");
796                 emit_messages(&i->event_list, i, "events");
797
798                 printf("WL_EXPORT const struct wl_interface "
799                        "%s_interface = {\n"
800                        "\t\"%s\", %d,\n",
801                        i->name, i->name, i->version);
802
803                 if (!wl_list_empty(&i->request_list))
804                         printf("\tARRAY_LENGTH(%s_requests), %s_requests,\n",
805                                i->name, i->name);
806                 else
807                         printf("\t0, NULL,\n");
808
809                 if (!wl_list_empty(&i->event_list))
810                         printf("\tARRAY_LENGTH(%s_events), %s_events,\n",
811                                i->name, i->name);
812                 else
813                         printf("\t0, NULL,\n");
814
815                 printf("};\n\n");
816         }
817 }
818
819 int main(int argc, char *argv[])
820 {
821         struct parse_context ctx;
822         struct protocol protocol;
823         int len;
824         void *buf;
825
826         if (argc != 2)
827                 usage(EXIT_FAILURE);
828
829         wl_list_init(&protocol.interface_list);
830         protocol.type_index = 0;
831         protocol.null_run_length = 0;
832         protocol.copyright = NULL;
833         ctx.protocol = &protocol;
834
835         ctx.filename = "<stdin>";
836         ctx.parser = XML_ParserCreate(NULL);
837         XML_SetUserData(ctx.parser, &ctx);
838         if (ctx.parser == NULL) {
839                 fprintf(stderr, "failed to create parser\n");
840                 exit(EXIT_FAILURE);
841         }
842
843         XML_SetElementHandler(ctx.parser, start_element, end_element);
844         XML_SetCharacterDataHandler(ctx.parser, character_data);
845
846         do {
847                 buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
848                 len = fread(buf, 1, XML_BUFFER_SIZE, stdin);
849                 if (len < 0) {
850                         fprintf(stderr, "fread: %s\n", strerror(errno));
851                         exit(EXIT_FAILURE);
852                 }
853                 XML_ParseBuffer(ctx.parser, len, len == 0);
854
855         } while (len > 0);
856
857         XML_ParserFree(ctx.parser);
858
859         if (strcmp(argv[1], "client-header") == 0) {
860                 emit_header(&protocol, 0);
861         } else if (strcmp(argv[1], "server-header") == 0) {
862                 emit_header(&protocol, 1);
863         } else if (strcmp(argv[1], "code") == 0) {
864                 emit_code(&protocol);
865         }
866
867         return 0;
868 }