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
