Two different protocols may use interfaces with identical names.
Implementing support for both those protocols would result in symbol
clashes, as wayland-scanner generates symbols from the interface names.

Make it possible to avoiding these clashes by adding a way to add a
prefix to the symbols generated by wayland-scanner. Implementations
(servers and clients) can then use these prefix:ed symbols to implement
different objects with the same name.

Signed-off-by: Jonas Ådahl <[email protected]>
---

Something like this would be needed if a compositor/client wants to implement
xdg-shell unstable v5 alongside xdg-shell stable, unless we want to rename all
our xdg-shell interfaces. Implementing xdg-shell unstable v6 alongside
xdg-shell stable does not have this issue.

See issue raised here:
https://lists.freedesktop.org/archives/wayland-devel/2017-June/034380.html


Jonas


 src/scanner.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 73 insertions(+), 21 deletions(-)

diff --git a/src/scanner.c b/src/scanner.c
index 517068c..00b5a84 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -228,6 +228,7 @@ struct entry {
 struct parse_context {
        struct location loc;
        XML_Parser parser;
+       char *symbol_prefix;
        struct protocol *protocol;
        struct interface *interface;
        struct message *message;
@@ -1041,7 +1042,9 @@ emit_type(struct arg *a)
 }
 
 static void
-emit_stubs(struct wl_list *message_list, struct interface *interface)
+emit_stubs(struct parse_context *ctx,
+          struct wl_list *message_list,
+          struct interface *interface)
 {
        struct message *m;
        struct arg *a, *ret;
@@ -1168,11 +1171,12 @@ emit_stubs(struct wl_list *message_list, struct 
interface *interface)
                        printf("\tstruct wl_proxy *%s;\n\n"
                               "\t%s = wl_proxy_marshal_constructor("
                               "(struct wl_proxy *) %s,\n"
-                              "\t\t\t %s_%s, &%s_interface",
+                              "\t\t\t %s_%s, &%s%s_interface",
                               ret->name, ret->name,
                               interface->name,
                               interface->uppercase_name,
                               m->uppercase_name,
+                              ctx->symbol_prefix,
                               ret->interface_name);
                } else {
                        /* No args have type="new_id" */
@@ -1507,7 +1511,7 @@ emit_mainpage_blurb(const struct protocol *protocol, enum 
side side)
 }
 
 static void
-emit_header(struct protocol *protocol, enum side side)
+emit_header(struct parse_context *ctx, struct protocol *protocol, enum side 
side)
 {
        struct interface *i, *i_next;
        struct wl_array types;
@@ -1576,7 +1580,7 @@ emit_header(struct protocol *protocol, enum side side)
                        format_text_to_comment(i->description->text, false);
                printf(" */\n");
                printf("extern const struct wl_interface "
-                      "%s_interface;\n", i->name);
+                      "%s%s_interface;\n", ctx->symbol_prefix, i->name);
        }
 
        printf("\n");
@@ -1596,7 +1600,7 @@ emit_header(struct protocol *protocol, enum side side)
                        emit_opcodes(&i->request_list, i);
                        emit_opcode_versions(&i->event_list, i);
                        emit_opcode_versions(&i->request_list, i);
-                       emit_stubs(&i->request_list, i);
+                       emit_stubs(ctx, &i->request_list, i);
                }
 
                free_interface(i);
@@ -1619,7 +1623,9 @@ emit_null_run(struct protocol *protocol)
 }
 
 static void
-emit_types(struct protocol *protocol, struct wl_list *message_list)
+emit_types(struct parse_context *ctx,
+          struct protocol *protocol,
+          struct wl_list *message_list)
 {
        struct message *m;
        struct arg *a;
@@ -1639,7 +1645,8 @@ emit_types(struct protocol *protocol, struct wl_list 
*message_list)
                        case NEW_ID:
                        case OBJECT:
                                if (a->interface_name)
-                                       printf("\t&%s_interface,\n",
+                                       printf("\t&%s%s_interface,\n",
+                                              ctx->symbol_prefix,
                                               a->interface_name);
                                else
                                        printf("\tNULL,\n");
@@ -1713,7 +1720,7 @@ emit_messages(struct wl_list *message_list,
 }
 
 static void
-emit_code(struct protocol *protocol)
+emit_code(struct parse_context *ctx, struct protocol *protocol)
 {
        struct interface *i, *next;
        struct wl_array types;
@@ -1738,7 +1745,8 @@ emit_code(struct protocol *protocol)
        wl_array_for_each(p, &types) {
                if (prev && strcmp(*p, prev) == 0)
                        continue;
-               printf("extern const struct wl_interface %s_interface;\n", *p);
+               printf("extern const struct wl_interface %s%s_interface;\n",
+                      ctx->symbol_prefix, *p);
                prev = *p;
        }
        wl_array_release(&types);
@@ -1747,8 +1755,8 @@ emit_code(struct protocol *protocol)
        printf("static const struct wl_interface *types[] = {\n");
        emit_null_run(protocol);
        wl_list_for_each(i, &protocol->interface_list, link) {
-               emit_types(protocol, &i->request_list);
-               emit_types(protocol, &i->event_list);
+               emit_types(ctx, protocol, &i->request_list);
+               emit_types(ctx, protocol, &i->event_list);
        }
        printf("};\n\n");
 
@@ -1758,9 +1766,9 @@ emit_code(struct protocol *protocol)
                emit_messages(&i->event_list, i, "events");
 
                printf("WL_EXPORT const struct wl_interface "
-                      "%s_interface = {\n"
+                      "%s%s_interface = {\n"
                       "\t\"%s\", %d,\n",
-                      i->name, i->name, i->version);
+                      ctx->symbol_prefix, i->name, i->name, i->version);
 
                if (!wl_list_empty(&i->request_list))
                        printf("\t%d, %s_requests,\n",
@@ -1790,6 +1798,35 @@ free_protocol(struct protocol *protocol)
        free_description(protocol->description);
 }
 
+static bool
+is_valid_symbol_prefix(char *symbol_prefix)
+{
+       int i, len;
+
+       len = strlen(symbol_prefix);
+       for (i = 0; i < len; i++) {
+               char c = symbol_prefix[i];
+
+               if (i == 0) {
+                       if (isalpha(c))
+                               continue;
+
+                       return false;
+               } else {
+                       if (isalpha(c))
+                               continue;
+                       if (isdigit(c))
+                               continue;
+                       if (c == '_')
+                               continue;
+
+                       return false;
+               }
+       }
+
+       return true;
+}
+
 int main(int argc, char *argv[])
 {
        struct parse_context ctx;
@@ -1802,6 +1839,7 @@ int main(int argc, char *argv[])
        bool core_headers = false;
        bool version = false;
        bool fail = false;
+       char *symbol_prefix = NULL;
        int opt;
        enum {
                CLIENT_HEADER,
@@ -1810,14 +1848,15 @@ int main(int argc, char *argv[])
        } mode;
 
        static const struct option options[] = {
-               { "help",              no_argument, NULL, 'h' },
-               { "version",           no_argument, NULL, 'v' },
-               { "include-core-only", no_argument, NULL, 'c' },
-               { 0,                   0,           NULL, 0 }
+               { "help",              no_argument,       NULL, 'h' },
+               { "version",           no_argument,       NULL, 'v' },
+               { "include-core-only", no_argument,       NULL, 'c' },
+               { "symbol-prefix",     required_argument, NULL, 'p' },
+               { 0,                   0,                 NULL, 0 }
        };
 
        while (1) {
-               opt = getopt_long(argc, argv, "hvc", options, NULL);
+               opt = getopt_long(argc, argv, "hvcp:", options, NULL);
 
                if (opt == -1)
                        break;
@@ -1832,6 +1871,9 @@ int main(int argc, char *argv[])
                case 'c':
                        core_headers = true;
                        break;
+               case 'p':
+                       symbol_prefix = strdup(optarg);
+                       break;
                default:
                        fail = true;
                        break;
@@ -1858,6 +1900,14 @@ int main(int argc, char *argv[])
        else
                usage(EXIT_FAILURE);
 
+       if (!symbol_prefix)
+               symbol_prefix = strdup("");
+       if (!is_valid_symbol_prefix(symbol_prefix)) {
+               fprintf(stderr, "Symbol prefix '%s' not valid\n",
+                       symbol_prefix);
+               exit(EXIT_FAILURE);
+       }
+
        if (argc == 3) {
                input_filename = argv[1];
                input = fopen(input_filename, "r");
@@ -1882,6 +1932,7 @@ int main(int argc, char *argv[])
        /* initialize context */
        memset(&ctx, 0, sizeof ctx);
        ctx.protocol = &protocol;
+       ctx.symbol_prefix = symbol_prefix;
        if (input == stdin)
                ctx.loc.filename = "<stdin>";
        else
@@ -1931,16 +1982,17 @@ int main(int argc, char *argv[])
 
        switch (mode) {
                case CLIENT_HEADER:
-                       emit_header(&protocol, CLIENT);
+                       emit_header(&ctx, &protocol, CLIENT);
                        break;
                case SERVER_HEADER:
-                       emit_header(&protocol, SERVER);
+                       emit_header(&ctx, &protocol, SERVER);
                        break;
                case CODE:
-                       emit_code(&protocol);
+                       emit_code(&ctx, &protocol);
                        break;
        }
 
+       free(symbol_prefix);
        free_protocol(&protocol);
        fclose(input);
 
-- 
2.13.0

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to