]> git.draconx.ca Git - upkg.git/commitdiff
uobject: Make module loader understand exports/imports.
authorNick Bowler <nbowler@draconx.ca>
Mon, 21 May 2012 01:34:42 +0000 (21:34 -0400)
committerNick Bowler <nbowler@draconx.ca>
Mon, 21 May 2012 01:34:42 +0000 (21:34 -0400)
It's possible for a package to have an instance of a class defined in
that same package; therefore the module loader needs to know about this.
Bring the export class index up to the public struct so that it's
possible to tell the difference.

This makes it possible to export the textures defined in Engine.u.
There's still a few vestigial bugs left over here, but we can fix those
later.

src/libupkg.c
src/uobject/module.c
src/uobject/module.h
src/uobject/uobject.c
src/upkg.h

index f1424e8977048e70e19cdb44dac42036207d874a..d4978a39bd89adabcb06d31ae412f479be13d7fb 100644 (file)
@@ -46,7 +46,7 @@ struct upkg_name {
 struct upkg_export_priv {
        struct upkg_export pub;
 
-       long class, super;
+       long super;
        unsigned long size, offset;
 };
 
@@ -282,7 +282,7 @@ static int pkg_init_exports(struct upkg_priv *pkg)
                }
 
                len = 0;
-               rc = upkg_decode_index(&export->class, buf+len, nbuf-len);
+               rc = upkg_decode_index(&export->pub.class, buf+len, nbuf-len);
                if (rc == 0) goto err;
                len += rc;
 
@@ -556,15 +556,15 @@ const char *upkg_export_class(struct upkg *pub, unsigned long idx,
        export = &pkg->exports[idx];
 
        /* Assumption: class references are always imports. */
-       format_assert(export->class <= 0, return NULL);
+       format_assert(export->pub.class <= 0, return NULL);
 
        /* Get the class. */
-       if (export->class == 0) {
+       if (export->pub.class == 0) {
                if (package) *package = "Core";
                return "Class";
        }
 
-       pkg_idx = -(export->class + 1);
+       pkg_idx = -(export->pub.class + 1);
        if (pkg_idx >= pkg->pub.import_count)
                return NULL;
        iclass = &pkg->imports[pkg_idx];
index 88748a02f20f0e24eb440519a522fbb9fb8f35e3..057d1d0080ee23d685baf05113862208a8cace3d 100644 (file)
@@ -24,7 +24,9 @@
 #include <ltdl.h>
 
 #include <uobject/module.h>
+#include <uobject/uobject.h>
 #include <uobject/package.h>
+#include <upkg.h>
 #include "avl.h"
 
 static unsigned initialized;
@@ -75,32 +77,109 @@ 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) };
+       struct { GTypeModule pkg; char buf[]; } *search_key;
+       GTypeModule *result;
 
-       GTypeModule *mod = avl_find(package_tree, &search);
-       if (!mod) {
+       search_key = malloc(sizeof *search_key + strlen(name) + 1);
+       if (!search_key)
+               return -1;
+
+       search_key->pkg = (GTypeModule) {
+               .name = str_cpy_lower(search_key->buf, name),
+       };
+
+       result = avl_find(package_tree, search_key);
+       free(search_key);
+
+       *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);
 }
index 28035264da03a960b0912dfb7744f3f38fa7912f..e4fd5a6245d8ac9e79f3a4d1d704feddcbf38f67 100644 (file)
@@ -35,12 +35,13 @@ int u_object_module_init(void);
 int u_object_module_exit(void);
 
 /*
- * Get a class handle from the UObject module system.  This will load the
- * appropriate shared object if necessary.  The resulting handle can then be
- * used to create instances of the class with g_object_new.
+ * Get a class handle from the UObject module system, where class is an
+ * object reference for the class within the provided package.  This will load
+ * the appropriate shared object if necessary.  The resulting handle can then
+ * be used to create instances of the class with g_object_new.
  *
  * Returns 0 on failure.
  */
-GType u_object_module_get_class(const char *package, const char *class);
+GType u_object_module_get_class(GTypeModule *pkg, long class);
 
 #endif
index 360dd31d2614e586b96d0250983a1b196b9f3fe7..9c5bfa13a3ccc9949a4cc687dab2067aa83f8c3b 100644 (file)
@@ -524,15 +524,17 @@ GObject *u_object_new_from_package(GTypeModule *pkg, unsigned long idx)
 {
        g_return_val_if_fail(IS_U_PKG(pkg), NULL);
 
-       const char *class, *package;
+       const struct upkg_export *export;
        GObject *obj = NULL;
        GType type;
 
-       class = upkg_export_class(U_PKG(pkg)->pkg, idx, &package);
-       if (!class)
+       export = upkg_get_export(U_PKG(pkg)->pkg, idx);
+       if (!export) {
+               u_err(pkg, "invalid package export: %lu", idx);
                return NULL;
+       }
 
-       type = u_object_module_get_class(package, class);
+       type = u_object_module_get_class(pkg, export->class);
        if (type) {
                obj = g_object_new(type, NULL);
                if (u_object_deserialize(obj, pkg, idx) != 0) {
index e4e5dcdeba38acc948951eed2c06a47f940ef170..d236714f091b0e165d44c91de9ce687cab04ff2c 100644 (file)
@@ -82,6 +82,7 @@ struct upkg_export {
 
        const char *name;
        unsigned long flags;
+       long class;
 };
 
 struct upkg_import {