[PATCH wayland v4] scanner: add a new --include-core-only option
Giulio Camuffo
giuliocamuffo at gmail.com
Wed Apr 29 06:46:51 PDT 2015
When using this new option the generated code will include the new
core headers instead of the old ones. The default needs to remain
unchanged for backward compatibility with old code.
With this change the generated headers will now forward declare all
types and interfaces it uses; that is needed when generating headers
for a my-extension.xml with --include-core-only, since it may use
types defined in wayland.xml.
The same is done also without --include-core-only, since it is an
harmless change.
getopt_long() is used for the option handling.
---
v4: removed leftover line
src/scanner.c | 208 +++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 149 insertions(+), 59 deletions(-)
diff --git a/src/scanner.c b/src/scanner.c
index adc9aa3..75322f7 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <ctype.h>
#include <expat.h>
+#include <getopt.h>
#include "wayland-util.h"
@@ -39,12 +40,17 @@ enum side {
static int
usage(int ret)
{
- fprintf(stderr, "usage: ./scanner [client-header|server-header|code]"
+ fprintf(stderr, "usage: ./scanner [OPTION] [client-header|server-header|code]"
" [input_file output_file]\n");
fprintf(stderr, "\n");
fprintf(stderr, "Converts XML protocol descriptions supplied on "
"stdin or input file to client\n"
- "headers, server headers, or protocol marshalling code.\n");
+ "headers, server headers, or protocol marshalling code.\n\n");
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, " -h, --help display this help and exit.\n"
+ " -c, --include-core-only include the core version of the headers,\n"
+ " that is e.g. wayland-client-core.h instead\n"
+ " of wayland-client.h.\n");
exit(ret);
}
@@ -68,6 +74,7 @@ struct protocol {
int null_run_length;
char *copyright;
struct description *description;
+ bool core_headers;
};
struct interface {
@@ -985,10 +992,64 @@ format_copyright(const char *copyright)
}
static void
+emit_types_forward_declarations(struct protocol *protocol,
+ struct wl_list *message_list,
+ struct wl_array *types)
+{
+ struct message *m;
+ struct arg *a;
+ int length;
+ char **p;
+
+ wl_list_for_each(m, message_list, link) {
+ length = 0;
+ m->all_null = 1;
+ wl_list_for_each(a, &m->arg_list, link) {
+ length++;
+ switch (a->type) {
+ case NEW_ID:
+ case OBJECT:
+ if (!a->interface_name)
+ continue;
+
+ m->all_null = 0;
+ p = fail_on_null(wl_array_add(types, sizeof *p));
+ *p = a->interface_name;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (m->all_null && length > protocol->null_run_length)
+ protocol->null_run_length = length;
+ }
+}
+
+static int
+cmp_names(const void *p1, const void *p2)
+{
+ const char * const *s1 = p1, * const *s2 = p2;
+
+ return strcmp(*s1, *s2);
+}
+
+static const char *
+get_include_name(bool core, enum side side)
+{
+ if (side == SERVER)
+ return core ? "wayland-server-core.h" : "wayland-server.h";
+ else
+ return core ? "wayland-client-core.h" : "wayland-client.h";
+}
+
+static void
emit_header(struct protocol *protocol, enum side side)
{
struct interface *i;
+ struct wl_array types;
const char *s = (side == SERVER) ? "SERVER" : "CLIENT";
+ char **p, *prev;
if (protocol->copyright)
format_copyright(protocol->copyright);
@@ -1007,17 +1068,39 @@ emit_header(struct protocol *protocol, enum side side)
"struct wl_resource;\n\n",
protocol->uppercase_name, s,
protocol->uppercase_name, s,
- (side == SERVER) ? "wayland-server.h" : "wayland-client.h");
+ get_include_name(protocol->core_headers, side));
- wl_list_for_each(i, &protocol->interface_list, link)
- printf("struct %s;\n", i->name);
- printf("\n");
+ wl_array_init(&types);
+ wl_list_for_each(i, &protocol->interface_list, link) {
+ emit_types_forward_declarations(protocol, &i->request_list, &types);
+ emit_types_forward_declarations(protocol, &i->event_list, &types);
+ }
wl_list_for_each(i, &protocol->interface_list, link) {
+ p = fail_on_null(wl_array_add(&types, sizeof *p));
+ *p = i->name;
+ }
+
+ qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names);
+ prev = NULL;
+ wl_array_for_each(p, &types) {
+ if (prev && strcmp(*p, prev) == 0)
+ continue;
+ printf("struct %s;\n", *p);
+ prev = *p;
+ }
+ printf("\n");
+
+ prev = NULL;
+ wl_array_for_each(p, &types) {
+ if (prev && strcmp(*p, prev) == 0)
+ continue;
printf("extern const struct wl_interface "
- "%s_interface;\n",
- i->name);
+ "%s_interface;\n", *p);
+ prev = *p;
}
+
+ wl_array_release(&types);
printf("\n");
wl_list_for_each(i, &protocol->interface_list, link) {
@@ -1044,41 +1127,6 @@ emit_header(struct protocol *protocol, enum side side)
}
static void
-emit_types_forward_declarations(struct protocol *protocol,
- struct wl_list *message_list,
- struct wl_array *types)
-{
- struct message *m;
- struct arg *a;
- int length;
- char **p;
-
- wl_list_for_each(m, message_list, link) {
- length = 0;
- m->all_null = 1;
- wl_list_for_each(a, &m->arg_list, link) {
- length++;
- switch (a->type) {
- case NEW_ID:
- case OBJECT:
- if (!a->interface_name)
- continue;
-
- m->all_null = 0;
- p = fail_on_null(wl_array_add(types, sizeof *p));
- *p = a->interface_name;
- break;
- default:
- break;
- }
- }
-
- if (m->all_null && length > protocol->null_run_length)
- protocol->null_run_length = length;
- }
-}
-
-static void
emit_null_run(struct protocol *protocol)
{
int i;
@@ -1181,14 +1229,6 @@ emit_messages(struct wl_list *message_list,
printf("};\n\n");
}
-static int
-cmp_names(const void *p1, const void *p2)
-{
- const char * const *s1 = p1, * const *s2 = p2;
-
- return strcmp(*s1, *s2);
-}
-
static void
emit_code(struct protocol *protocol)
{
@@ -1260,33 +1300,82 @@ int main(int argc, char *argv[])
FILE *input = stdin;
int len;
void *buf;
+ bool help = false, core_headers = false;
+ bool fail = false;
+ int opt, option_index = 0;
enum {
CLIENT_HEADER,
SERVER_HEADER,
CODE,
} mode;
- if (argc != 2 && argc != 4)
+ static const struct option options[] = {
+ {"help", no_argument, 0, 0 },
+ {"include-core-only", no_argument, 0, 0 },
+ {0, 0, 0, 0 }
+ };
+
+ while (1) {
+ opt = getopt_long(argc, argv, "hc",
+ options, &option_index);
+
+ if (opt == -1)
+ break;
+
+ if (opt == 0) {
+ switch (option_index) {
+ case 0:
+ help = true;
+ break;
+ case 1:
+ core_headers = true;
+ break;
+ default:
+ fail = true;
+ break;
+ }
+ continue;
+ }
+
+ switch (opt) {
+ case 'h':
+ help = true;
+ break;
+ case 'c':
+ core_headers = true;
+ break;
+ default:
+ fail = true;
+ break;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (help)
+ usage(EXIT_SUCCESS);
+ else if ((argc != 1 && argc != 3) || fail)
usage(EXIT_FAILURE);
- else if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0)
+ else if (strcmp(argv[0], "help") == 0)
usage(EXIT_SUCCESS);
- else if (strcmp(argv[1], "client-header") == 0)
+ else if (strcmp(argv[0], "client-header") == 0)
mode = CLIENT_HEADER;
- else if (strcmp(argv[1], "server-header") == 0)
+ else if (strcmp(argv[0], "server-header") == 0)
mode = SERVER_HEADER;
- else if (strcmp(argv[1], "code") == 0)
+ else if (strcmp(argv[0], "code") == 0)
mode = CODE;
else
usage(EXIT_FAILURE);
- if (argc == 4) {
- input = fopen(argv[2], "r");
+ if (argc == 3) {
+ input = fopen(argv[1], "r");
if (input == NULL) {
fprintf(stderr, "Could not open input file: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
- if (freopen(argv[3], "w", stdout) == NULL) {
+ if (freopen(argv[2], "w", stdout) == NULL) {
fprintf(stderr, "Could not open output file: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
@@ -1297,6 +1386,7 @@ int main(int argc, char *argv[])
protocol.type_index = 0;
protocol.null_run_length = 0;
protocol.copyright = NULL;
+ protocol.core_headers = core_headers;
memset(&ctx, 0, sizeof ctx);
ctx.protocol = &protocol;
--
2.3.6
More information about the wayland-devel
mailing list