[PATCH wayland 2/3] scanner: Allow adding a prefix to exported symbols
Jonas Ådahl
jadahl at gmail.com
Mon Jul 3 09:16:45 UTC 2017
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 <jadahl at gmail.com>
---
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
More information about the wayland-devel
mailing list