X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/8445442abc02fc325a9ce228759403113583818c..43115cbfefb29535b3e9da83ab247a7f24c6994b:/src/main.c diff --git a/src/main.c b/src/main.c index 9a9a1ac..6a0c791 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ * Copyright (C) 1999,2000 the Free Software Foundation. * Copyright (C) 2000 Eazel, Inc. * Copyright (C) 2001-2011 George (Jiri) Lebl + * Copyright © 2019-2020 Nick Bowler * * Author: George (Jiri) Lebl * @@ -1126,6 +1127,55 @@ add_interfaces (void) } } +static void +add_dynamic_interfaces(void) +{ + GList *li = ((Class *)class)->interfaces; + + if (li) { + /* + * Hack to work around bug in g_type_module_add_interface, + * which will fail to add an interface to types that derive + * from something that also implements the same interface. + * + * The actual GType system does not have any such problem, + * and the GTypeModule implementation details relied upon + * here have not changed once since the feature was first + * implemented almost 20 years ago. + */ + out_printf(out, "\t\tstruct _ModuleInterfaceInfo {\n" + "\t\t\tgboolean loaded;\n" + "\t\t\tGType instance_type;\n" + "\t\t\tGType interface_type;\n" + "\t\t\tGInterfaceInfo info;\n" + "\t\t} *modinfo;\n"); + } + + for (; li; li = li->next) { + char *name = replace_sep(li->data, '_'); + char *type = make_pre_macro(li->data, "TYPE"); + + out_printf(out, "\n" + "\t\tmodinfo = g_malloc(sizeof *modinfo);\n" + "\t\tmodinfo->loaded = TRUE;\n" + "\t\tmodinfo->instance_type = %s_type_id;\n" + "\t\tmodinfo->interface_type = %s;\n" + "\t\tmodinfo->info = %s_info;\n" + "\t\tg_type_add_interface_dynamic\n" + "\t\t\t( modinfo->instance_type\n" + "\t\t\t, modinfo->interface_type\n" + "\t\t\t, G_TYPE_PLUGIN(type_module)\n" + "\t\t\t);\n" + "\t\ttype_module->interface_infos = g_slist_prepend\n" + "\t\t\t( type_module->interface_infos\n" + "\t\t\t, modinfo\n" + "\t\t\t);\n", funcbase, type, name); + + g_free(type); + g_free(name); + } +} + static void add_get_type(void) { @@ -1174,6 +1224,57 @@ add_get_type(void) "}\n\n"); } +static void +add_dynamic_get_type (void) +{ + out_printf(out, + "static GType %s_type_id;\n\n" + "GType\n" + "%s_get_type (void)\n" + "{\n" + "\treturn %s_type_id;\n" + "}\n\n", + funcbase, funcbase, funcbase); + + out_printf(out, + "void\n" + "%s_register_type (GTypeModule *type_module)\n" + "{\n" + "\tstatic const GTypeInfo info = {\n" + "\t\tsizeof (%sClass),\n" + "\t\t(GBaseInitFunc) NULL,\n" + "\t\t(GBaseFinalizeFunc) NULL,\n" + "\t\t(GClassInitFunc) %s_class_init,\n" + "\t\t(GClassFinalizeFunc) NULL,\n" + "\t\tNULL /* class_data */,\n" + "\t\tsizeof (%s),\n" + "\t\t%d /* n_preallocs */,\n" + "\t\t(GInstanceInitFunc) %s_init,\n" + "\t\tNULL\n" + "\t};\n\n", + funcbase, typebase, funcbase, typebase, prealloc, funcbase); + + add_interface_infos(); + + out_printf(out, + "\t%s_type_id = g_type_module_register_type(\n" + "\t\ttype_module,\n" + "\t\t%s,\n" + "\t\t\"%s\",\n" + "\t\t&info,\n" + "\t\t(GTypeFlags)%s\n" + "\t);\n\n" + "\t{\n", + funcbase, pmacrotype, typebase, + ((Class *)class)->abstract ? "G_TYPE_FLAG_ABSTRACT" : "0"); + + add_dynamic_interfaces(); + + out_printf(out, + "\t}\n" + "}\n\n"); +} + static void add_bonobo_object_get_type (void) { @@ -3652,8 +3753,23 @@ print_class_block(Class *c) " * Public methods\n" " */\n"); - if ( ! overrode_get_type) { - out_printf (outh, "GType\t%s_get_type\t(void) G_GNUC_CONST;\n", funcbase); + if (!overrode_get_type) { + /* + * For ordinary "static" types it should be safe to mark the + * get_type implementation as const, since the get_type + * function return really is constant at the call boundary + * (even though there is an initial setup on the first call). + * But for dynamic types, since the registration is explicitly + * separated, we need to settle for "pure" as the results of + * get_type differ before and after type registration. + */ + out_printf(outh, "GType\t%s_get_type\t(void) %s;\n", funcbase, + c->dynamic ? "G_GNUC_PURE" : "G_GNUC_CONST"); + } + + if (c->dynamic) { + out_printf(outh, "void\t%s_register_type\t(GTypeModule *);\n", + funcbase); } for(li = c->nodes; li != NULL; li = li->next) { @@ -3721,11 +3837,13 @@ print_class_block(Class *c) add_interface_inits (c); - if ( ! overrode_get_type) { + if (!overrode_get_type) { if (c->bonobo_object_class != NULL) - add_bonobo_object_get_type (); + add_bonobo_object_get_type(); + else if (c->dynamic) + add_dynamic_get_type(); else - add_get_type (); + add_get_type(); } out_printf (out, "/* a macro for creating a new object of our type */\n");