You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2012/04/14 16:04:18 UTC

[lucy-commits] svn commit: r1326105 - in /lucy/trunk: clownfish/perl/lib/Clownfish/ clownfish/src/ core/Lucy/Object/

Author: nwellnhof
Date: Sat Apr 14 14:04:17 2012
New Revision: 1326105

URL: http://svn.apache.org/viewvc?rev=1326105&view=rev
Log:
Initialize VTables during run-time

Modified:
    lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs
    lucy/trunk/clownfish/src/CFCBindAliases.c
    lucy/trunk/clownfish/src/CFCBindClass.c
    lucy/trunk/clownfish/src/CFCBindClass.h
    lucy/trunk/clownfish/src/CFCBindCore.c
    lucy/trunk/clownfish/src/CFCPerl.c
    lucy/trunk/core/Lucy/Object/VTable.c
    lucy/trunk/core/Lucy/Object/VTable.cfh

Modified: lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs
URL: http://svn.apache.org/viewvc/lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs?rev=1326105&r1=1326104&r2=1326105&view=diff
==============================================================================
--- lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs (original)
+++ lucy/trunk/clownfish/perl/lib/Clownfish/CFC.xs Sat Apr 14 14:04:17 2012
@@ -1804,10 +1804,10 @@ CODE:
 OUTPUT: RETVAL
 
 SV*
-to_c(self)
+to_c_data(self)
     CFCBindClass *self;
 CODE:
-    RETVAL = S_sv_eat_c_string(CFCBindClass_to_c(self));
+    RETVAL = S_sv_eat_c_string(CFCBindClass_to_c_data(self));
 OUTPUT: RETVAL
 
 SV*

Modified: lucy/trunk/clownfish/src/CFCBindAliases.c
URL: http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCBindAliases.c?rev=1326105&r1=1326104&r2=1326105&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCBindAliases.c (original)
+++ lucy/trunk/clownfish/src/CFCBindAliases.c Sat Apr 14 14:04:17 2012
@@ -95,6 +95,7 @@ struct alias aliases[] = {
 
     {"cfish_VTable", "lucy_VTable"},
     {"CFISH_VTABLE", "LUCY_VTABLE"},
+    {"cfish_VTable_bootstrap", "lucy_VTable_bootstrap"},
     {"cfish_VTable_add_to_registry", "lucy_VTable_add_to_registry"},
     {"cfish_VTable_add_alias_to_registry", "lucy_VTable_add_alias_to_registry"},
     {"cfish_VTable_offset_of_parent", "lucy_VTable_offset_of_parent"},

Modified: lucy/trunk/clownfish/src/CFCBindClass.c
URL: http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCBindClass.c?rev=1326105&r1=1326104&r2=1326105&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCBindClass.c (original)
+++ lucy/trunk/clownfish/src/CFCBindClass.c Sat Apr 14 14:04:17 2012
@@ -34,7 +34,7 @@ struct CFCBindClass {
     CFCBase base;
     CFCClass *client;
     char *full_callbacks_var;
-    char *full_name_var;
+    char *full_methods_var;
     char *short_names_macro;
 };
 
@@ -50,12 +50,6 @@ S_to_c_header_dynamic(CFCBindClass *self
 static char*
 S_struct_definition(CFCBindClass *self);
 
-/* C code defining the ZombieCharBuf which contains the class name for this
- * class.
- */
-static char*
-S_name_var_definition(CFCBindClass *self);
-
 // Return C code defining the class's VTable.
 static char*
 S_vtable_definition(CFCBindClass *self);
@@ -112,10 +106,10 @@ CFCBindClass_init(CFCBindClass *self, CF
     const char *full_vtable_var = CFCClass_full_vtable_var(client);
     const char *PREFIX = CFCClass_get_PREFIX(client);
     self->full_callbacks_var = (char*)MALLOCATE(strlen(full_vtable_var) + 20);
-    self->full_name_var      = (char*)MALLOCATE(strlen(full_vtable_var) + 20);
+    self->full_methods_var   = (char*)MALLOCATE(strlen(full_vtable_var) + 20);
     self->short_names_macro  = (char*)MALLOCATE(strlen(PREFIX) + 20);
     sprintf(self->full_callbacks_var, "%s_CALLBACKS", full_vtable_var);
-    sprintf(self->full_name_var, "%s_CLASS_NAME", full_vtable_var);
+    sprintf(self->full_methods_var, "%s_METHODS", full_vtable_var);
     sprintf(self->short_names_macro, "%sUSE_SHORT_NAMES", PREFIX);
 
     return self;
@@ -124,7 +118,7 @@ CFCBindClass_init(CFCBindClass *self, CF
 void
 CFCBindClass_destroy(CFCBindClass *self) {
     FREEMEM(self->full_callbacks_var);
-    FREEMEM(self->full_name_var);
+    FREEMEM(self->full_methods_var);
     FREEMEM(self->short_names_macro);
     CFCBase_decref((CFCBase*)self->client);
     CFCBase_destroy((CFCBase*)self);
@@ -290,7 +284,7 @@ S_to_c_header_dynamic(CFCBindClass *self
 }
 
 char*
-CFCBindClass_to_c(CFCBindClass *self) {
+CFCBindClass_to_c_data(CFCBindClass *self) {
     CFCClass *client = self->client;
 
     if (CFCClass_inert(client)) {
@@ -300,9 +294,8 @@ CFCBindClass_to_c(CFCBindClass *self) {
     const char *include_h = CFCClass_include_h(client);
     const char *autocode  = CFCClass_get_autocode(client);
     const char *vt_type   = CFCClass_full_vtable_type(client);
+    const char *vt_hidden = CFCClass_full_vtable_hidden(client);
     const char *cnick     = CFCClass_get_cnick(client);
-    char *class_name_def  = S_name_var_definition(self);
-    char *vtable_def      = S_vtable_definition(self);
 
     CFCMethod **methods  = CFCClass_methods(client);
     CFCMethod **fresh_methods = CFCClass_fresh_methods(client);
@@ -319,6 +312,10 @@ CFCBindClass_to_c(CFCBindClass *self) {
     cb_var = CFCUtil_cat(cb_var, "cfish_Callback *", self->full_callbacks_var,
                          "[] = {\n    ", NULL);
 
+    char *method_var = CFCUtil_strdup("");
+    method_var = CFCUtil_cat(method_var, "cfish_method_t ",
+                             self->full_methods_var, "[] = {\n    ", NULL);
+
     for (int meth_num = 0; methods[meth_num] != NULL; meth_num++) {
         CFCMethod *method = methods[meth_num];
         int method_is_fresh = S_method_is_fresh(method, fresh_methods);
@@ -365,11 +362,18 @@ CFCBindClass_to_c(CFCBindClass *self) {
             cb_var = CFCUtil_cat(cb_var, "&", full_cb_sym, ",\n    ", NULL);
         }
 
+        // Define method implementations.
+        const char *implementing_sym = CFCMethod_implementing_func_sym(method);
+        method_var = CFCUtil_cat(method_var, "(cfish_method_t)",
+                                 implementing_sym, ",\n    ", NULL);
+
         FREEMEM(offset_str);
     }
 
     // Close callbacks variable definition.
     cb_var =  CFCUtil_cat(cb_var, "NULL\n};\n", NULL);
+    // Close methods variable definition.
+    method_var =  CFCUtil_cat(method_var, "NULL\n};\n", NULL);
 
     const char pattern[] =
         "#include \"%s\"\n"
@@ -398,7 +402,7 @@ CFCBindClass_to_c(CFCBindClass *self) {
         "\n"
         "%s\n"
         "\n"
-        "/* Define the variable which holds this class's class name.\n"
+        "/* Define this class's method implementations.\n"
         " */\n"
         "\n"
         "%s\n"
@@ -406,7 +410,7 @@ CFCBindClass_to_c(CFCBindClass *self) {
         "/* Define this class's VTable.\n"
         " */\n"
         "\n"
-        "%s\n"
+        "%s %s;\n"
         "\n"
         "/* Include auxilary automatically generated code for this class.\n"
         " */\n"
@@ -419,21 +423,21 @@ CFCBindClass_to_c(CFCBindClass *self) {
                   + strlen(cb_funcs)
                   + strlen(cb_objects)
                   + strlen(cb_var)
-                  + strlen(class_name_def)
-                  + strlen(vtable_def)
+                  + strlen(method_var)
+                  + strlen(vt_type)
+                  + strlen(vt_hidden)
                   + strlen(autocode)
                   + 100;
     char *code = (char*)MALLOCATE(size);
     sprintf(code, pattern, include_h, offsets, cb_funcs, cb_objects, cb_var,
-            class_name_def, vtable_def, autocode);
+            method_var, vt_type, vt_hidden, autocode);
 
+    FREEMEM(method_var);
     FREEMEM(fresh_methods);
     FREEMEM(offsets);
     FREEMEM(cb_funcs);
     FREEMEM(cb_objects);
     FREEMEM(cb_var);
-    FREEMEM(class_name_def);
-    FREEMEM(vtable_def);
     return code;
 }
 
@@ -464,38 +468,17 @@ S_struct_definition(CFCBindClass *self) 
     return struct_def;
 }
 
-static char*
-S_name_var_definition(CFCBindClass *self) {
-    const char *class_name  = CFCClass_get_class_name(self->client);
-    unsigned class_name_len = (unsigned)strlen(class_name);
-
-    const char pattern[] =
-        "static cfish_ZombieCharBuf %s = {\n"
-        "    CFISH_ZOMBIECHARBUF,\n"
-        "    {1}, /* ref.count */\n"
-        "    \"%s\",\n"
-        "    %u,\n"
-        "    0\n"
-        "};\n\n";
-    size_t size = sizeof(pattern)
-                  + strlen(self->full_name_var)
-                  + class_name_len
-                  + 15 // class_name_len
-                  + 20;
-    char *name_var_def = (char*)MALLOCATE(size);
-    sprintf(name_var_def, pattern, self->full_name_var, class_name,
-            class_name_len);
+// Return C code bootstrapping the class's VTable.
+char*
+CFCBindClass_to_vtable_bootstrap(CFCBindClass *self) {
+    CFCClass *client = self->client;
 
-    return name_var_def;
-}
+    if (CFCClass_inert(client)) {
+        return CFCUtil_strdup("");
+    }
 
-// Return C code defining the class's VTable.
-static char*
-S_vtable_definition(CFCBindClass *self) {
-    CFCClass    *client     = self->client;
     CFCClass    *parent     = CFCClass_get_parent(client);
-    CFCMethod  **methods    = CFCClass_methods(client);
-    const char  *vt_type    = CFCClass_full_vtable_type(client);
+    const char  *class_name = CFCClass_get_class_name(client);
     const char  *vt_var     = CFCClass_full_vtable_var(client);
     const char  *struct_sym = CFCClass_full_struct_sym(client);
 
@@ -504,56 +487,31 @@ S_vtable_definition(CFCBindClass *self) 
                              ? CFCClass_full_vtable_var(parent)
                              : "NULL"; // No parent, e.g. Obj or inert classes.
 
-    // Spec functions which implement the methods, casting to quiet compiler.
-    char *method_str = CFCUtil_strdup("");
-    int num_methods = 0;
-    for (; methods[num_methods] != NULL; num_methods++) {
-        CFCMethod *method = methods[num_methods];
-        const char *implementing_sym = CFCMethod_implementing_func_sym(method);
-        size_t size = strlen(method_str) + strlen(implementing_sym) + 50;
-        method_str = (char*)REALLOCATE(method_str, size);
-        if (strlen(method_str)) {
-            strcat(method_str, ",\n");
-        }
-        strcat(method_str, "        (cfish_method_t)");
-        strcat(method_str, implementing_sym);
-    }
-
     char pattern[] =
-        "\n"
-        "%s %s_vt = {\n"
-        "    CFISH_VTABLE, /* vtable vtable */\n"
-        "    {1}, /* ref.count */\n"
-        "    %s, /* parent */\n"
-        "    (cfish_CharBuf*)&%s,\n"
-        "    0, /* flags */\n"
-        "    NULL, /* \"void *x\" member reserved for future use */\n"
-        "    sizeof(%s), /* obj_alloc_size */\n"
-        "    offsetof(cfish_VTable, methods)\n"
-        "        + %d * sizeof(cfish_method_t), /* vt_alloc_size */\n"
-        "    &%s,  /* callbacks */\n"
-        "    {\n"
-        "%s\n"
-        "    }\n"
-        "};\n\n";
+        "    cfish_VTable_bootstrap(\n"
+        "        %s, /* vtable */\n"
+        "        %s, /* parent */\n"
+        "        \"%s\", /* name */\n"
+        "        0, /* flags */\n"
+        "        NULL, /* \"void *x\" member reserved for future use */\n"
+        "        sizeof(%s), /* obj_alloc_size */\n"
+        "        %s, /* callbacks */\n"
+        "        %s /* methods */\n"
+        "    );\n";
 
     size_t size = sizeof(pattern)
-                  + strlen(vt_type)
                   + strlen(vt_var)
                   + strlen(parent_ref)
-                  + strlen(self->full_name_var)
+                  + strlen(class_name)
                   + strlen(struct_sym)
-                  + 10 /* num_methods */
                   + strlen(self->full_callbacks_var)
-                  + strlen(method_str)
+                  + strlen(self->full_methods_var)
                   + 40;
-    char *vtable_def = (char*)MALLOCATE(size);
-    sprintf(vtable_def, pattern, vt_type, vt_var, parent_ref,
-            self->full_name_var, struct_sym, num_methods,
-            self->full_callbacks_var, method_str);
+    char *code = (char*)MALLOCATE(size);
+    sprintf(code, pattern, vt_var, parent_ref, class_name, struct_sym,
+            self->full_callbacks_var, self->full_methods_var);
 
-    FREEMEM(method_str);
-    return vtable_def;
+    return code;
 }
 
 // Declare cfish_Callback objects.

Modified: lucy/trunk/clownfish/src/CFCBindClass.h
URL: http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCBindClass.h?rev=1326105&r1=1326104&r2=1326105&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCBindClass.h (original)
+++ lucy/trunk/clownfish/src/CFCBindClass.h Sat Apr 14 14:04:17 2012
@@ -49,11 +49,15 @@ CFCBindClass_destroy(CFCBindClass *self)
 char*
 CFCBindClass_to_c_header(CFCBindClass *self);
 
-/** Return the .c file which contains autogenerated C code necessary for the
- * class to function properly.
+/** Return the C data definitions necessary for the class to function properly.
  */
 char*
-CFCBindClass_to_c(CFCBindClass *self);
+CFCBindClass_to_c_data(CFCBindClass *self);
+
+/** Return the autogenerated C code necessary to bootstrap the class.
+ */
+char*
+CFCBindClass_to_vtable_bootstrap(CFCBindClass *self);
 
 #ifdef __cplusplus
 }

Modified: lucy/trunk/clownfish/src/CFCBindCore.c
URL: http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCBindCore.c?rev=1326105&r1=1326104&r2=1326105&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCBindCore.c (original)
+++ lucy/trunk/clownfish/src/CFCBindCore.c Sat Apr 14 14:04:17 2012
@@ -26,6 +26,7 @@
 #include "CFCClass.h"
 #include "CFCFile.h"
 #include "CFCHierarchy.h"
+#include "CFCParcel.h"
 #include "CFCUtil.h"
 
 struct CFCBindCore {
@@ -114,10 +115,15 @@ CFCBindCore_write_all_modified(CFCBindCo
 static void
 S_write_parcel_h(CFCBindCore *self) {
     CFCHierarchy *hierarchy = self->hierarchy;
+    CFCParcel    *parcel    = NULL;
 
     // Declare object structs for all instantiable classes.
+    // Obtain parcel prefix for use in bootstrap function name.
     char *typedefs = CFCUtil_strdup("");
     CFCClass **ordered = CFCHierarchy_ordered_classes(hierarchy);
+    if (!ordered[0]) {
+        CFCUtil_die("No classes found.");
+    }
     for (int i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
         if (!CFCClass_inert(klass)) {
@@ -125,7 +131,12 @@ S_write_parcel_h(CFCBindCore *self) {
             typedefs = CFCUtil_cat(typedefs, "typedef struct ", full_struct,
                                    " ", full_struct, ";\n", NULL);
         }
+        if (parcel && CFCClass_get_parcel(klass) != parcel) {
+            CFCUtil_die("Multiple parcels not yet supported.");
+        }
+        parcel = CFCClass_get_parcel(klass);
     }
+    const char *prefix = CFCParcel_get_prefix(parcel);
     FREEMEM(ordered);
 
     // Create Clownfish aliases if necessary.
@@ -205,6 +216,9 @@ S_write_parcel_h(CFCBindCore *self) {
         "    size_t         offset;\n"
         "} cfish_Callback;\n"
         "\n"
+        "void\n"
+        "%sbootstrap_parcel();\n"
+        "\n"
         "#ifdef __cplusplus\n"
         "}\n"
         "#endif\n"
@@ -217,10 +231,11 @@ S_write_parcel_h(CFCBindCore *self) {
                   + strlen(self->header)
                   + strlen(aliases)
                   + strlen(typedefs)
+                  + strlen(prefix)
                   + strlen(self->footer)
                   + 50;
     char *file_content = (char*)MALLOCATE(size);
-    sprintf(file_content, pattern, self->header, aliases, typedefs,
+    sprintf(file_content, pattern, self->header, aliases, typedefs, prefix,
             self->footer);
 
     // Unlink then write file.
@@ -239,62 +254,72 @@ S_write_parcel_h(CFCBindCore *self) {
 static void
 S_write_parcel_c(CFCBindCore *self) {
     CFCHierarchy *hierarchy = self->hierarchy;
+    CFCParcel    *parcel    = NULL;
 
     // Aggregate C code from all files.
-    char *content      = CFCUtil_strdup("");
+    // Obtain parcel prefix for use in bootstrap function name.
     char *privacy_syms = CFCUtil_strdup("");
     char *includes     = CFCUtil_strdup("");
-    CFCFile **files    = CFCHierarchy_files(hierarchy);
-    for (int i = 0; files[i] != NULL; i++) {
-        CFCFile *file = files[i];
-        CFCBase **blocks = CFCFile_blocks(file);
-        for (int j = 0; blocks[j] != NULL; j++) {
-            const char *cfc_class = CFCBase_get_cfc_class(blocks[j]);
-            if (strcmp(cfc_class, "Clownfish::CFC::Model::Class") != 0) {
-                continue;
-            }
-
-            CFCClass *klass = (CFCClass*)blocks[j];
-            if (CFCClass_included(klass)) { continue; }
-
-            CFCBindClass *class_binding = CFCBindClass_new(klass);
-            char *c_code = CFCBindClass_to_c(class_binding);
-            content = CFCUtil_cat(content, c_code, "\n", NULL);
-            FREEMEM(c_code);
-            CFCBase_decref((CFCBase*)class_binding);
-            const char *privacy_sym = CFCClass_privacy_symbol(klass);
-            privacy_syms = CFCUtil_cat(privacy_syms, "#define ",
-                                       privacy_sym, "\n", NULL);
-            const char *include_h = CFCClass_include_h(klass);
-            includes = CFCUtil_cat(includes, "#include \"", include_h,
-                                   "\"\n", NULL);
+    char *c_data       = CFCUtil_strdup("");
+    char *vt_bootstrap = CFCUtil_strdup("");
+    CFCClass **ordered = CFCHierarchy_ordered_classes(hierarchy);
+    if (!ordered[0]) {
+        CFCUtil_die("No classes found.");
+    }
+    for (int i = 0; ordered[i] != NULL; i++) {
+        CFCClass *klass = ordered[i];
+        if (CFCClass_included(klass)) { continue; }
+
+        CFCBindClass *class_binding = CFCBindClass_new(klass);
+        char *class_c_data = CFCBindClass_to_c_data(class_binding);
+        c_data = CFCUtil_cat(c_data, class_c_data, "\n", NULL);
+        FREEMEM(class_c_data);
+        char *vt_boot = CFCBindClass_to_vtable_bootstrap(class_binding);
+        vt_bootstrap = CFCUtil_cat(vt_bootstrap, vt_boot, NULL);
+        FREEMEM(vt_boot);
+        CFCBase_decref((CFCBase*)class_binding);
+        const char *privacy_sym = CFCClass_privacy_symbol(klass);
+        privacy_syms = CFCUtil_cat(privacy_syms, "#define ",
+                                   privacy_sym, "\n", NULL);
+        const char *include_h = CFCClass_include_h(klass);
+        includes = CFCUtil_cat(includes, "#include \"", include_h,
+                               "\"\n", NULL);
+        if (parcel && CFCClass_get_parcel(klass) != parcel) {
+            CFCUtil_die("Multiple parcels not yet supported.");
         }
+        parcel = CFCClass_get_parcel(klass);
     }
+    const char *prefix = CFCParcel_get_prefix(parcel);
+    FREEMEM(ordered);
 
     char pattern[] =
         "%s\n"
         "\n"
-        "#define C_LUCY_ZOMBIECHARBUF\n"
-        "#define C_LUCY_VTABLE\n"
         "%s\n"
         "#include \"parcel.h\"\n"
-        "#include \"Lucy/Object/CharBuf.h\"\n"
         "#include \"Lucy/Object/VTable.h\"\n"
         "%s\n"
         "\n"
         "%s\n"
         "\n"
+        "void\n"
+        "%sbootstrap_parcel() {\n"
+        "%s"
+        "}\n"
+        "\n"
         "%s\n";
     size_t size = sizeof(pattern)
                   + strlen(self->header)
                   + strlen(privacy_syms)
                   + strlen(includes)
-                  + strlen(content)
+                  + strlen(c_data)
+                  + strlen(prefix)
+                  + strlen(vt_bootstrap)
                   + strlen(self->footer)
                   + 50;
     char *file_content = (char*)MALLOCATE(size);
     sprintf(file_content, pattern, self->header, privacy_syms, includes,
-            content, self->footer);
+            c_data, prefix, vt_bootstrap, self->footer);
 
     // Unlink then open file.
     const char *src_dest = CFCHierarchy_get_source_dest(hierarchy);
@@ -306,7 +331,7 @@ S_write_parcel_c(CFCBindCore *self) {
 
     FREEMEM(privacy_syms);
     FREEMEM(includes);
-    FREEMEM(content);
-    FREEMEM(file_content);
+    FREEMEM(c_data);
+    FREEMEM(vt_bootstrap);
 }
 

Modified: lucy/trunk/clownfish/src/CFCPerl.c
URL: http://svn.apache.org/viewvc/lucy/trunk/clownfish/src/CFCPerl.c?rev=1326105&r1=1326104&r2=1326105&view=diff
==============================================================================
--- lucy/trunk/clownfish/src/CFCPerl.c (original)
+++ lucy/trunk/clownfish/src/CFCPerl.c Sat Apr 14 14:04:17 2012
@@ -237,6 +237,7 @@ S_write_boot_c(CFCPerl *self) {
     char *pound_includes = CFCUtil_strdup("");
     char *registrations  = CFCUtil_strdup("");
     char *isa_pushes     = CFCUtil_strdup("");
+    const char *prefix   = CFCParcel_get_prefix(self->parcel);
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
@@ -312,6 +313,8 @@ S_write_boot_c(CFCPerl *self) {
         "\n"
         "void\n"
         "%s() {\n"
+        "    %sbootstrap_parcel();\n"
+        "\n"
         "    AV *isa;\n"
         "    cfish_ZombieCharBuf *alias = CFISH_ZCB_WRAP_STR(\"\", 0);\n"
         "%s\n"
@@ -326,13 +329,14 @@ S_write_boot_c(CFCPerl *self) {
                   + strlen(self->boot_h_file)
                   + strlen(pound_includes)
                   + strlen(self->boot_func)
+                  + strlen(prefix)
                   + strlen(registrations)
                   + strlen(isa_pushes)
                   + strlen(self->footer)
                   + 100;
     char *content = (char*)MALLOCATE(size);
     sprintf(content, pattern, self->header, self->boot_h_file, pound_includes,
-            self->boot_func, registrations, isa_pushes, self->footer);
+            self->boot_func, prefix, registrations, isa_pushes, self->footer);
     CFCUtil_write_file(self->boot_c_path, content, strlen(content));
 
     FREEMEM(content);

Modified: lucy/trunk/core/Lucy/Object/VTable.c
URL: http://svn.apache.org/viewvc/lucy/trunk/core/Lucy/Object/VTable.c?rev=1326105&r1=1326104&r2=1326105&view=diff
==============================================================================
--- lucy/trunk/core/Lucy/Object/VTable.c (original)
+++ lucy/trunk/core/Lucy/Object/VTable.c Sat Apr 14 14:04:17 2012
@@ -16,6 +16,7 @@
 
 #define C_LUCY_VTABLE
 #define C_LUCY_OBJ
+#define C_LUCY_CHARBUF
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 
@@ -40,6 +41,41 @@ S_scrunch_charbuf(CharBuf *source, CharB
 
 LockFreeRegistry *VTable_registry = NULL;
 
+VTable*
+VTable_bootstrap(VTable *self, VTable *parent, const char *name, int flags,
+                 void *x, size_t obj_alloc_size, void *callbacks,
+                 cfish_method_t *methods) {
+    // Create CharBuf manually, since the CharBuf VTable might not be
+    // bootstrapped yet.
+    CharBuf *name_cb = (CharBuf*)Memory_wrapped_calloc(sizeof(CharBuf), 1);
+    size_t name_len  = strlen(name);
+
+    name_cb->vtable    = CHARBUF;
+    name_cb->ref.count = 1;
+    name_cb->ptr       = (char*)MALLOCATE(name_len + 1);
+    name_cb->size      = name_len;
+    name_cb->cap       = name_len + 1;
+    strcpy(name_cb->ptr, name);
+
+    self->vtable         = CFISH_VTABLE;
+    self->ref.count      = 1;
+    self->parent         = parent;
+    self->name           = name_cb;
+    self->flags          = flags;
+    self->x              = x;
+    self->obj_alloc_size = obj_alloc_size;
+    self->callbacks      = callbacks;
+
+    int n;
+    for (n = 0; methods[n]; ++n) {
+        self->methods[n] = methods[n];
+    }
+    self->vt_alloc_size = offsetof(cfish_VTable, methods)
+                          + n * sizeof(cfish_method_t);
+
+    return self;
+}
+
 void
 VTable_destroy(VTable *self) {
     THROW(ERR, "Insane attempt to destroy VTable for class '%o'", self->name);

Modified: lucy/trunk/core/Lucy/Object/VTable.cfh
URL: http://svn.apache.org/viewvc/lucy/trunk/core/Lucy/Object/VTable.cfh?rev=1326105&r1=1326104&r2=1326105&view=diff
==============================================================================
--- lucy/trunk/core/Lucy/Object/VTable.cfh (original)
+++ lucy/trunk/core/Lucy/Object/VTable.cfh Sat Apr 14 14:04:17 2012
@@ -37,6 +37,11 @@ class Lucy::Object::VTable inherits Lucy
     inert LockFreeRegistry *registry;
     inert size_t offset_of_parent;
 
+    inert VTable*
+    bootstrap(VTable *self, VTable *parent, const char *name, int flags,
+              void *x, size_t obj_alloc_size, void *callbacks,
+              cfish_method_t *methods);
+
     /** Return a singleton.  If a VTable can be found in the registry based on
      * the supplied class name, it will be returned.  Otherwise, a new VTable
      * will be created using [parent] as a base.