Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2008-2011 Kristian Hgsberg
      3  * Copyright  2011 Intel Corporation
      4  * Copyright  2015 Red Hat, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining
      7  * a copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sublicense, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial
     16  * portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     25  * SOFTWARE.
     26  */
     27 
     28 #include "config.h"
     29 #include "wayland-version.h"
     30 
     31 #include <stdbool.h>
     32 #include <stdio.h>
     33 #include <stdarg.h>
     34 #include <stdint.h>
     35 #include <string.h>
     36 #include <errno.h>
     37 #include <ctype.h>
     38 #include <expat.h>
     39 #include <getopt.h>
     40 #include <limits.h>
     41 #include <unistd.h>
     42 
     43 #if HAVE_LIBXML
     44 #include <libxml/parser.h>
     45 
     46 /* Embedded wayland.dtd file, see dtddata.S */
     47 extern char DTD_DATA_begin;
     48 extern int DTD_DATA_len;
     49 #endif
     50 
     51 #include "wayland-util.h"
     52 
     53 #define PROGRAM_NAME "wayland-scanner"
     54 
     55 enum side {
     56 	CLIENT,
     57 	SERVER,
     58 };
     59 
     60 static int
     61 usage(int ret)
     62 {
     63 	fprintf(stderr, "usage: %s [OPTION] [client-header|server-header|code]"
     64 		" [input_file output_file]\n", PROGRAM_NAME);
     65 	fprintf(stderr, "\n");
     66 	fprintf(stderr, "Converts XML protocol descriptions supplied on "
     67 			"stdin or input file to client\n"
     68 			"headers, server headers, or protocol marshalling code.\n\n");
     69 	fprintf(stderr, "options:\n");
     70 	fprintf(stderr, "    -h,  --help                  display this help and exit.\n"
     71 			"    -v,  --version               print the wayland library version that\n"
     72 			"                                 the scanner was built against.\n"
     73 		        "    -c,  --include-core-only     include the core version of the headers,\n"
     74 	                "                                 that is e.g. wayland-client-core.h instead\n"
     75 	                "                                 of wayland-client.h.\n");
     76 	exit(ret);
     77 }
     78 
     79 static int
     80 scanner_version(int ret)
     81 {
     82 	fprintf(stderr, "%s %s\n", PROGRAM_NAME, WAYLAND_VERSION);
     83 	exit(ret);
     84 }
     85 
     86 static bool
     87 is_dtd_valid(FILE *input, const char *filename)
     88 {
     89 	bool rc = true;
     90 #if HAVE_LIBXML
     91 	xmlParserCtxtPtr ctx = NULL;
     92 	xmlDocPtr doc = NULL;
     93 	xmlDtdPtr dtd = NULL;
     94 	xmlValidCtxtPtr	dtdctx;
     95 	xmlParserInputBufferPtr	buffer;
     96 	int fd = fileno(input);
     97 
     98 	dtdctx = xmlNewValidCtxt();
     99 	ctx = xmlNewParserCtxt();
    100 	if (!ctx || !dtdctx)
    101 		abort();
    102 
    103 	buffer = xmlParserInputBufferCreateMem(&DTD_DATA_begin,
    104 					       DTD_DATA_len,
    105 					       XML_CHAR_ENCODING_UTF8);
    106 	if (!buffer) {
    107 		fprintf(stderr, "Failed to init buffer for DTD.\n");
    108 		abort();
    109 	}
    110 
    111 	dtd = xmlIOParseDTD(NULL, buffer, XML_CHAR_ENCODING_UTF8);
    112 	if (!dtd) {
    113 		fprintf(stderr, "Failed to parse DTD.\n");
    114 		abort();
    115 	}
    116 
    117 	doc = xmlCtxtReadFd(ctx, fd, filename, NULL, 0);
    118 	if (!doc) {
    119 		fprintf(stderr, "Failed to read XML\n");
    120 		abort();
    121 	}
    122 
    123 	rc = xmlValidateDtd(dtdctx, doc, dtd);
    124 	xmlFreeDoc(doc);
    125 	xmlFreeParserCtxt(ctx);
    126 	xmlFreeValidCtxt(dtdctx);
    127 	/* xmlIOParseDTD consumes buffer */
    128 
    129 	if (lseek(fd, 0, SEEK_SET) != 0) {
    130 		fprintf(stderr, "Failed to reset fd, output would be garbage.\n");
    131 		abort();
    132 	}
    133 #endif
    134 	return rc;
    135 }
    136 
    137 #define XML_BUFFER_SIZE 4096
    138 
    139 struct location {
    140 	const char *filename;
    141 	int line_number;
    142 };
    143 
    144 struct description {
    145 	char *summary;
    146 	char *text;
    147 };
    148 
    149 struct protocol {
    150 	char *name;
    151 	char *uppercase_name;
    152 	struct wl_list interface_list;
    153 	int type_index;
    154 	int null_run_length;
    155 	char *copyright;
    156 	struct description *description;
    157 	bool core_headers;
    158 };
    159 
    160 struct interface {
    161 	struct location loc;
    162 	char *name;
    163 	char *uppercase_name;
    164 	int version;
    165 	int since;
    166 	struct wl_list request_list;
    167 	struct wl_list event_list;
    168 	struct wl_list enumeration_list;
    169 	struct wl_list link;
    170 	struct description *description;
    171 };
    172 
    173 struct message {
    174 	struct location loc;
    175 	char *name;
    176 	char *uppercase_name;
    177 	struct wl_list arg_list;
    178 	struct wl_list link;
    179 	int arg_count;
    180 	int new_id_count;
    181 	int type_index;
    182 	int all_null;
    183 	int destructor;
    184 	int since;
    185 	struct description *description;
    186 };
    187 
    188 enum arg_type {
    189 	NEW_ID,
    190 	INT,
    191 	UNSIGNED,
    192 	FIXED,
    193 	STRING,
    194 	OBJECT,
    195 	ARRAY,
    196 	FD
    197 };
    198 
    199 struct arg {
    200 	char *name;
    201 	enum arg_type type;
    202 	int nullable;
    203 	char *interface_name;
    204 	struct wl_list link;
    205 	char *summary;
    206 	char *enumeration_name;
    207 };
    208 
    209 struct enumeration {
    210 	char *name;
    211 	char *uppercase_name;
    212 	struct wl_list entry_list;
    213 	struct wl_list link;
    214 	struct description *description;
    215 	bool bitfield;
    216 };
    217 
    218 struct entry {
    219 	char *name;
    220 	char *uppercase_name;
    221 	char *value;
    222 	char *summary;
    223 	struct wl_list link;
    224 };
    225 
    226 struct parse_context {
    227 	struct location loc;
    228 	XML_Parser parser;
    229 	struct protocol *protocol;
    230 	struct interface *interface;
    231 	struct message *message;
    232 	struct enumeration *enumeration;
    233 	struct description *description;
    234 	char character_data[8192];
    235 	unsigned int character_data_length;
    236 };
    237 
    238 static void *
    239 fail_on_null(void *p)
    240 {
    241 	if (p == NULL) {
    242 		fprintf(stderr, "%s: out of memory\n", PROGRAM_NAME);
    243 		exit(EXIT_FAILURE);
    244 	}
    245 
    246 	return p;
    247 }
    248 
    249 static void *
    250 zalloc(size_t s)
    251 {
    252 	return calloc(s, 1);
    253 }
    254 
    255 static void *
    256 xzalloc(size_t s)
    257 {
    258 	return fail_on_null(zalloc(s));
    259 }
    260 
    261 static char *
    262 xstrdup(const char *s)
    263 {
    264 	return fail_on_null(strdup(s));
    265 }
    266 
    267 static char *
    268 uppercase_dup(const char *src)
    269 {
    270 	char *u;
    271 	int i;
    272 
    273 	u = xstrdup(src);
    274 	for (i = 0; u[i]; i++)
    275 		u[i] = toupper(u[i]);
    276 	u[i] = '\0';
    277 
    278 	return u;
    279 }
    280 
    281 static const char *indent(int n)
    282 {
    283 	const char *whitespace[] = {
    284 		"\t\t\t\t\t\t\t\t\t\t\t\t",
    285 		"\t\t\t\t\t\t\t\t\t\t\t\t ",
    286 		"\t\t\t\t\t\t\t\t\t\t\t\t  ",
    287 		"\t\t\t\t\t\t\t\t\t\t\t\t   ",
    288 		"\t\t\t\t\t\t\t\t\t\t\t\t    ",
    289 		"\t\t\t\t\t\t\t\t\t\t\t\t     ",
    290 		"\t\t\t\t\t\t\t\t\t\t\t\t      ",
    291 		"\t\t\t\t\t\t\t\t\t\t\t\t       "
    292 	};
    293 
    294 	return whitespace[n % 8] + 12 - n / 8;
    295 }
    296 
    297 static void
    298 desc_dump(char *desc, const char *fmt, ...) WL_PRINTF(2, 3);
    299 
    300 static void
    301 desc_dump(char *desc, const char *fmt, ...)
    302 {
    303 	va_list ap;
    304 	char buf[128], hang;
    305 	int col, i, j, k, startcol, newlines;
    306 
    307 	va_start(ap, fmt);
    308 	vsnprintf(buf, sizeof buf, fmt, ap);
    309 	va_end(ap);
    310 
    311 	for (i = 0, col = 0; buf[i] != '*'; i++) {
    312 		if (buf[i] == '\t')
    313 			col = (col + 8) & ~7;
    314 		else
    315 			col++;
    316 	}
    317 
    318 	printf("%s", buf);
    319 
    320 	if (!desc) {
    321 		printf("(none)\n");
    322 		return;
    323 	}
    324 
    325 	startcol = col;
    326 	col += strlen(&buf[i]);
    327 	if (col - startcol > 2)
    328 		hang = '\t';
    329 	else
    330 		hang = ' ';
    331 
    332 	for (i = 0; desc[i]; ) {
    333 		k = i;
    334 		newlines = 0;
    335 		while (desc[i] && isspace(desc[i])) {
    336 			if (desc[i] == '\n')
    337 				newlines++;
    338 			i++;
    339 		}
    340 		if (!desc[i])
    341 			break;
    342 
    343 		j = i;
    344 		while (desc[i] && !isspace(desc[i]))
    345 			i++;
    346 
    347 		if (newlines > 1)
    348 			printf("\n%s*", indent(startcol));
    349 		if (newlines > 1 || col + i - j > 72) {
    350 			printf("\n%s*%c", indent(startcol), hang);
    351 			col = startcol;
    352 		}
    353 
    354 		if (col > startcol && k > 0)
    355 			col += printf(" ");
    356 		col += printf("%.*s", i - j, &desc[j]);
    357 	}
    358 	putchar('\n');
    359 }
    360 
    361 static void
    362 fail(struct location *loc, const char *msg, ...)
    363 {
    364 	va_list ap;
    365 
    366 	va_start(ap, msg);
    367 	fprintf(stderr, "%s:%d: error: ",
    368 		loc->filename, loc->line_number);
    369 	vfprintf(stderr, msg, ap);
    370 	fprintf(stderr, "\n");
    371 	va_end(ap);
    372 	exit(EXIT_FAILURE);
    373 }
    374 
    375 static void
    376 warn(struct location *loc, const char *msg, ...)
    377 {
    378 	va_list ap;
    379 
    380 	va_start(ap, msg);
    381 	fprintf(stderr, "%s:%d: warning: ",
    382 		loc->filename, loc->line_number);
    383 	vfprintf(stderr, msg, ap);
    384 	fprintf(stderr, "\n");
    385 	va_end(ap);
    386 }
    387 
    388 static bool
    389 is_nullable_type(struct arg *arg)
    390 {
    391 	switch (arg->type) {
    392 	/* Strings, objects, and arrays are possibly nullable */
    393 	case STRING:
    394 	case OBJECT:
    395 	case NEW_ID:
    396 	case ARRAY:
    397 		return true;
    398 	default:
    399 		return false;
    400 	}
    401 }
    402 
    403 static struct message *
    404 create_message(struct location loc, const char *name)
    405 {
    406 	struct message *message;
    407 
    408 	message = xzalloc(sizeof *message);
    409 	message->loc = loc;
    410 	message->name = xstrdup(name);
    411 	message->uppercase_name = uppercase_dup(name);
    412 	wl_list_init(&message->arg_list);
    413 
    414 	return message;
    415 }
    416 
    417 static void
    418 free_arg(struct arg *arg)
    419 {
    420 	free(arg->name);
    421 	free(arg->interface_name);
    422 	free(arg->summary);
    423 	free(arg);
    424 }
    425 
    426 static struct arg *
    427 create_arg(const char *name)
    428 {
    429 	struct arg *arg;
    430 
    431 	arg = xzalloc(sizeof *arg);
    432 	arg->name = xstrdup(name);
    433 
    434 	return arg;
    435 }
    436 
    437 static bool
    438 set_arg_type(struct arg *arg, const char *type)
    439 {
    440 	if (strcmp(type, "int") == 0)
    441 		arg->type = INT;
    442 	else if (strcmp(type, "uint") == 0)
    443 		arg->type = UNSIGNED;
    444 	else if (strcmp(type, "fixed") == 0)
    445 		arg->type = FIXED;
    446 	else if (strcmp(type, "string") == 0)
    447 		arg->type = STRING;
    448 	else if (strcmp(type, "array") == 0)
    449 		arg->type = ARRAY;
    450 	else if (strcmp(type, "fd") == 0)
    451 		arg->type = FD;
    452 	else if (strcmp(type, "new_id") == 0)
    453 		arg->type = NEW_ID;
    454 	else if (strcmp(type, "object") == 0)
    455 		arg->type = OBJECT;
    456 	else
    457 		return false;
    458 
    459 	return true;
    460 }
    461 
    462 static void
    463 free_description(struct description *desc)
    464 {
    465 	if (!desc)
    466 		return;
    467 
    468 	free(desc->summary);
    469 	free(desc->text);
    470 
    471 	free(desc);
    472 }
    473 
    474 static void
    475 free_message(struct message *message)
    476 {
    477 	struct arg *a, *a_next;
    478 
    479 	free(message->name);
    480 	free(message->uppercase_name);
    481 	free_description(message->description);
    482 
    483 	wl_list_for_each_safe(a, a_next, &message->arg_list, link)
    484 		free_arg(a);
    485 
    486 	free(message);
    487 }
    488 
    489 static struct enumeration *
    490 create_enumeration(const char *name)
    491 {
    492 	struct enumeration *enumeration;
    493 
    494 	enumeration = xzalloc(sizeof *enumeration);
    495 	enumeration->name = xstrdup(name);
    496 	enumeration->uppercase_name = uppercase_dup(name);
    497 
    498 	wl_list_init(&enumeration->entry_list);
    499 
    500 	return enumeration;
    501 }
    502 
    503 static struct entry *
    504 create_entry(const char *name, const char *value)
    505 {
    506 	struct entry *entry;
    507 
    508 	entry = xzalloc(sizeof *entry);
    509 	entry->name = xstrdup(name);
    510 	entry->uppercase_name = uppercase_dup(name);
    511 	entry->value = xstrdup(value);
    512 
    513 	return entry;
    514 }
    515 
    516 static void
    517 free_entry(struct entry *entry)
    518 {
    519 	free(entry->name);
    520 	free(entry->uppercase_name);
    521 	free(entry->value);
    522 	free(entry->summary);
    523 
    524 	free(entry);
    525 }
    526 
    527 static void
    528 free_enumeration(struct enumeration *enumeration)
    529 {
    530 	struct entry *e, *e_next;
    531 
    532 	free(enumeration->name);
    533 	free(enumeration->uppercase_name);
    534 	free_description(enumeration->description);
    535 
    536 	wl_list_for_each_safe(e, e_next, &enumeration->entry_list, link)
    537 		free_entry(e);
    538 
    539 	free(enumeration);
    540 }
    541 
    542 static struct interface *
    543 create_interface(struct location loc, const char *name, int version)
    544 {
    545 	struct interface *interface;
    546 
    547 	interface = xzalloc(sizeof *interface);
    548 	interface->loc = loc;
    549 	interface->name = xstrdup(name);
    550 	interface->uppercase_name = uppercase_dup(name);
    551 	interface->version = version;
    552 	interface->since = 1;
    553 	wl_list_init(&interface->request_list);
    554 	wl_list_init(&interface->event_list);
    555 	wl_list_init(&interface->enumeration_list);
    556 
    557 	return interface;
    558 }
    559 
    560 static void
    561 free_interface(struct interface *interface)
    562 {
    563 	struct message *m, *next_m;
    564 	struct enumeration *e, *next_e;
    565 
    566 	free(interface->name);
    567 	free(interface->uppercase_name);
    568 	free_description(interface->description);
    569 
    570 	wl_list_for_each_safe(m, next_m, &interface->request_list, link)
    571 		free_message(m);
    572 	wl_list_for_each_safe(m, next_m, &interface->event_list, link)
    573 		free_message(m);
    574 	wl_list_for_each_safe(e, next_e, &interface->enumeration_list, link)
    575 		free_enumeration(e);
    576 
    577 	free(interface);
    578 }
    579 
    580 /* Convert string to unsigned integer
    581  *
    582  * Parses a non-negative base-10 number from the given string.  If the
    583  * specified string is blank, contains non-numerical characters, is out
    584  * of range, or results in a negative number, -1 is returned to indicate
    585  * an error.
    586  *
    587  * Upon error, this routine does not modify or set errno.
    588  *
    589  * Returns -1 on error, or a non-negative integer on success
    590  */
    591 static int
    592 strtouint(const char *str)
    593 {
    594 	long int ret;
    595 	char *end;
    596 	int prev_errno = errno;
    597 
    598 	errno = 0;
    599 	ret = strtol(str, &end, 10);
    600 	if (errno != 0 || end == str || *end != '\0')
    601 		return -1;
    602 
    603 	/* check range */
    604 	if (ret < 0 || ret > INT_MAX) {
    605 		return -1;
    606 	}
    607 
    608 	errno = prev_errno;
    609 	return (int)ret;
    610 }
    611 
    612 static void
    613 start_element(void *data, const char *element_name, const char **atts)
    614 {
    615 	struct parse_context *ctx = data;
    616 	struct interface *interface;
    617 	struct message *message;
    618 	struct arg *arg;
    619 	struct enumeration *enumeration;
    620 	struct entry *entry;
    621 	struct description *description = NULL;
    622 	const char *name = NULL;
    623 	const char *type = NULL;
    624 	const char *interface_name = NULL;
    625 	const char *value = NULL;
    626 	const char *summary = NULL;
    627 	const char *since = NULL;
    628 	const char *allow_null = NULL;
    629 	const char *enumeration_name = NULL;
    630 	const char *bitfield = NULL;
    631 	int i, version = 0;
    632 
    633 	ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
    634 	for (i = 0; atts[i]; i += 2) {
    635 		if (strcmp(atts[i], "name") == 0)
    636 			name = atts[i + 1];
    637 		if (strcmp(atts[i], "version") == 0) {
    638 			version = strtouint(atts[i + 1]);
    639 			if (version == -1)
    640 				fail(&ctx->loc, "wrong version (%s)", atts[i + 1]);
    641 		}
    642 		if (strcmp(atts[i], "type") == 0)
    643 			type = atts[i + 1];
    644 		if (strcmp(atts[i], "value") == 0)
    645 			value = atts[i + 1];
    646 		if (strcmp(atts[i], "interface") == 0)
    647 			interface_name = atts[i + 1];
    648 		if (strcmp(atts[i], "summary") == 0)
    649 			summary = atts[i + 1];
    650 		if (strcmp(atts[i], "since") == 0)
    651 			since = atts[i + 1];
    652 		if (strcmp(atts[i], "allow-null") == 0)
    653 			allow_null = atts[i + 1];
    654 		if (strcmp(atts[i], "enum") == 0)
    655 			enumeration_name = atts[i + 1];
    656 		if (strcmp(atts[i], "bitfield") == 0)
    657 			bitfield = atts[i + 1];
    658 	}
    659 
    660 	ctx->character_data_length = 0;
    661 	if (strcmp(element_name, "protocol") == 0) {
    662 		if (name == NULL)
    663 			fail(&ctx->loc, "no protocol name given");
    664 
    665 		ctx->protocol->name = xstrdup(name);
    666 		ctx->protocol->uppercase_name = uppercase_dup(name);
    667 	} else if (strcmp(element_name, "copyright") == 0) {
    668 
    669 	} else if (strcmp(element_name, "interface") == 0) {
    670 		if (name == NULL)
    671 			fail(&ctx->loc, "no interface name given");
    672 
    673 		if (version == 0)
    674 			fail(&ctx->loc, "no interface version given");
    675 
    676 		interface = create_interface(ctx->loc, name, version);
    677 		ctx->interface = interface;
    678 		wl_list_insert(ctx->protocol->interface_list.prev,
    679 			       &interface->link);
    680 	} else if (strcmp(element_name, "request") == 0 ||
    681 		   strcmp(element_name, "event") == 0) {
    682 		if (name == NULL)
    683 			fail(&ctx->loc, "no request name given");
    684 
    685 		message = create_message(ctx->loc, name);
    686 
    687 		if (strcmp(element_name, "request") == 0)
    688 			wl_list_insert(ctx->interface->request_list.prev,
    689 				       &message->link);
    690 		else
    691 			wl_list_insert(ctx->interface->event_list.prev,
    692 				       &message->link);
    693 
    694 		if (type != NULL && strcmp(type, "destructor") == 0)
    695 			message->destructor = 1;
    696 
    697 		if (since != NULL) {
    698 			version = strtouint(since);
    699 			if (version == -1) {
    700 				fail(&ctx->loc, "invalid integer (%s)\n", since);
    701 			} else if (version > ctx->interface->version) {
    702 				fail(&ctx->loc, "since (%u) larger than version (%u)\n",
    703 				     version, ctx->interface->version);
    704 			}
    705 		} else {
    706 			version = 1;
    707 		}
    708 
    709 		if (version < ctx->interface->since)
    710 			warn(&ctx->loc, "since version not increasing\n");
    711 		ctx->interface->since = version;
    712 		message->since = version;
    713 
    714 		if (strcmp(name, "destroy") == 0 && !message->destructor)
    715 			fail(&ctx->loc, "destroy request should be destructor type");
    716 
    717 		ctx->message = message;
    718 	} else if (strcmp(element_name, "arg") == 0) {
    719 		if (name == NULL)
    720 			fail(&ctx->loc, "no argument name given");
    721 
    722 		arg = create_arg(name);
    723 		if (!set_arg_type(arg, type))
    724 			fail(&ctx->loc, "unknown type (%s)", type);
    725 
    726 		switch (arg->type) {
    727 		case NEW_ID:
    728 			ctx->message->new_id_count++;
    729 
    730 			/* Fall through to OBJECT case. */
    731 
    732 		case OBJECT:
    733 			if (interface_name)
    734 				arg->interface_name = xstrdup(interface_name);
    735 			break;
    736 		default:
    737 			if (interface_name != NULL)
    738 				fail(&ctx->loc, "interface attribute not allowed for type %s", type);
    739 			break;
    740 		}
    741 
    742 		if (allow_null) {
    743 			if (strcmp(allow_null, "true") == 0)
    744 				arg->nullable = 1;
    745 			else if (strcmp(allow_null, "false") != 0)
    746 				fail(&ctx->loc,
    747 				     "invalid value for allow-null attribute (%s)",
    748 				     allow_null);
    749 
    750 			if (!is_nullable_type(arg))
    751 				fail(&ctx->loc,
    752 				     "allow-null is only valid for objects, strings, and arrays");
    753 		}
    754 
    755 		if (enumeration_name == NULL || strcmp(enumeration_name, "") == 0)
    756 			arg->enumeration_name = NULL;
    757 		else
    758 			arg->enumeration_name = xstrdup(enumeration_name);
    759 
    760 		if (summary)
    761 			arg->summary = xstrdup(summary);
    762 
    763 		wl_list_insert(ctx->message->arg_list.prev, &arg->link);
    764 		ctx->message->arg_count++;
    765 	} else if (strcmp(element_name, "enum") == 0) {
    766 		if (name == NULL)
    767 			fail(&ctx->loc, "no enum name given");
    768 
    769 		enumeration = create_enumeration(name);
    770 
    771 		if (bitfield == NULL || strcmp(bitfield, "false") == 0)
    772 			enumeration->bitfield = false;
    773 		else if (strcmp(bitfield, "true") == 0)
    774 			enumeration->bitfield = true;
    775 		else
    776 			fail(&ctx->loc,
    777 			     "invalid value (%s) for bitfield attribute (only true/false are accepted)",
    778 			     bitfield);
    779 
    780 		wl_list_insert(ctx->interface->enumeration_list.prev,
    781 			       &enumeration->link);
    782 
    783 		ctx->enumeration = enumeration;
    784 	} else if (strcmp(element_name, "entry") == 0) {
    785 		if (name == NULL)
    786 			fail(&ctx->loc, "no entry name given");
    787 
    788 		entry = create_entry(name, value);
    789 
    790 		if (summary)
    791 			entry->summary = xstrdup(summary);
    792 		else
    793 			entry->summary = NULL;
    794 		wl_list_insert(ctx->enumeration->entry_list.prev,
    795 			       &entry->link);
    796 	} else if (strcmp(element_name, "description") == 0) {
    797 		if (summary == NULL)
    798 			fail(&ctx->loc, "description without summary");
    799 
    800 		description = xzalloc(sizeof *description);
    801 		description->summary = xstrdup(summary);
    802 
    803 		if (ctx->message)
    804 			ctx->message->description = description;
    805 		else if (ctx->enumeration)
    806 			ctx->enumeration->description = description;
    807 		else if (ctx->interface)
    808 			ctx->interface->description = description;
    809 		else
    810 			ctx->protocol->description = description;
    811 		ctx->description = description;
    812 	}
    813 }
    814 
    815 static struct enumeration *
    816 find_enumeration(struct protocol *protocol,
    817 		 struct interface *interface,
    818 		 char *enum_attribute)
    819 {
    820 	struct interface *i;
    821 	struct enumeration *e;
    822 	char *enum_name;
    823 	uint32_t idx = 0, j;
    824 
    825 	for (j = 0; j + 1 < strlen(enum_attribute); j++) {
    826 		if (enum_attribute[j] == '.') {
    827 			idx = j;
    828 		}
    829 	}
    830 
    831 	if (idx > 0) {
    832 		enum_name = enum_attribute + idx + 1;
    833 
    834 		wl_list_for_each(i, &protocol->interface_list, link)
    835 			if (strncmp(i->name, enum_attribute, idx) == 0)
    836 				wl_list_for_each(e, &i->enumeration_list, link)
    837 					if (strcmp(e->name, enum_name) == 0)
    838 						return e;
    839 	} else if (interface) {
    840 		enum_name = enum_attribute;
    841 
    842 		wl_list_for_each(e, &interface->enumeration_list, link)
    843 			if (strcmp(e->name, enum_name) == 0)
    844 				return e;
    845 	}
    846 
    847 	return NULL;
    848 }
    849 
    850 static void
    851 verify_arguments(struct parse_context *ctx,
    852 		 struct interface *interface,
    853 		 struct wl_list *messages,
    854 		 struct wl_list *enumerations)
    855 {
    856 	struct message *m;
    857 	wl_list_for_each(m, messages, link) {
    858 		struct arg *a;
    859 		wl_list_for_each(a, &m->arg_list, link) {
    860 			struct enumeration *e;
    861 
    862 			if (!a->enumeration_name)
    863 				continue;
    864 
    865 
    866 			e = find_enumeration(ctx->protocol, interface,
    867 					     a->enumeration_name);
    868 
    869 			if (e == NULL)
    870 				fail(&ctx->loc,
    871 				     "could not find enumeration %s",
    872 				     a->enumeration_name);
    873 
    874 			switch (a->type) {
    875 			case INT:
    876 				if (e->bitfield)
    877 					fail(&ctx->loc,
    878 					     "bitfield-style enum must only be referenced by uint");
    879 				break;
    880 			case UNSIGNED:
    881 				break;
    882 			default:
    883 				fail(&ctx->loc,
    884 				     "enumeration-style argument has wrong type");
    885 			}
    886 		}
    887 	}
    888 
    889 }
    890 
    891 static void
    892 end_element(void *data, const XML_Char *name)
    893 {
    894 	struct parse_context *ctx = data;
    895 
    896 	if (strcmp(name, "copyright") == 0) {
    897 		ctx->protocol->copyright =
    898 			strndup(ctx->character_data,
    899 				ctx->character_data_length);
    900 	} else if (strcmp(name, "description") == 0) {
    901 		ctx->description->text =
    902 			strndup(ctx->character_data,
    903 				ctx->character_data_length);
    904 		ctx->description = NULL;
    905 	} else if (strcmp(name, "request") == 0 ||
    906 		   strcmp(name, "event") == 0) {
    907 		ctx->message = NULL;
    908 	} else if (strcmp(name, "enum") == 0) {
    909 		if (wl_list_empty(&ctx->enumeration->entry_list)) {
    910 			fail(&ctx->loc, "enumeration %s was empty",
    911 			     ctx->enumeration->name);
    912 		}
    913 		ctx->enumeration = NULL;
    914 	} else if (strcmp(name, "protocol") == 0) {
    915 		struct interface *i;
    916 
    917 		wl_list_for_each(i, &ctx->protocol->interface_list, link) {
    918 			verify_arguments(ctx, i, &i->request_list, &i->enumeration_list);
    919 			verify_arguments(ctx, i, &i->event_list, &i->enumeration_list);
    920 		}
    921 	}
    922 }
    923 
    924 static void
    925 character_data(void *data, const XML_Char *s, int len)
    926 {
    927 	struct parse_context *ctx = data;
    928 
    929 	if (ctx->character_data_length + len > sizeof (ctx->character_data)) {
    930 		fprintf(stderr, "too much character data");
    931 		exit(EXIT_FAILURE);
    932 	    }
    933 
    934 	memcpy(ctx->character_data + ctx->character_data_length, s, len);
    935 	ctx->character_data_length += len;
    936 }
    937 
    938 static void
    939 format_text_to_comment(const char *text, bool standalone_comment)
    940 {
    941 	int bol = 1, start = 0, i, length;
    942 	bool comment_started = !standalone_comment;
    943 
    944 	length = strlen(text);
    945 	for (i = 0; i <= length; i++) {
    946 		if (bol && (text[i] == ' ' || text[i] == '\t')) {
    947 			continue;
    948 		} else if (bol) {
    949 			bol = 0;
    950 			start = i;
    951 		}
    952 		if (text[i] == '\n' ||
    953 		    (text[i] == '\0' && !(start == i))) {
    954 			printf("%s%s%.*s\n",
    955 			       comment_started ? " *" : "/*",
    956 			       i > start ? " " : "",
    957 			       i - start, text + start);
    958 			bol = 1;
    959 			comment_started = true;
    960 		}
    961 	}
    962 	if (comment_started && standalone_comment)
    963 		printf(" */\n\n");
    964 }
    965 
    966 static void
    967 emit_opcodes(struct wl_list *message_list, struct interface *interface)
    968 {
    969 	struct message *m;
    970 	int opcode;
    971 
    972 	if (wl_list_empty(message_list))
    973 		return;
    974 
    975 	opcode = 0;
    976 	wl_list_for_each(m, message_list, link)
    977 		printf("#define %s_%s %d\n",
    978 		       interface->uppercase_name, m->uppercase_name, opcode++);
    979 
    980 	printf("\n");
    981 }
    982 
    983 static void
    984 emit_opcode_versions(struct wl_list *message_list, struct interface *interface)
    985 {
    986 	struct message *m;
    987 
    988 	wl_list_for_each(m, message_list, link) {
    989 		printf("/**\n * @ingroup iface_%s\n */\n", interface->name);
    990 		printf("#define %s_%s_SINCE_VERSION %d\n",
    991 		       interface->uppercase_name, m->uppercase_name, m->since);
    992 	}
    993 
    994 	printf("\n");
    995 }
    996 
    997 static void
    998 emit_type(struct arg *a)
    999 {
   1000 	switch (a->type) {
   1001 	default:
   1002 	case INT:
   1003 	case FD:
   1004 		printf("int32_t ");
   1005 		break;
   1006 	case NEW_ID:
   1007 	case UNSIGNED:
   1008 		printf("uint32_t ");
   1009 		break;
   1010 	case FIXED:
   1011 		printf("wl_fixed_t ");
   1012 		break;
   1013 	case STRING:
   1014 		printf("const char *");
   1015 		break;
   1016 	case OBJECT:
   1017 		printf("struct %s *", a->interface_name);
   1018 		break;
   1019 	case ARRAY:
   1020 		printf("struct wl_array *");
   1021 		break;
   1022 	}
   1023 }
   1024 
   1025 static void
   1026 emit_stubs(struct wl_list *message_list, struct interface *interface)
   1027 {
   1028 	struct message *m;
   1029 	struct arg *a, *ret;
   1030 	int has_destructor, has_destroy;
   1031 
   1032 	printf("/** @ingroup iface_%s */\n", interface->name);
   1033 	printf("static inline void\n"
   1034 	       "%s_set_user_data(struct %s *%s, void *user_data)\n"
   1035 	       "{\n"
   1036 	       "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n"
   1037 	       "}\n\n",
   1038 	       interface->name, interface->name, interface->name,
   1039 	       interface->name);
   1040 
   1041 	printf("/** @ingroup iface_%s */\n", interface->name);
   1042 	printf("static inline void *\n"
   1043 	       "%s_get_user_data(struct %s *%s)\n"
   1044 	       "{\n"
   1045 	       "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n"
   1046 	       "}\n\n",
   1047 	       interface->name, interface->name, interface->name,
   1048 	       interface->name);
   1049 
   1050 	printf("static inline uint32_t\n"
   1051 	       "%s_get_version(struct %s *%s)\n"
   1052 	       "{\n"
   1053 	       "\treturn wl_proxy_get_version((struct wl_proxy *) %s);\n"
   1054 	       "}\n\n",
   1055 	       interface->name, interface->name, interface->name,
   1056 	       interface->name);
   1057 
   1058 	has_destructor = 0;
   1059 	has_destroy = 0;
   1060 	wl_list_for_each(m, message_list, link) {
   1061 		if (m->destructor)
   1062 			has_destructor = 1;
   1063 		if (strcmp(m->name, "destroy") == 0)
   1064 			has_destroy = 1;
   1065 	}
   1066 
   1067 	if (!has_destructor && has_destroy) {
   1068 		fail(&interface->loc,
   1069 		     "interface '%s' has method named destroy "
   1070 		     "but no destructor",
   1071 		     interface->name);
   1072 		exit(EXIT_FAILURE);
   1073 	}
   1074 
   1075 	if (!has_destroy && strcmp(interface->name, "wl_display") != 0) {
   1076 		printf("/** @ingroup iface_%s */\n", interface->name);
   1077 		printf("static inline void\n"
   1078 		       "%s_destroy(struct %s *%s)\n"
   1079 		       "{\n"
   1080 		       "\twl_proxy_destroy("
   1081 		       "(struct wl_proxy *) %s);\n"
   1082 		       "}\n\n",
   1083 		       interface->name, interface->name, interface->name,
   1084 		       interface->name);
   1085 	}
   1086 
   1087 	if (wl_list_empty(message_list))
   1088 		return;
   1089 
   1090 	wl_list_for_each(m, message_list, link) {
   1091 		if (m->new_id_count > 1) {
   1092 			warn(&m->loc,
   1093 			     "request '%s::%s' has more than "
   1094 			     "one new_id arg, not emitting stub\n",
   1095 			     interface->name, m->name);
   1096 			continue;
   1097 		}
   1098 
   1099 		ret = NULL;
   1100 		wl_list_for_each(a, &m->arg_list, link) {
   1101 			if (a->type == NEW_ID)
   1102 				ret = a;
   1103 		}
   1104 
   1105 		printf("/**\n"
   1106 		       " * @ingroup iface_%s\n", interface->name);
   1107 		if (m->description && m->description->text)
   1108 			format_text_to_comment(m->description->text, false);
   1109 		printf(" */\n");
   1110 		if (ret && ret->interface_name == NULL)
   1111 			printf("static inline void *\n");
   1112 		else if (ret)
   1113 			printf("static inline struct %s *\n",
   1114 			       ret->interface_name);
   1115 		else
   1116 			printf("static inline void\n");
   1117 
   1118 		printf("%s_%s(struct %s *%s",
   1119 		       interface->name, m->name,
   1120 		       interface->name, interface->name);
   1121 
   1122 		wl_list_for_each(a, &m->arg_list, link) {
   1123 			if (a->type == NEW_ID && a->interface_name == NULL) {
   1124 				printf(", const struct wl_interface *interface"
   1125 				       ", uint32_t version");
   1126 				continue;
   1127 			} else if (a->type == NEW_ID)
   1128 				continue;
   1129 			printf(", ");
   1130 			emit_type(a);
   1131 			printf("%s", a->name);
   1132 		}
   1133 
   1134 		printf(")\n"
   1135 		       "{\n");
   1136 		if (ret && ret->interface_name == NULL) {
   1137 			/* an arg has type ="new_id" but interface is not
   1138 			 * provided, such as in wl_registry.bind */
   1139 			printf("\tstruct wl_proxy *%s;\n\n"
   1140 			       "\t%s = wl_proxy_marshal_constructor_versioned("
   1141 			       "(struct wl_proxy *) %s,\n"
   1142 			       "\t\t\t %s_%s, interface, version",
   1143 			       ret->name, ret->name,
   1144 			       interface->name,
   1145 			       interface->uppercase_name,
   1146 			       m->uppercase_name);
   1147 		} else if (ret) {
   1148 			/* Normal factory case, an arg has type="new_id" and
   1149 			 * an interface is provided */
   1150 			printf("\tstruct wl_proxy *%s;\n\n"
   1151 			       "\t%s = wl_proxy_marshal_constructor("
   1152 			       "(struct wl_proxy *) %s,\n"
   1153 			       "\t\t\t %s_%s, &%s_interface",
   1154 			       ret->name, ret->name,
   1155 			       interface->name,
   1156 			       interface->uppercase_name,
   1157 			       m->uppercase_name,
   1158 			       ret->interface_name);
   1159 		} else {
   1160 			/* No args have type="new_id" */
   1161 			printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n"
   1162 			       "\t\t\t %s_%s",
   1163 			       interface->name,
   1164 			       interface->uppercase_name,
   1165 			       m->uppercase_name);
   1166 		}
   1167 
   1168 		wl_list_for_each(a, &m->arg_list, link) {
   1169 			if (a->type == NEW_ID) {
   1170 				if (a->interface_name == NULL)
   1171 					printf(", interface->name, version");
   1172 				printf(", NULL");
   1173 			} else {
   1174 				printf(", %s", a->name);
   1175 			}
   1176 		}
   1177 		printf(");\n");
   1178 
   1179 		if (m->destructor)
   1180 			printf("\n\twl_proxy_destroy("
   1181 			       "(struct wl_proxy *) %s);\n",
   1182 			       interface->name);
   1183 
   1184 		if (ret && ret->interface_name == NULL)
   1185 			printf("\n\treturn (void *) %s;\n", ret->name);
   1186 		else if (ret)
   1187 			printf("\n\treturn (struct %s *) %s;\n",
   1188 			       ret->interface_name, ret->name);
   1189 
   1190 		printf("}\n\n");
   1191 	}
   1192 }
   1193 
   1194 static void
   1195 emit_event_wrappers(struct wl_list *message_list, struct interface *interface)
   1196 {
   1197 	struct message *m;
   1198 	struct arg *a;
   1199 
   1200 	/* We provide hand written functions for the display object */
   1201 	if (strcmp(interface->name, "wl_display") == 0)
   1202 		return;
   1203 
   1204 	wl_list_for_each(m, message_list, link) {
   1205 		printf("/**\n"
   1206 		       " * @ingroup iface_%s\n"
   1207 		       " * Sends an %s event to the client owning the resource.\n",
   1208 		       interface->name,
   1209 		       m->name);
   1210 		printf(" * @param resource_ The client's resource\n");
   1211 		wl_list_for_each(a, &m->arg_list, link) {
   1212 			if (a->summary)
   1213 				printf(" * @param %s %s\n", a->name, a->summary);
   1214 		}
   1215 		printf(" */\n");
   1216 		printf("static inline void\n"
   1217 		       "%s_send_%s(struct wl_resource *resource_",
   1218 		       interface->name, m->name);
   1219 
   1220 		wl_list_for_each(a, &m->arg_list, link) {
   1221 			printf(", ");
   1222 			switch (a->type) {
   1223 			case NEW_ID:
   1224 			case OBJECT:
   1225 				printf("struct wl_resource *");
   1226 				break;
   1227 			default:
   1228 				emit_type(a);
   1229 			}
   1230 			printf("%s", a->name);
   1231 		}
   1232 
   1233 		printf(")\n"
   1234 		       "{\n"
   1235 		       "\twl_resource_post_event(resource_, %s_%s",
   1236 		       interface->uppercase_name, m->uppercase_name);
   1237 
   1238 		wl_list_for_each(a, &m->arg_list, link)
   1239 			printf(", %s", a->name);
   1240 
   1241 		printf(");\n");
   1242 		printf("}\n\n");
   1243 	}
   1244 }
   1245 
   1246 static void
   1247 emit_enumerations(struct interface *interface)
   1248 {
   1249 	struct enumeration *e;
   1250 	struct entry *entry;
   1251 
   1252 	wl_list_for_each(e, &interface->enumeration_list, link) {
   1253 		struct description *desc = e->description;
   1254 
   1255 		printf("#ifndef %s_%s_ENUM\n",
   1256 		       interface->uppercase_name, e->uppercase_name);
   1257 		printf("#define %s_%s_ENUM\n",
   1258 		       interface->uppercase_name, e->uppercase_name);
   1259 
   1260 		if (desc) {
   1261 			printf("/**\n");
   1262 			printf(" * @ingroup iface_%s\n", interface->name);
   1263 			format_text_to_comment(desc->summary, false);
   1264 			if (desc->text)
   1265 				format_text_to_comment(desc->text, false);
   1266 			printf(" */\n");
   1267 		}
   1268 		printf("enum %s_%s {\n", interface->name, e->name);
   1269 		wl_list_for_each(entry, &e->entry_list, link) {
   1270 			if (entry->summary)
   1271 				printf("\t/**\n"
   1272 				       "\t * %s\n"
   1273 				       "\t */\n", entry->summary);
   1274 			printf("\t%s_%s_%s = %s,\n",
   1275 			       interface->uppercase_name,
   1276 			       e->uppercase_name,
   1277 			       entry->uppercase_name, entry->value);
   1278 		}
   1279 		printf("};\n");
   1280 		printf("#endif /* %s_%s_ENUM */\n\n",
   1281 		       interface->uppercase_name, e->uppercase_name);
   1282 	}
   1283 }
   1284 
   1285 static void
   1286 emit_structs(struct wl_list *message_list, struct interface *interface, enum side side)
   1287 {
   1288 	struct message *m;
   1289 	struct arg *a;
   1290 	int n;
   1291 
   1292 	if (wl_list_empty(message_list))
   1293 		return;
   1294 
   1295 	printf("/**\n");
   1296 	printf(" * @ingroup iface_%s\n", interface->name);
   1297 	printf(" * @struct %s_%s\n", interface->name,
   1298 	       (side == SERVER) ? "interface" : "listener");
   1299 	printf(" */\n");
   1300 	printf("struct %s_%s {\n", interface->name,
   1301 	       (side == SERVER) ? "interface" : "listener");
   1302 
   1303 	wl_list_for_each(m, message_list, link) {
   1304 		struct description *mdesc = m->description;
   1305 
   1306 		printf("\t/**\n");
   1307 		if (mdesc) {
   1308 			if (mdesc->summary)
   1309 				printf("\t * %s\n", mdesc->summary);
   1310 			printf("\t *\n");
   1311 			desc_dump(mdesc->text, "\t * ");
   1312 		}
   1313 		wl_list_for_each(a, &m->arg_list, link) {
   1314 			if (side == SERVER && a->type == NEW_ID &&
   1315 			    a->interface_name == NULL)
   1316 				printf("\t * @param interface name of the objects interface\n"
   1317 				       "\t * @param version version of the objects interface\n");
   1318 
   1319 			if (a->summary)
   1320 				printf("\t * @param %s %s\n", a->name,
   1321 				       a->summary);
   1322 		}
   1323 		if (m->since > 1) {
   1324 			printf("\t * @since %d\n", m->since);
   1325 		}
   1326 		printf("\t */\n");
   1327 		printf("\tvoid (*%s)(", m->name);
   1328 
   1329 		n = strlen(m->name) + 17;
   1330 		if (side == SERVER) {
   1331 			printf("struct wl_client *client,\n"
   1332 			       "%sstruct wl_resource *resource",
   1333 			       indent(n));
   1334 		} else {
   1335 			printf("void *data,\n"),
   1336 			printf("%sstruct %s *%s",
   1337 			       indent(n), interface->name, interface->name);
   1338 		}
   1339 
   1340 		wl_list_for_each(a, &m->arg_list, link) {
   1341 			printf(",\n%s", indent(n));
   1342 
   1343 			if (side == SERVER && a->type == OBJECT)
   1344 				printf("struct wl_resource *");
   1345 			else if (side == SERVER && a->type == NEW_ID && a->interface_name == NULL)
   1346 				printf("const char *interface, uint32_t version, uint32_t ");
   1347 			else if (side == CLIENT && a->type == OBJECT && a->interface_name == NULL)
   1348 				printf("void *");
   1349 
   1350 			else if (side == CLIENT && a->type == NEW_ID)
   1351 				printf("struct %s *", a->interface_name);
   1352 			else
   1353 				emit_type(a);
   1354 
   1355 			printf("%s", a->name);
   1356 		}
   1357 
   1358 		printf(");\n");
   1359 	}
   1360 
   1361 	printf("};\n\n");
   1362 
   1363 	if (side == CLIENT) {
   1364 	    printf("/**\n"
   1365 		   " * @ingroup iface_%s\n"
   1366 		   " */\n", interface->name);
   1367 	    printf("static inline int\n"
   1368 		   "%s_add_listener(struct %s *%s,\n"
   1369 		   "%sconst struct %s_listener *listener, void *data)\n"
   1370 		   "{\n"
   1371 		   "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n"
   1372 		   "%s(void (**)(void)) listener, data);\n"
   1373 		   "}\n\n",
   1374 		   interface->name, interface->name, interface->name,
   1375 		   indent(14 + strlen(interface->name)),
   1376 		   interface->name,
   1377 		   interface->name,
   1378 		   indent(37));
   1379 	}
   1380 }
   1381 
   1382 static void
   1383 emit_types_forward_declarations(struct protocol *protocol,
   1384 				struct wl_list *message_list,
   1385 				struct wl_array *types)
   1386 {
   1387 	struct message *m;
   1388 	struct arg *a;
   1389 	int length;
   1390 	char **p;
   1391 
   1392 	wl_list_for_each(m, message_list, link) {
   1393 		length = 0;
   1394 		m->all_null = 1;
   1395 		wl_list_for_each(a, &m->arg_list, link) {
   1396 			length++;
   1397 			switch (a->type) {
   1398 			case NEW_ID:
   1399 			case OBJECT:
   1400 				if (!a->interface_name)
   1401 					continue;
   1402 
   1403 				m->all_null = 0;
   1404 				p = fail_on_null(wl_array_add(types, sizeof *p));
   1405 				*p = a->interface_name;
   1406 				break;
   1407 			default:
   1408 				break;
   1409 			}
   1410 		}
   1411 
   1412 		if (m->all_null && length > protocol->null_run_length)
   1413 			protocol->null_run_length = length;
   1414 	}
   1415 }
   1416 
   1417 static int
   1418 cmp_names(const void *p1, const void *p2)
   1419 {
   1420 	const char * const *s1 = p1, * const *s2 = p2;
   1421 
   1422 	return strcmp(*s1, *s2);
   1423 }
   1424 
   1425 static const char *
   1426 get_include_name(bool core, enum side side)
   1427 {
   1428 	if (side == SERVER)
   1429 		return core ? "wayland-server-core.h" : "wayland-server.h";
   1430 	else
   1431 		return core ? "wayland-client-core.h" : "wayland-client.h";
   1432 }
   1433 
   1434 static void
   1435 emit_mainpage_blurb(const struct protocol *protocol, enum side side)
   1436 {
   1437 	struct interface *i;
   1438 
   1439 	printf("/**\n"
   1440 	       " * @page page_%s The %s protocol\n",
   1441 	       protocol->name, protocol->name);
   1442 
   1443 	if (protocol->description) {
   1444 		if (protocol->description->summary) {
   1445 			printf(" * %s\n"
   1446 			       " *\n", protocol->description->summary);
   1447 		}
   1448 
   1449 		if (protocol->description->text) {
   1450 			printf(" * @section page_desc_%s Description\n", protocol->name);
   1451 			format_text_to_comment(protocol->description->text, false);
   1452 			printf(" *\n");
   1453 		}
   1454 	}
   1455 
   1456 	printf(" * @section page_ifaces_%s Interfaces\n", protocol->name);
   1457 	wl_list_for_each(i, &protocol->interface_list, link) {
   1458 		printf(" * - @subpage page_iface_%s - %s\n",
   1459 		       i->name,
   1460 		       i->description && i->description->summary ?  i->description->summary : "");
   1461 	}
   1462 
   1463 	if (protocol->copyright) {
   1464 		printf(" * @section page_copyright_%s Copyright\n",
   1465 		       protocol->name);
   1466 		printf(" * <pre>\n");
   1467 		format_text_to_comment(protocol->copyright, false);
   1468 		printf(" * </pre>\n");
   1469 	}
   1470 
   1471 	printf(" */\n");
   1472 }
   1473 
   1474 static void
   1475 emit_header(struct protocol *protocol, enum side side)
   1476 {
   1477 	struct interface *i, *i_next;
   1478 	struct wl_array types;
   1479 	const char *s = (side == SERVER) ? "SERVER" : "CLIENT";
   1480 	char **p, *prev;
   1481 
   1482 	printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
   1483 
   1484 	printf("#ifndef %s_%s_PROTOCOL_H\n"
   1485 	       "#define %s_%s_PROTOCOL_H\n"
   1486 	       "\n"
   1487 	       "#include <stdint.h>\n"
   1488 	       "#include <stddef.h>\n"
   1489 	       "#include \"%s\"\n\n"
   1490 	       "#ifdef  __cplusplus\n"
   1491 	       "extern \"C\" {\n"
   1492 	       "#endif\n\n",
   1493 	       protocol->uppercase_name, s,
   1494 	       protocol->uppercase_name, s,
   1495 	       get_include_name(protocol->core_headers, side));
   1496 	if (side == SERVER)
   1497 		printf("struct wl_client;\n"
   1498 		       "struct wl_resource;\n\n");
   1499 
   1500 	emit_mainpage_blurb(protocol, side);
   1501 
   1502 	wl_array_init(&types);
   1503 	wl_list_for_each(i, &protocol->interface_list, link) {
   1504 		emit_types_forward_declarations(protocol, &i->request_list, &types);
   1505 		emit_types_forward_declarations(protocol, &i->event_list, &types);
   1506 	}
   1507 
   1508 	wl_list_for_each(i, &protocol->interface_list, link) {
   1509 		p = fail_on_null(wl_array_add(&types, sizeof *p));
   1510 		*p = i->name;
   1511 	}
   1512 
   1513 	qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names);
   1514 	prev = NULL;
   1515 	wl_array_for_each(p, &types) {
   1516 		if (prev && strcmp(*p, prev) == 0)
   1517 			continue;
   1518 		printf("struct %s;\n", *p);
   1519 		prev = *p;
   1520 	}
   1521 	wl_array_release(&types);
   1522 	printf("\n");
   1523 
   1524 	wl_list_for_each(i, &protocol->interface_list, link) {
   1525 		printf("/**\n"
   1526 		       " * @page page_iface_%s %s\n",
   1527 		       i->name, i->name);
   1528 		if (i->description && i->description->text) {
   1529 			printf(" * @section page_iface_%s_desc Description\n",
   1530 			       i->name);
   1531 			format_text_to_comment(i->description->text, false);
   1532 		}
   1533 		printf(" * @section page_iface_%s_api API\n"
   1534 		       " * See @ref iface_%s.\n"
   1535 		       " */\n",
   1536 		       i->name, i->name);
   1537 		printf("/**\n"
   1538 		       " * @defgroup iface_%s The %s interface\n",
   1539 		       i->name, i->name);
   1540 		if (i->description && i->description->text)
   1541 			format_text_to_comment(i->description->text, false);
   1542 		printf(" */\n");
   1543 		printf("extern const struct wl_interface "
   1544 		       "%s_interface;\n", i->name);
   1545 	}
   1546 
   1547 	printf("\n");
   1548 
   1549 	wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) {
   1550 
   1551 		emit_enumerations(i);
   1552 
   1553 		if (side == SERVER) {
   1554 			emit_structs(&i->request_list, i, side);
   1555 			emit_opcodes(&i->event_list, i);
   1556 			emit_opcode_versions(&i->event_list, i);
   1557 			emit_opcode_versions(&i->request_list, i);
   1558 			emit_event_wrappers(&i->event_list, i);
   1559 		} else {
   1560 			emit_structs(&i->event_list, i, side);
   1561 			emit_opcodes(&i->request_list, i);
   1562 			emit_opcode_versions(&i->event_list, i);
   1563 			emit_opcode_versions(&i->request_list, i);
   1564 			emit_stubs(&i->request_list, i);
   1565 		}
   1566 
   1567 		free_interface(i);
   1568 	}
   1569 
   1570 	printf("#ifdef  __cplusplus\n"
   1571 	       "}\n"
   1572 	       "#endif\n"
   1573 	       "\n"
   1574 	       "#endif\n");
   1575 }
   1576 
   1577 static void
   1578 emit_null_run(struct protocol *protocol)
   1579 {
   1580 	int i;
   1581 
   1582 	for (i = 0; i < protocol->null_run_length; i++)
   1583 		printf("\tNULL,\n");
   1584 }
   1585 
   1586 static void
   1587 emit_types(struct protocol *protocol, struct wl_list *message_list)
   1588 {
   1589 	struct message *m;
   1590 	struct arg *a;
   1591 
   1592 	wl_list_for_each(m, message_list, link) {
   1593 		if (m->all_null) {
   1594 			m->type_index = 0;
   1595 			continue;
   1596 		}
   1597 
   1598 		m->type_index =
   1599 			protocol->null_run_length + protocol->type_index;
   1600 		protocol->type_index += m->arg_count;
   1601 
   1602 		wl_list_for_each(a, &m->arg_list, link) {
   1603 			switch (a->type) {
   1604 			case NEW_ID:
   1605 			case OBJECT:
   1606 				if (a->interface_name)
   1607 					printf("\t&%s_interface,\n",
   1608 					       a->interface_name);
   1609 				else
   1610 					printf("\tNULL,\n");
   1611 				break;
   1612 			default:
   1613 				printf("\tNULL,\n");
   1614 				break;
   1615 			}
   1616 		}
   1617 	}
   1618 }
   1619 
   1620 static void
   1621 emit_messages(struct wl_list *message_list,
   1622 	      struct interface *interface, const char *suffix)
   1623 {
   1624 	struct message *m;
   1625 	struct arg *a;
   1626 
   1627 	if (wl_list_empty(message_list))
   1628 		return;
   1629 
   1630 	printf("static const struct wl_message "
   1631 	       "%s_%s[] = {\n",
   1632 	       interface->name, suffix);
   1633 
   1634 	wl_list_for_each(m, message_list, link) {
   1635 		printf("\t{ \"%s\", \"", m->name);
   1636 
   1637 		if (m->since > 1)
   1638 			printf("%d", m->since);
   1639 
   1640 		wl_list_for_each(a, &m->arg_list, link) {
   1641 			if (is_nullable_type(a) && a->nullable)
   1642 				printf("?");
   1643 
   1644 			switch (a->type) {
   1645 			default:
   1646 			case INT:
   1647 				printf("i");
   1648 				break;
   1649 			case NEW_ID:
   1650 				if (a->interface_name == NULL)
   1651 					printf("su");
   1652 				printf("n");
   1653 				break;
   1654 			case UNSIGNED:
   1655 				printf("u");
   1656 				break;
   1657 			case FIXED:
   1658 				printf("f");
   1659 				break;
   1660 			case STRING:
   1661 				printf("s");
   1662 				break;
   1663 			case OBJECT:
   1664 				printf("o");
   1665 				break;
   1666 			case ARRAY:
   1667 				printf("a");
   1668 				break;
   1669 			case FD:
   1670 				printf("h");
   1671 				break;
   1672 			}
   1673 		}
   1674 		printf("\", types + %d },\n", m->type_index);
   1675 	}
   1676 
   1677 	printf("};\n\n");
   1678 }
   1679 
   1680 static void
   1681 emit_code(struct protocol *protocol)
   1682 {
   1683 	struct interface *i, *next;
   1684 	struct wl_array types;
   1685 	char **p, *prev;
   1686 
   1687 	printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
   1688 
   1689 	if (protocol->copyright)
   1690 		format_text_to_comment(protocol->copyright, true);
   1691 
   1692 	printf("#include <stdlib.h>\n"
   1693 	       "#include <stdint.h>\n"
   1694 	       "#include \"wayland-util.h\"\n\n");
   1695 
   1696 	wl_array_init(&types);
   1697 	wl_list_for_each(i, &protocol->interface_list, link) {
   1698 		emit_types_forward_declarations(protocol, &i->request_list, &types);
   1699 		emit_types_forward_declarations(protocol, &i->event_list, &types);
   1700 	}
   1701 	qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names);
   1702 	prev = NULL;
   1703 	wl_array_for_each(p, &types) {
   1704 		if (prev && strcmp(*p, prev) == 0)
   1705 			continue;
   1706 		printf("extern const struct wl_interface %s_interface;\n", *p);
   1707 		prev = *p;
   1708 	}
   1709 	wl_array_release(&types);
   1710 	printf("\n");
   1711 
   1712 	printf("static const struct wl_interface *types[] = {\n");
   1713 	emit_null_run(protocol);
   1714 	wl_list_for_each(i, &protocol->interface_list, link) {
   1715 		emit_types(protocol, &i->request_list);
   1716 		emit_types(protocol, &i->event_list);
   1717 	}
   1718 	printf("};\n\n");
   1719 
   1720 	wl_list_for_each_safe(i, next, &protocol->interface_list, link) {
   1721 
   1722 		emit_messages(&i->request_list, i, "requests");
   1723 		emit_messages(&i->event_list, i, "events");
   1724 
   1725 		printf("WL_EXPORT const struct wl_interface "
   1726 		       "%s_interface = {\n"
   1727 		       "\t\"%s\", %d,\n",
   1728 		       i->name, i->name, i->version);
   1729 
   1730 		if (!wl_list_empty(&i->request_list))
   1731 			printf("\t%d, %s_requests,\n",
   1732 			       wl_list_length(&i->request_list), i->name);
   1733 		else
   1734 			printf("\t0, NULL,\n");
   1735 
   1736 		if (!wl_list_empty(&i->event_list))
   1737 			printf("\t%d, %s_events,\n",
   1738 			       wl_list_length(&i->event_list), i->name);
   1739 		else
   1740 			printf("\t0, NULL,\n");
   1741 
   1742 		printf("};\n\n");
   1743 
   1744 		/* we won't need it any further */
   1745 		free_interface(i);
   1746 	}
   1747 }
   1748 
   1749 static void
   1750 free_protocol(struct protocol *protocol)
   1751 {
   1752 	free(protocol->name);
   1753 	free(protocol->uppercase_name);
   1754 	free(protocol->copyright);
   1755 	free_description(protocol->description);
   1756 }
   1757 
   1758 int main(int argc, char *argv[])
   1759 {
   1760 	struct parse_context ctx;
   1761 	struct protocol protocol;
   1762 	FILE *input = stdin;
   1763 	char *input_filename = NULL;
   1764 	int len;
   1765 	void *buf;
   1766 	bool help = false;
   1767 	bool core_headers = false;
   1768 	bool version = false;
   1769 	bool fail = false;
   1770 	int opt;
   1771 	enum {
   1772 		CLIENT_HEADER,
   1773 		SERVER_HEADER,
   1774 		CODE,
   1775 	} mode;
   1776 
   1777 	static const struct option options[] = {
   1778 		{ "help",              no_argument, NULL, 'h' },
   1779 		{ "version",           no_argument, NULL, 'v' },
   1780 		{ "include-core-only", no_argument, NULL, 'c' },
   1781 		{ 0,                   0,           NULL, 0 }
   1782 	};
   1783 
   1784 	while (1) {
   1785 		opt = getopt_long(argc, argv, "hvc", options, NULL);
   1786 
   1787 		if (opt == -1)
   1788 			break;
   1789 
   1790 		switch (opt) {
   1791 		case 'h':
   1792 			help = true;
   1793 			break;
   1794 		case 'v':
   1795 			version = true;
   1796 			break;
   1797 		case 'c':
   1798 			core_headers = true;
   1799 			break;
   1800 		default:
   1801 			fail = true;
   1802 			break;
   1803 		}
   1804 	}
   1805 
   1806 	argv += optind;
   1807 	argc -= optind;
   1808 
   1809 	if (help)
   1810 		usage(EXIT_SUCCESS);
   1811 	else if (version)
   1812 		scanner_version(EXIT_SUCCESS);
   1813 	else if ((argc != 1 && argc != 3) || fail)
   1814 		usage(EXIT_FAILURE);
   1815 	else if (strcmp(argv[0], "help") == 0)
   1816 		usage(EXIT_SUCCESS);
   1817 	else if (strcmp(argv[0], "client-header") == 0)
   1818 		mode = CLIENT_HEADER;
   1819 	else if (strcmp(argv[0], "server-header") == 0)
   1820 		mode = SERVER_HEADER;
   1821 	else if (strcmp(argv[0], "code") == 0)
   1822 		mode = CODE;
   1823 	else
   1824 		usage(EXIT_FAILURE);
   1825 
   1826 	if (argc == 3) {
   1827 		input_filename = argv[1];
   1828 		input = fopen(input_filename, "r");
   1829 		if (input == NULL) {
   1830 			fprintf(stderr, "Could not open input file: %s\n",
   1831 				strerror(errno));
   1832 			exit(EXIT_FAILURE);
   1833 		}
   1834 		if (freopen(argv[2], "w", stdout) == NULL) {
   1835 			fprintf(stderr, "Could not open output file: %s\n",
   1836 				strerror(errno));
   1837 			fclose(input);
   1838 			exit(EXIT_FAILURE);
   1839 		}
   1840 	}
   1841 
   1842 	/* initialize protocol structure */
   1843 	memset(&protocol, 0, sizeof protocol);
   1844 	wl_list_init(&protocol.interface_list);
   1845 	protocol.core_headers = core_headers;
   1846 
   1847 	/* initialize context */
   1848 	memset(&ctx, 0, sizeof ctx);
   1849 	ctx.protocol = &protocol;
   1850 	if (input == stdin)
   1851 		ctx.loc.filename = "<stdin>";
   1852 	else
   1853 		ctx.loc.filename = input_filename;
   1854 
   1855 	if (!is_dtd_valid(input, ctx.loc.filename)) {
   1856 		fprintf(stderr,
   1857 		"*******************************************************\n"
   1858 		"*                                                     *\n"
   1859 		"* WARNING: XML failed validation against built-in DTD *\n"
   1860 		"*                                                     *\n"
   1861 		"*******************************************************\n");
   1862 	}
   1863 
   1864 	/* create XML parser */
   1865 	ctx.parser = XML_ParserCreate(NULL);
   1866 	XML_SetUserData(ctx.parser, &ctx);
   1867 	if (ctx.parser == NULL) {
   1868 		fprintf(stderr, "failed to create parser\n");
   1869 		fclose(input);
   1870 		exit(EXIT_FAILURE);
   1871 	}
   1872 
   1873 	XML_SetElementHandler(ctx.parser, start_element, end_element);
   1874 	XML_SetCharacterDataHandler(ctx.parser, character_data);
   1875 
   1876 	do {
   1877 		buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
   1878 		len = fread(buf, 1, XML_BUFFER_SIZE, input);
   1879 		if (len < 0) {
   1880 			fprintf(stderr, "fread: %m\n");
   1881 			fclose(input);
   1882 			exit(EXIT_FAILURE);
   1883 		}
   1884 		if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) {
   1885 			fprintf(stderr,
   1886 				"Error parsing XML at line %ld col %ld: %s\n",
   1887 				XML_GetCurrentLineNumber(ctx.parser),
   1888 				XML_GetCurrentColumnNumber(ctx.parser),
   1889 				XML_ErrorString(XML_GetErrorCode(ctx.parser)));
   1890 			fclose(input);
   1891 			exit(EXIT_FAILURE);
   1892 		}
   1893 	} while (len > 0);
   1894 
   1895 	XML_ParserFree(ctx.parser);
   1896 
   1897 	switch (mode) {
   1898 		case CLIENT_HEADER:
   1899 			emit_header(&protocol, CLIENT);
   1900 			break;
   1901 		case SERVER_HEADER:
   1902 			emit_header(&protocol, SERVER);
   1903 			break;
   1904 		case CODE:
   1905 			emit_code(&protocol);
   1906 			break;
   1907 	}
   1908 
   1909 	free_protocol(&protocol);
   1910 	fclose(input);
   1911 
   1912 	return 0;
   1913 }
   1914