예제 #1
0
static void
S_write_host_h(CFCPerl *self, CFCParcel *parcel) {
    const char *prefix = CFCParcel_get_prefix(parcel);
    const char *PREFIX = CFCParcel_get_PREFIX(parcel);

    char *guard = CFCUtil_sprintf("H_%sBOOT", PREFIX);

    const char pattern[] = 
        "%s\n"
        "\n"
        "#ifndef %s\n"
        "#define %s 1\n"
        "\n"
        "#ifdef __cplusplus\n"
        "extern \"C\" {\n"
        "#endif\n"
        "\n"
        "void\n"
        "%sbootstrap_perl(void);\n"
        "\n"
        "#ifdef __cplusplus\n"
        "}\n"
        "#endif\n"
        "\n"
        "#endif /* %s */\n"
        "\n"
        "%s\n";
    char *content
        = CFCUtil_sprintf(pattern, self->c_header, guard, guard, prefix, guard,
                          self->c_footer);

    const char *inc_dest = CFCHierarchy_get_include_dest(self->hierarchy);
    char *host_h_path = CFCUtil_sprintf("%s" CHY_DIR_SEP "%sperl.h", inc_dest,
                                        prefix);
    CFCUtil_write_file(host_h_path, content, strlen(content));
    FREEMEM(host_h_path);

    FREEMEM(content);
    FREEMEM(guard);
}
예제 #2
0
/* Write the "parcel.h" header file, which contains common symbols needed by
 * all classes, plus typedefs for all class structs.
 */
static void
S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel) {
    CFCHierarchy *hierarchy   = self->hierarchy;
    const char   *prefix      = CFCParcel_get_prefix(parcel);
    const char   *PREFIX      = CFCParcel_get_PREFIX(parcel);
    const char   *privacy_sym = CFCParcel_get_privacy_sym(parcel);

    // Declare object structs and class singletons for all instantiable
    // classes.
    char *typedefs    = CFCUtil_strdup("");
    char *class_decls = CFCUtil_strdup("");
    CFCClass **ordered = CFCHierarchy_ordered_classes(hierarchy);
    for (int i = 0; ordered[i] != NULL; i++) {
        CFCClass *klass = ordered[i];
        const char *class_prefix = CFCClass_get_prefix(klass);
        if (strcmp(class_prefix, prefix) != 0) { continue; }

        if (!CFCClass_inert(klass)) {
            const char *full_struct = CFCClass_full_struct_sym(klass);
            typedefs = CFCUtil_cat(typedefs, "typedef struct ", full_struct,
                                   " ", full_struct, ";\n", NULL);
            const char *class_var = CFCClass_full_class_var(klass);
            class_decls = CFCUtil_cat(class_decls, "extern ", PREFIX,
                                      "VISIBLE cfish_Class *", class_var,
                                      ";\n", NULL);
        }
    }
    FREEMEM(ordered);

    // Special includes and macros for Clownfish parcel.
    const char *cfish_includes =
        "#include <stdarg.h>\n"
        "#include <stddef.h>\n"
        "\n"
        "#include \"cfish_platform.h\"\n"
        "#include \"cfish_hostdefs.h\"\n";

    // Special definitions for Clownfish parcel.
    const char *cfish_defs_1 =
        "#define CFISH_UNUSED_VAR(var) ((void)var)\n"
        "#define CFISH_UNREACHABLE_RETURN(type) return (type)0\n"
        "\n"
        "/* Generic method pointer.\n"
        " */\n"
        "typedef void\n"
        "(*cfish_method_t)(const void *vself);\n"
        "\n"
        "/* Access the function pointer for a given method from the class.\n"
        " */\n"
        "#define CFISH_METHOD_PTR(_class, _full_meth) \\\n"
        "     ((_full_meth ## _t)cfish_method(_class, _full_meth ## _OFFSET))\n"
        "\n"
        "static CFISH_INLINE cfish_method_t\n"
        "cfish_method(const void *klass, uint32_t offset) {\n"
        "    union { char *cptr; cfish_method_t *fptr; } ptr;\n"
        "    ptr.cptr = (char*)klass + offset;\n"
        "    return ptr.fptr[0];\n"
        "}\n"
        "\n"
        "typedef struct cfish_Dummy {\n"
        "   CFISH_OBJ_HEAD\n"
        "   void *klass;\n"
        "} cfish_Dummy;\n"
        "\n"
        "/* Access the function pointer for a given method from the object.\n"
        " */\n"
        "static CFISH_INLINE cfish_method_t\n"
        "cfish_obj_method(const void *object, uint32_t offset) {\n"
        "    cfish_Dummy *dummy = (cfish_Dummy*)object;\n"
        "    return cfish_method(dummy->klass, offset);\n"
        "}\n"
        "\n"
        "/* Access the function pointer for the given method in the\n"
        " * superclass. */\n"
        "#define CFISH_SUPER_METHOD_PTR(_class, _full_meth) \\\n"
        "     ((_full_meth ## _t)cfish_super_method(_class, \\\n"
        "                                           _full_meth ## _OFFSET))\n"
        "\n"
        "extern CFISH_VISIBLE uint32_t cfish_Class_offset_of_parent;\n"
        "static CFISH_INLINE cfish_method_t\n"
        "cfish_super_method(const void *klass, uint32_t offset) {\n"
        "    char *class_as_char = (char*)klass;\n"
        "    cfish_Class **parent_ptr\n"
        "        = (cfish_Class**)(class_as_char + cfish_Class_offset_of_parent);\n"
        "    return cfish_method(*parent_ptr, offset);\n"
        "}\n"
        "\n"
        "typedef void\n"
        "(*cfish_destroy_t)(void *vself);\n"
        "extern CFISH_VISIBLE uint32_t CFISH_Obj_Destroy_OFFSET;\n"
        "\n"
        "/** Invoke the [](.Destroy) method found in `klass` on\n"
        " * `self`.\n"
        " *\n"
        " * TODO: Eliminate this function if we can arrive at a proper SUPER syntax.\n"
        " */\n"
        "static CFISH_INLINE void\n"
        "cfish_super_destroy(void *vself, cfish_Class *klass) {\n"
        "    cfish_Obj *self = (cfish_Obj*)vself;\n"
        "    if (self != NULL) {\n"
        "        cfish_destroy_t super_destroy\n"
        "            = (cfish_destroy_t)cfish_super_method(klass, CFISH_Obj_Destroy_OFFSET);\n"
        "        super_destroy(self);\n"
        "    }\n"
        "}\n"
        "\n"
        "#define CFISH_SUPER_DESTROY(_self, _class) \\\n"
        "    cfish_super_destroy(_self, _class)\n"
        "\n"
        "extern CFISH_VISIBLE cfish_Obj*\n"
        "cfish_inc_refcount(void *vself);\n"
        "\n"
        "/** NULL-safe invocation invocation of `cfish_inc_refcount`.\n"
        " *\n"
        " * @return NULL if `self` is NULL, otherwise the return value\n"
        " * of `cfish_inc_refcount`.\n"
        " */\n"
        "static CFISH_INLINE cfish_Obj*\n"
        "cfish_incref(void *vself) {\n"
        "    if (vself != NULL) { return cfish_inc_refcount(vself); }\n"
        "    else { return NULL; }\n"
        "}\n"
        "\n"
        "#define CFISH_INCREF(_self) cfish_incref(_self)\n"
        "#define CFISH_INCREF_NN(_self) cfish_inc_refcount(_self)\n"
        "\n"
        "extern CFISH_VISIBLE uint32_t\n"
        "cfish_dec_refcount(void *vself);\n"
        "\n"
        "/** NULL-safe invocation of `cfish_dec_refcount`.\n"
        " *\n"
        " * @return NULL if `self` is NULL, otherwise the return value\n"
        " * of `cfish_dec_refcount`.\n"
        " */\n"
        "static CFISH_INLINE uint32_t\n"
        "cfish_decref(void *vself) {\n"
        "    if (vself != NULL) { return cfish_dec_refcount(vself); }\n"
        "    else { return 0; }\n"
        "}\n"
        "\n"
        "#define CFISH_DECREF(_self) cfish_decref(_self)\n"
        "#define CFISH_DECREF_NN(_self) cfish_dec_refcount(_self)\n"
        "\n"
        "extern CFISH_VISIBLE uint32_t\n"
        "cfish_get_refcount(void *vself);\n"
        "\n"
        "#define CFISH_REFCOUNT_NN(_self) \\\n"
        "    cfish_get_refcount(_self)\n"
        "\n"
        "/* Flags for internal use. */\n"
        "#define CFISH_fREFCOUNTSPECIAL 0x00000001\n"
        "#define CFISH_fFINAL           0x00000002\n"
        ;
    const char *cfish_defs_2 =
        "#ifdef CFISH_USE_SHORT_NAMES\n"
        "  #define UNUSED_VAR               CFISH_UNUSED_VAR\n"
        "  #define UNREACHABLE_RETURN       CFISH_UNREACHABLE_RETURN\n"
        "  #define METHOD_PTR               CFISH_METHOD_PTR\n"
        "  #define SUPER_METHOD_PTR         CFISH_SUPER_METHOD_PTR\n"
        "  #define SUPER_DESTROY(_self, _class) CFISH_SUPER_DESTROY(_self, _class)\n"
        "  #define INCREF(_self)                CFISH_INCREF(_self)\n"
        "  #define INCREF_NN(_self)             CFISH_INCREF_NN(_self)\n"
        "  #define DECREF(_self)                CFISH_DECREF(_self)\n"
        "  #define DECREF_NN(_self)             CFISH_DECREF_NN(_self)\n"
        "  #define REFCOUNT_NN(_self)           CFISH_REFCOUNT_NN(_self)\n"
        "#endif\n"
        "\n";

    char *extra_defs;
    char *extra_includes;
    if (CFCParcel_is_cfish(parcel)) {
        const char *spec_typedefs = CFCBindSpecs_get_typedefs();
        extra_defs = CFCUtil_sprintf("%s%s%s", cfish_defs_1, spec_typedefs,
                                     cfish_defs_2);
        extra_includes = CFCUtil_strdup(cfish_includes);
    }
    else {
        extra_defs = CFCUtil_strdup("");
        extra_includes = CFCUtil_strdup("");

        // Include parcel.h of prerequisite parcels.
        CFCParcel **prereq_parcels = CFCParcel_prereq_parcels(parcel);
        for (size_t i = 0; prereq_parcels[i]; ++i) {
            const char *prereq_prefix
                = CFCParcel_get_prefix(prereq_parcels[i]);
            extra_includes = CFCUtil_cat(extra_includes, "#include \"",
                                         prereq_prefix, "parcel.h\"\n", NULL);
        }
        FREEMEM(prereq_parcels);
    }

    const char pattern[] =
        "%s\n"
        "#ifndef CFISH_%sPARCEL_H\n"
        "#define CFISH_%sPARCEL_H 1\n"
        "\n"
        "#ifdef __cplusplus\n"
        "extern \"C\" {\n"
        "#endif\n"
        "\n"
        "%s" // Extra includes.
        "\n"
        "#ifdef %s\n"
        "  #define %sVISIBLE CFISH_EXPORT\n"
        "#else\n"
        "  #define %sVISIBLE CFISH_IMPORT\n"
        "#endif\n"
        "\n"
        "%s" // Typedefs.
        "\n"
        "%s" // Class singletons.
        "\n"
        "%s" // Extra definitions.
        "%sVISIBLE void\n"
        "%sbootstrap_inheritance();\n"
        "\n"
        "%sVISIBLE void\n"
        "%sbootstrap_parcel();\n"
        "\n"
        "void\n"
        "%sinit_parcel();\n"
        "\n"
        "#ifdef __cplusplus\n"
        "}\n"
        "#endif\n"
        "\n"
        "#endif /* CFISH_%sPARCEL_H */\n"
        "\n"
        "%s\n"
        "\n";
    char *file_content
        = CFCUtil_sprintf(pattern, self->c_header, PREFIX, PREFIX,
                          extra_includes, privacy_sym, PREFIX, PREFIX,
                          typedefs, class_decls, extra_defs, PREFIX, prefix,
                          PREFIX, prefix, prefix, PREFIX, self->c_footer);

    // Unlink then write file.
    const char *inc_dest = CFCHierarchy_get_include_dest(hierarchy);
    char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "%sparcel.h", inc_dest,
                                     prefix);
    remove(filepath);
    CFCUtil_write_file(filepath, file_content, strlen(file_content));
    FREEMEM(filepath);

    FREEMEM(typedefs);
    FREEMEM(class_decls);
    FREEMEM(extra_defs);
    FREEMEM(extra_includes);
    FREEMEM(file_content);
}
예제 #3
0
const char*
CFCSymbol_get_PREFIX(CFCSymbol *self) {
    return CFCParcel_get_PREFIX(self->parcel);
}