mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	scanner: add a new --include-core-only option
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. Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
		
							parent
							
								
									ea73cb00bc
								
							
						
					
					
						commit
						e799b1fa9c
					
				
					 1 changed files with 168 additions and 78 deletions
				
			
		
							
								
								
									
										246
									
								
								src/scanner.c
									
										
									
									
									
								
							
							
						
						
									
										246
									
								
								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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -984,65 +991,6 @@ format_copyright(const char *copyright)
 | 
			
		|||
	printf(" */\n\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_header(struct protocol *protocol, enum side side)
 | 
			
		||||
{
 | 
			
		||||
	struct interface *i;
 | 
			
		||||
	const char *s = (side == SERVER) ? "SERVER" : "CLIENT";
 | 
			
		||||
 | 
			
		||||
	if (protocol->copyright)
 | 
			
		||||
		format_copyright(protocol->copyright);
 | 
			
		||||
 | 
			
		||||
	printf("#ifndef %s_%s_PROTOCOL_H\n"
 | 
			
		||||
	       "#define %s_%s_PROTOCOL_H\n"
 | 
			
		||||
	       "\n"
 | 
			
		||||
	       "#ifdef  __cplusplus\n"
 | 
			
		||||
	       "extern \"C\" {\n"
 | 
			
		||||
	       "#endif\n"
 | 
			
		||||
	       "\n"
 | 
			
		||||
	       "#include <stdint.h>\n"
 | 
			
		||||
	       "#include <stddef.h>\n"
 | 
			
		||||
	       "#include \"%s\"\n\n"
 | 
			
		||||
	       "struct wl_client;\n"
 | 
			
		||||
	       "struct wl_resource;\n\n",
 | 
			
		||||
	       protocol->uppercase_name, s,
 | 
			
		||||
	       protocol->uppercase_name, s,
 | 
			
		||||
	       (side == SERVER) ? "wayland-server.h" : "wayland-client.h");
 | 
			
		||||
 | 
			
		||||
	wl_list_for_each(i, &protocol->interface_list, link)
 | 
			
		||||
		printf("struct %s;\n", i->name);
 | 
			
		||||
	printf("\n");
 | 
			
		||||
 | 
			
		||||
	wl_list_for_each(i, &protocol->interface_list, link) {
 | 
			
		||||
		printf("extern const struct wl_interface "
 | 
			
		||||
		       "%s_interface;\n",
 | 
			
		||||
		       i->name);
 | 
			
		||||
	}
 | 
			
		||||
	printf("\n");
 | 
			
		||||
 | 
			
		||||
	wl_list_for_each(i, &protocol->interface_list, link) {
 | 
			
		||||
 | 
			
		||||
		emit_enumerations(i);
 | 
			
		||||
 | 
			
		||||
		if (side == SERVER) {
 | 
			
		||||
			emit_structs(&i->request_list, i, side);
 | 
			
		||||
			emit_opcodes(&i->event_list, i);
 | 
			
		||||
			emit_opcode_versions(&i->event_list, i);
 | 
			
		||||
			emit_event_wrappers(&i->event_list, i);
 | 
			
		||||
		} else {
 | 
			
		||||
			emit_structs(&i->event_list, i, side);
 | 
			
		||||
			emit_opcodes(&i->request_list, i);
 | 
			
		||||
			emit_stubs(&i->request_list, i);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printf("#ifdef  __cplusplus\n"
 | 
			
		||||
	       "}\n"
 | 
			
		||||
	       "#endif\n"
 | 
			
		||||
	       "\n"
 | 
			
		||||
	       "#endif\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_types_forward_declarations(struct protocol *protocol,
 | 
			
		||||
				struct wl_list *message_list,
 | 
			
		||||
| 
						 | 
				
			
			@ -1078,6 +1026,106 @@ emit_types_forward_declarations(struct protocol *protocol,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
	printf("#ifndef %s_%s_PROTOCOL_H\n"
 | 
			
		||||
	       "#define %s_%s_PROTOCOL_H\n"
 | 
			
		||||
	       "\n"
 | 
			
		||||
	       "#ifdef  __cplusplus\n"
 | 
			
		||||
	       "extern \"C\" {\n"
 | 
			
		||||
	       "#endif\n"
 | 
			
		||||
	       "\n"
 | 
			
		||||
	       "#include <stdint.h>\n"
 | 
			
		||||
	       "#include <stddef.h>\n"
 | 
			
		||||
	       "#include \"%s\"\n\n"
 | 
			
		||||
	       "struct wl_client;\n"
 | 
			
		||||
	       "struct wl_resource;\n\n",
 | 
			
		||||
	       protocol->uppercase_name, s,
 | 
			
		||||
	       protocol->uppercase_name, s,
 | 
			
		||||
	       get_include_name(protocol->core_headers, side));
 | 
			
		||||
 | 
			
		||||
	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", *p);
 | 
			
		||||
		prev = *p;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_array_release(&types);
 | 
			
		||||
	printf("\n");
 | 
			
		||||
 | 
			
		||||
	wl_list_for_each(i, &protocol->interface_list, link) {
 | 
			
		||||
 | 
			
		||||
		emit_enumerations(i);
 | 
			
		||||
 | 
			
		||||
		if (side == SERVER) {
 | 
			
		||||
			emit_structs(&i->request_list, i, side);
 | 
			
		||||
			emit_opcodes(&i->event_list, i);
 | 
			
		||||
			emit_opcode_versions(&i->event_list, i);
 | 
			
		||||
			emit_event_wrappers(&i->event_list, i);
 | 
			
		||||
		} else {
 | 
			
		||||
			emit_structs(&i->event_list, i, side);
 | 
			
		||||
			emit_opcodes(&i->request_list, i);
 | 
			
		||||
			emit_stubs(&i->request_list, i);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printf("#ifdef  __cplusplus\n"
 | 
			
		||||
	       "}\n"
 | 
			
		||||
	       "#endif\n"
 | 
			
		||||
	       "\n"
 | 
			
		||||
	       "#endif\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_null_run(struct protocol *protocol)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
		usage(EXIT_FAILURE);
 | 
			
		||||
	else if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0)
 | 
			
		||||
	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 (strcmp(argv[1], "client-header") == 0)
 | 
			
		||||
	else if ((argc != 1 && argc != 3) || fail)
 | 
			
		||||
		usage(EXIT_FAILURE);
 | 
			
		||||
	else if (strcmp(argv[0], "help") == 0)
 | 
			
		||||
		usage(EXIT_SUCCESS);
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue