X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/blobdiff_plain/0a55ae84545c5e5a45e2240c06bd77a1917f7d3e..HEAD:/src/uobject/module.c diff --git a/src/uobject/module.c b/src/uobject/module.c index 2fa4402..1d41d07 100644 --- a/src/uobject/module.c +++ b/src/uobject/module.c @@ -1,21 +1,22 @@ /* - * upkg: tool for manipulating Unreal Tournament packages. - * Copyright (C) 2009 Nick Bowler + * upkg: tool for manipulating Unreal Tournament packages. + * Copyright © 2009-2012, 2022 Nick Bowler * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ +#include #include #include #include @@ -24,7 +25,9 @@ #include #include +#include #include +#include #include "avl.h" static unsigned initialized; @@ -75,32 +78,106 @@ int u_object_module_exit(void) return 0; } -GType u_object_module_get_class(const char *package, const char *class) +static int lookup_module(GTypeModule **out, const char *name) { - char buf[strlen(package) + strlen(class) + 1]; - GTypeModule search = { .name = str_cpy_lower(buf, package) }; + GTypeModule *result, key = {0}; + char *buf; - GTypeModule *mod = avl_find(package_tree, &search); - if (!mod) { + buf = malloc(strlen(name) + 1); + if (!buf) + return -1; + + key.name = str_cpy_lower(buf, name); + result = avl_find(package_tree, &key); + free(buf); + + *out = result; + return 0; +} + +GTypeModule * +u_module_get_from_import(GTypeModule *pkg, const struct upkg_import *i) +{ + GTypeModule *result; + + while (i->parent != NULL) + i = i->parent; + + if (strcmp(i->class_package, "Core") != 0 + || strcmp(i->class_name, "Package") != 0) { + u_err(pkg, "import root must be an instance of Core.Package"); + return NULL; + } + + if (lookup_module(&result, i->name) != 0) { + u_err(pkg, "fatal error performing package lookup"); + return NULL; + } + + if (!result) { void **p; - mod = u_pkg_open(package); - if (!mod) { - return 0; + result = u_pkg_open(i->name); + if (!result) { + u_warn(pkg, "failed to open package: %s", i->name); + return NULL; } - p = avl_probe(package_tree, mod); + p = avl_probe(package_tree, result); if (!p) { - g_object_unref(mod); + u_err(pkg, "fatal error inserting package"); + g_object_unref(result); + return NULL; + } + } + + return result; +} + +GType u_object_module_get_class(GTypeModule *pkg, long class) +{ + GTypeModule *mod; + const char *classname; + + if (class == 0) { + u_warn(pkg, "class implementations not supported yet"); + return 0; + } else if (class < 0) { + const struct upkg_import *import; + + import = upkg_get_import(U_PKG(pkg)->pkg, -(class+1)); + if (!import) { + u_err(pkg, "invalid package import: %ld", -(class+1)); return 0; } + + mod = u_module_get_from_import(pkg, import); + if (!mod) + return 0; + + classname = import->name; + } else if (class > 0) { + const struct upkg_export *export; + + export = upkg_get_export(U_PKG(pkg)->pkg, class-1); + if (!export) { + u_err(pkg, "invalid package export: %ld", class-1); + return 0; + } + + mod = pkg; + classname = export->name; } if (!g_type_module_use(mod)) return 0; - str_cpy_lower(buf+strlen(package), class); - buf[0] = toupper(buf[0]); - buf[strlen(package)] = toupper(buf[strlen(package)]); - return g_type_from_name(buf); + /* XXX: Do this better. */ + char typename[strlen(mod->name) + strlen(classname) + 1]; + str_cpy_lower(typename, mod->name); + str_cpy_lower(typename+strlen(mod->name), classname); + typename[0] = toupper(typename[0]); + typename[strlen(mod->name)] = toupper(typename[strlen(mod->name)]); + + return g_type_from_name(typename); }