"Fossies" - the Fresh Open Source Software Archive

Member "wayland-1.18.0/src/scanner.c" (11 Feb 2020, 49859 Bytes) of package /linux/misc/wayland-1.18.0.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "scanner.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.17.0_vs_1.18.0.

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