diff options
author | Uli Schlachter <psychon@znc.in> | 2015-03-24 21:18:53 +0100 |
---|---|---|
committer | Uli Schlachter <psychon@znc.in> | 2015-03-24 21:18:53 +0100 |
commit | 278a19c56676ef24a57020f2b3d78c44ee9faaf9 (patch) | |
tree | d5f586aad2b7bcd0fd134d9376eda21b9779081d | |
parent | 71b018acc7e2719f8404b628fcff725521716af7 (diff) |
Implement a working code generator
With this change, the output of the code generator actually compiles and can be
linked into a library. This also changes the API between the generated code and
the library code. Hopefully, this API is nicer.
The code generator generates a function register_extensions() that looks up all
extensions and calls register_extension() for each one. Also, a global variable
xproto_info is exported which contains the information for all core requests and
also provides fallback names for unknown major codes / event codes / error
codes.
Signed-off-by: Uli Schlachter <psychon@znc.in>
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | src/errors.h | 16 | ||||
-rwxr-xr-x | src/extensions.py | 35 | ||||
-rw-r--r-- | src/static_tables.c | 72 | ||||
-rw-r--r-- | src/xcb_errors.c | 60 |
6 files changed, 61 insertions, 134 deletions
@@ -1,2 +1,2 @@ src/libxcb_errors.so -src/static_tables.inc +src/extensions.c @@ -1,8 +1,13 @@ FLAGS=-std=gnu89 -Wall -Wextra -lxcb -fpic -shared -Wl,-no-undefined # -Wl,-export-symbols-regex,'^xcb_errors_' -src/libxcb_errors.so: $(wildcard src/*.c) $(wildcard *.h) Makefile src/static_tables.inc syms +all: src/libxcb_errors.so + +src/libxcb_errors.so: $(wildcard src/*.c) $(wildcard *.h) src/extensions.c Makefile syms gcc $(FLAGS) -Wl,--retain-symbols-file=syms -o $@ $(wildcard src/*.c) +src/extensions.c: src/extensions.py + PYTHONPATH=/home/psychon/projects/proto/ src/extensions.py $@ /home/psychon/projects/proto/src/*xml + syms: echo xcb_errors_context_new > $@ echo xcb_errors_context_free > $@ @@ -10,6 +15,3 @@ syms: echo xcb_errors_get_name_for_minor_code > $@ echo xcb_errors_get_name_for_event > $@ echo xcb_errors_get_name_for_error > $@ - -src/static_tables.inc: - for x in $$(seq 0 255) ; do echo "ENTRY($$x)" ; done > $@ diff --git a/src/errors.h b/src/errors.h index 25b2c61..f854bcb 100644 --- a/src/errors.h +++ b/src/errors.h @@ -30,20 +30,18 @@ struct static_extension_info_t { uint16_t num_minor; - uint8_t num_events; - uint8_t num_errors; + uint16_t num_events; + uint16_t num_errors; const char *strings_minor; const char *strings_events; const char *strings_errors; }; -extern const char unknown_major_code[]; -extern const char unknown_error_code[]; -extern const char unknown_event_code[]; +extern const struct static_extension_info_t xproto_info; -const char *xproto_get_name_for_major_code(uint8_t major_code); -const char *xproto_get_name_for_event(uint8_t event_code); -const char *xproto_get_name_for_error(uint8_t error_code); -struct static_extension_info_t find_static_info_for_extension(const char *name); +int register_extensions(xcb_errors_context_t *ctx, xcb_connection_t *conn); +int register_extension(xcb_errors_context_t *ctx, xcb_connection_t *conn, + xcb_query_extension_cookie_t cookie, const char *name, + const struct static_extension_info_t static_info); #endif /* __ERRORS_H__ */ diff --git a/src/extensions.py b/src/extensions.py index 7ea3637..39e4c1a 100755 --- a/src/extensions.py +++ b/src/extensions.py @@ -53,16 +53,27 @@ class Module(object): return names modules = [] +xproto = None def parseFile(filename): - modules.append(Module(filename)) + global xproto + mod = Module(filename) + if mod.is_ext: + modules.append(mod) + else: + assert xproto == None + xproto = mod # Parse the xml file output_file = sys.argv[1] for input_file in sys.argv[2:]: parseFile(input_file) +assert xproto != None + output = open(output_file, "w") output.write("#include \"errors.h\"\n") +output.write("#include <string.h>\n") +output.write("\n") def format_strings(name, table): if table is None: @@ -72,14 +83,32 @@ def format_strings(name, table): output.write("\t.num_%s = %d,\n" % (name, len(table))) output.write("\t.strings_%s = \"%s\\0\",\n" % (name, "\\0".join(table))) -for module in modules: +def emit_module(module): t = "" + prefix = "extension_" if module.is_ext: t = "static " - output.write("%sconst struct static_extension_info_t extension_%s_info = { // %s\n" % (t, module.name, module.xname)) + else: + prefix = "" + output.write("%sconst struct static_extension_info_t %s%s_info = { // %s\n" % (t, prefix, module.name, module.xname)) format_strings("minor", module.requests_table) format_strings("events", module.events_table) format_strings("errors", module.errors_table) output.write("};\n\n") +for module in modules: + emit_module(module) +emit_module(xproto) + +output.write("int register_extensions(xcb_errors_context_t *ctx, xcb_connection_t *conn)\n"); +output.write("{\n"); +output.write("\txcb_query_extension_cookie_t cookies[%d];\n" % len(modules)); +output.write("\tint ret = 0;\n"); +for idx in range(len(modules)): + output.write("\tcookies[%d] = xcb_query_extension(conn, strlen(\"%s\"), \"%s\");\n" % (idx, modules[idx].xname, modules[idx].xname)); +for idx in range(len(modules)): + output.write("\tret |= register_extension(ctx, conn, cookies[%d], \"%s\", extension_%s_info);\n" % (idx, modules[idx].name, modules[idx].name)); +output.write("\treturn ret;\n"); +output.write("}\n"); + output.close() diff --git a/src/static_tables.c b/src/static_tables.c deleted file mode 100644 index 3a0d797..0000000 --- a/src/static_tables.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright © 2015 Uli Schlachter - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the names of the authors or their - * institutions shall not be used in advertising or otherwise to promote the - * sale, use or other dealings in this Software without prior written - * authorization from the authors. - */ - -#include "errors.h" - -const char unknown_major_code[] = { -#define ENTRY(i) "Unknown major code " #i "\0" -#include "static_tables.inc" -#undef ENTRY -}; - -const char unknown_error_code[] = { -#define ENTRY(i) "Unknown error " #i "\0" -#include "static_tables.inc" -#undef ENTRY -}; - -const char unknown_event_code[] = { -#define ENTRY(i) "Unknown event " #i "\0" -#include "static_tables.inc" -#undef ENTRY -}; - -#warning TODO: Implement these -const char *xproto_get_name_for_major_code(uint8_t major_code) { - (void) major_code; - return NULL; -} - -const char *xproto_get_name_for_event(uint8_t event_code) { - (void) event_code; - return NULL; -} - -const char *xproto_get_name_for_error(uint8_t error_code) { - (void) error_code; - return NULL; -} -struct static_extension_info_t find_static_info_for_extension(const char *name) { - struct static_extension_info_t info = { - .num_minor = 0, - .num_events = 0, - .num_errors = 0, - .strings_minor = NULL, - .strings_events = NULL, - .strings_errors = NULL - }; - (void) name; - return info; -} diff --git a/src/xcb_errors.c b/src/xcb_errors.c index f33966a..6f2f1ac 100644 --- a/src/xcb_errors.c +++ b/src/xcb_errors.c @@ -36,7 +36,7 @@ struct extension_info_t { uint8_t major_opcode; uint8_t first_event; uint8_t first_error; - char *name; + const char *name; }; struct xcb_errors_context_t { @@ -49,30 +49,26 @@ static const char *get_strings_entry(const char *strings, unsigned int index) { return strings; } -static int register_extension(xcb_errors_context_t *ctx, xcb_connection_t *conn, const char *ext) +int register_extension(xcb_errors_context_t *ctx, xcb_connection_t *conn, + xcb_query_extension_cookie_t cookie, const char *name, + const struct static_extension_info_t static_info) { struct extension_info_t *info; - struct static_extension_info_t static_info; xcb_query_extension_reply_t *reply; - char *ext_dup; - ext_dup = strdup(ext); info = calloc(1, sizeof(*info)); - reply = xcb_query_extension_reply(conn, - xcb_query_extension(conn, strlen(ext), ext), NULL); - static_info = find_static_info_for_extension(ext); + reply = xcb_query_extension_reply(conn, cookie, NULL); - if (!info || !reply || !ext_dup || !reply->present || (static_info.num_minor == 0)) { + if (!info || !reply || !reply->present) { + int had_error = !reply || reply->present; free(info); free(reply); - free(ext_dup); - /* This is used to indicate an unsupported extension */ - if (static_info.num_minor == 0) - return 0; - return -1; + if (had_error) + return -1; + return 0; } - info->name = ext_dup; + info->name = name; info->static_info = static_info; info->major_opcode = reply->major_opcode; info->first_event = reply->first_event; @@ -88,8 +84,6 @@ static int register_extension(xcb_errors_context_t *ctx, xcb_connection_t *conn, int xcb_errors_context_new(xcb_connection_t *conn, xcb_errors_context_t **c) { xcb_errors_context_t *ctx = NULL; - xcb_list_extensions_reply_t *reply = NULL; - xcb_str_iterator_t iter; if ((*c = calloc(1, sizeof(*c))) == NULL) goto error_out; @@ -97,26 +91,12 @@ int xcb_errors_context_new(xcb_connection_t *conn, xcb_errors_context_t **c) ctx = *c; ctx->extensions = NULL; - reply = xcb_list_extensions_reply(conn, - xcb_list_extensions(conn), NULL); - if (!reply) + if (!register_extensions(ctx, conn)) goto error_out; - // TODO: Make this do all the query_extension requests first and then - // collect the results. Less roundtrips. - iter = xcb_list_extensions_names_iterator(reply); - while (iter.rem > 0) { - int status = register_extension(ctx, conn, xcb_str_name(iter.data)); - if (status < 0) - goto error_out; - xcb_str_next(&iter); - } - - free(reply); return 0; error_out: - free(reply); xcb_errors_context_free(ctx); *c = NULL; return -1; @@ -133,7 +113,6 @@ void xcb_errors_context_free(xcb_errors_context_t *ctx) while (info) { struct extension_info_t *prev = info; info = info->next; - free(prev->name); free(prev); } @@ -144,15 +123,12 @@ const char *xcb_errors_get_name_for_major_code(xcb_errors_context_t *ctx, uint8_t major_code) { struct extension_info_t *info = ctx->extensions; - const char *result = xproto_get_name_for_major_code(major_code); - if (result) - return result; while (info && info->major_opcode != major_code) info = info->next; if (info == NULL) - return get_strings_entry(unknown_major_code, major_code); + return get_strings_entry(xproto_info.strings_minor, major_code); return info->name; } @@ -176,15 +152,12 @@ const char *xcb_errors_get_name_for_event(xcb_errors_context_t *ctx, uint8_t event_code) { struct extension_info_t *info = ctx->extensions; - const char *result = xproto_get_name_for_event(event_code); - if (result) - return result; while (info && !IS_IN_RANGE(event_code, info->first_event, info->static_info.num_events)) info = info->next; if (info == NULL) - return get_strings_entry(unknown_event_code, event_code); + return get_strings_entry(xproto_info.strings_events, event_code); return get_strings_entry(info->static_info.strings_events, event_code - info->first_event); } @@ -193,15 +166,12 @@ const char *xcb_errors_get_name_for_error(xcb_errors_context_t *ctx, uint8_t error_code) { struct extension_info_t *info = ctx->extensions; - const char *result = xproto_get_name_for_error(error_code); - if (result) - return result; while (info && !IS_IN_RANGE(error_code, info->first_error, info->static_info.num_errors)) info = info->next; if (info == NULL) - return get_strings_entry(unknown_error_code, error_code); + return get_strings_entry(xproto_info.strings_errors, error_code); return get_strings_entry(info->static_info.strings_errors, error_code - info->first_error); } |