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); }
/* 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); }
const char* CFCSymbol_get_PREFIX(CFCSymbol *self) { return CFCParcel_get_PREFIX(self->parcel); }