void CFCTest_set_file_times(const char *path, time_t time) { // Strawberry Perl may unpack the distribution's files as read-only. DWORD attrs = GetFileAttributes(path); if (attrs == INVALID_FILE_ATTRIBUTES) { CFCUtil_die("Can't get file attrs of '%s': %u", path, GetLastError()); } if (attrs & FILE_ATTRIBUTE_READONLY) { attrs &= ~FILE_ATTRIBUTE_READONLY; if (!SetFileAttributes(path, attrs)) { CFCUtil_die("Can't make '%s' writable: %u", path, GetLastError()); } } HANDLE handle = CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (handle == INVALID_HANDLE_VALUE) { CFCUtil_die("Can't open '%s': %u", path, GetLastError()); } uint64_t ticks = 10000000 * (UINT64_C(11644473600) + time); FILETIME file_time; file_time.dwLowDateTime = (DWORD)ticks; file_time.dwHighDateTime = (DWORD)(ticks >> 32); if (!SetFileTime(handle, &file_time, &file_time, &file_time)) { CFCUtil_die("Can't set file time of '%s': %u", path, GetLastError()); } CloseHandle(handle); }
void CFCParcel_add_class(CFCParcel *self, CFCClass *klass) { // Ensure unique class name. const char *class_name = CFCClass_get_name(klass); CFCClass *other = S_fetch_class(self, class_name, 2); if (other) { CFCUtil_die("Two classes with name %s", class_name); } const char *struct_sym = CFCClass_get_struct_sym(klass); const char *nickname = CFCClass_get_nickname(klass); for (size_t i = 0; self->classes[i]; ++i) { CFCClass *other = self->classes[i]; // Ensure unique struct symbol and nickname in parcel. if (strcmp(struct_sym, CFCClass_get_struct_sym(other)) == 0) { CFCUtil_die("Class name conflict between %s and %s", CFCClass_get_name(klass), CFCClass_get_name(other)); } if (strcmp(nickname, CFCClass_get_nickname(other)) == 0) { CFCUtil_die("Class nickname conflict between %s and %s", CFCClass_get_name(klass), CFCClass_get_name(other)); } } size_t num_classes = self->num_classes; size_t size = (num_classes + 2) * sizeof(CFCClass*); CFCClass **classes = (CFCClass**)REALLOCATE(self->classes, size); classes[num_classes] = (CFCClass*)CFCBase_incref((CFCBase*)klass); classes[num_classes+1] = NULL; self->classes = classes; self->num_classes = num_classes + 1; }
static void S_process_dump_member(CFCClass *klass, CFCVariable *member, char *buf, size_t buf_size) { CFCUTIL_NULL_CHECK(member); CFCType *type = CFCVariable_get_type(member); const char *name = CFCVariable_micro_sym(member); unsigned name_len = (unsigned)strlen(name); const char *specifier = CFCType_get_specifier(type); // Skip the VTable. if (strcmp(specifier, "cfish_VTable") == 0) { return; } if (CFCType_is_integer(type) || CFCType_is_floating(type)) { char int_pattern[] = " Cfish_Hash_Store_Str(dump, \"%s\", %u, (cfish_Obj*)cfish_CB_newf(\"%%i64\", (int64_t)ivars->%s));\n"; char float_pattern[] = " Cfish_Hash_Store_Str(dump, \"%s\", %u, (cfish_Obj*)cfish_CB_newf(\"%%f64\", (double)ivars->%s));\n"; char bool_pattern[] = " Cfish_Hash_Store_Str(dump, \"%s\", %u, (cfish_Obj*)cfish_Bool_singleton(ivars->%s));\n"; const char *pattern; if (strcmp(specifier, "bool") == 0) { pattern = bool_pattern; } else if (CFCType_is_integer(type)) { pattern = int_pattern; } else { pattern = float_pattern; } size_t needed = strlen(pattern) + name_len * 2 + 20; if (buf_size < needed) { CFCUtil_die("Buffer not big enough (%lu < %lu)", (unsigned long)buf_size, (unsigned long)needed); } sprintf(buf, pattern, name, name_len, name); } else if (CFCType_is_object(type)) { char pattern[] = " if (ivars->%s) {\n" " Cfish_Hash_Store_Str(dump, \"%s\", %u, Cfish_Obj_Dump((cfish_Obj*)ivars->%s));\n" " }\n"; size_t needed = strlen(pattern) + name_len * 3 + 20; if (buf_size < needed) { CFCUtil_die("Buffer not big enough (%lu < %lu)", (unsigned long)buf_size, (unsigned long)needed); } sprintf(buf, pattern, name, name, name_len, name); } else { CFCUtil_die("Don't know how to dump a %s", CFCType_get_specifier(type)); } CFCClass_append_autocode(klass, buf); }
static void S_process_load_member(CFCClass *klass, CFCVariable *member, char *buf, size_t buf_size) { CFCUTIL_NULL_CHECK(member); CFCType *type = CFCVariable_get_type(member); const char *type_str = CFCType_to_c(type); const char *name = CFCVariable_micro_sym(member); unsigned name_len = (unsigned)strlen(name); char extraction[200]; const char *specifier = CFCType_get_specifier(type); // Skip the VTable. if (strcmp(specifier, "cfish_VTable") == 0) { return; } if (2 * strlen(type_str) + 100 > sizeof(extraction)) { // play it safe CFCUtil_die("type_str too long: '%s'", type_str); } if (CFCType_is_integer(type)) { if (strcmp(specifier, "bool") == 0) { sprintf(extraction, "Cfish_Obj_To_Bool(var)"); } else { sprintf(extraction, "(%s)Cfish_Obj_To_I64(var)", type_str); } } else if (CFCType_is_floating(type)) { sprintf(extraction, "(%s)Cfish_Obj_To_F64(var)", type_str); } else if (CFCType_is_object(type)) { const char *vtable_var = CFCType_get_vtable_var(type); sprintf(extraction, "(%s*)CFISH_CERTIFY(Cfish_Obj_Load(var, var), %s)", specifier, vtable_var); } else { CFCUtil_die("Don't know how to load %s", specifier); } const char *pattern = " {\n" " cfish_Obj *var = Cfish_Hash_Fetch_Str(source, \"%s\", %u);\n" " if (var) { ivars->%s = %s; }\n" " }\n"; size_t needed = sizeof(pattern) + (name_len * 2) + strlen(extraction) + 20; if (buf_size < needed) { CFCUtil_die("Buffer not big enough (%lu < %lu)", (unsigned long)buf_size, (unsigned long)needed); } sprintf(buf, pattern, name, name_len, name, extraction); CFCClass_append_autocode(klass, buf); }
void CFCType_resolve(CFCType *self, CFCClass **classes) { if (CFCType_is_composite(self)) { CFCType_resolve(self->child, classes); return; } if (!CFCType_is_object(self)) { return; } CFCClass *klass = NULL; char *specifier = self->specifier; if (isupper(self->specifier[0])) { // Try to find class from class list. for (size_t i = 0; classes[i]; ++i) { CFCClass *maybe_class = classes[i]; const char *struct_sym = CFCClass_get_struct_sym(maybe_class); if (strcmp(specifier, struct_sym) == 0) { if (klass) { CFCUtil_die("Type '%s' is ambigious", specifier); } klass = maybe_class; } } if (!klass) { CFCUtil_die("No class found for type '%s'", specifier); } // Create actual specifier with prefix. const char *prefix = CFCClass_get_prefix(klass); self->specifier = CFCUtil_sprintf("%s%s", prefix, specifier); FREEMEM(specifier); } else { // Try to find class from class list. for (size_t i = 0; classes[i]; ++i) { CFCClass *maybe_class = classes[i]; const char *full_struct_sym = CFCClass_full_struct_sym(maybe_class); if (strcmp(specifier, full_struct_sym) == 0) { klass = maybe_class; break; } } } // Add parcel dependency. if (klass) { CFCParcel *class_parcel = CFCClass_get_parcel(klass); CFCParcel_add_dependent_parcel(self->parcel, class_parcel); } }
CFCParcel* CFCParcel_init(CFCParcel *self, const char *name, const char *cnick, CFCVersion *version) { // Validate name. if (!name || !S_validate_name_or_cnick(name)) { CFCUtil_die("Invalid name: '%s'", name ? name : "[NULL]"); } self->name = CFCUtil_strdup(name); // Validate or derive cnick. if (cnick) { if (!S_validate_name_or_cnick(cnick)) { CFCUtil_die("Invalid cnick: '%s'", cnick); } self->cnick = CFCUtil_strdup(cnick); } else { // Default cnick to name. self->cnick = CFCUtil_strdup(name); } // Default to version v0. if (version) { self->version = (CFCVersion*)CFCBase_incref((CFCBase*)version); } else { self->version = CFCVersion_new("v0"); } // Derive prefix, Prefix, PREFIX. size_t cnick_len = strlen(self->cnick); size_t prefix_len = cnick_len ? cnick_len + 1 : 0; size_t amount = prefix_len + 1; self->prefix = (char*)MALLOCATE(amount); self->Prefix = (char*)MALLOCATE(amount); self->PREFIX = (char*)MALLOCATE(amount); memcpy(self->Prefix, self->cnick, cnick_len); if (cnick_len) { self->Prefix[cnick_len] = '_'; self->Prefix[cnick_len + 1] = '\0'; } else { self->Prefix[cnick_len] = '\0'; } for (size_t i = 0; i < amount; i++) { self->prefix[i] = tolower(self->Prefix[i]); self->PREFIX[i] = toupper(self->Prefix[i]); } self->prefix[prefix_len] = '\0'; self->Prefix[prefix_len] = '\0'; self->PREFIX[prefix_len] = '\0'; return self; }
CFCMethod* CFCMethod_init(CFCMethod *self, CFCParcel *parcel, const char *exposure, const char *class_name, const char *class_cnick, const char *macro_sym, CFCType *return_type, CFCParamList *param_list, CFCDocuComment *docucomment, int is_final, int is_abstract) { // Validate macro_sym, derive micro_sym. if (!S_validate_macro_sym(macro_sym)) { CFCBase_decref((CFCBase*)self); CFCUtil_die("Invalid macro_sym: '%s'", macro_sym ? macro_sym : "[NULL]"); } char *micro_sym = CFCUtil_strdup(macro_sym); for (size_t i = 0; micro_sym[i] != '\0'; i++) { micro_sym[i] = tolower(micro_sym[i]); } // Super-init and clean up derived micro_sym. CFCFunction_init((CFCFunction*)self, parcel, exposure, class_name, class_cnick, micro_sym, return_type, param_list, docucomment, false); FREEMEM(micro_sym); // Verify that the first element in the arg list is a self. CFCVariable **args = CFCParamList_get_variables(param_list); if (!args[0]) { CFCUtil_die("Missing 'self' argument"); } CFCType *type = CFCVariable_get_type(args[0]); const char *specifier = CFCType_get_specifier(type); const char *prefix = CFCMethod_get_prefix(self); const char *last_colon = strrchr(class_name, ':'); const char *struct_sym = last_colon ? last_colon + 1 : class_name; if (strcmp(specifier, struct_sym) != 0) { char *wanted = CFCUtil_sprintf("%s%s", prefix, struct_sym); int mismatch = strcmp(wanted, specifier); FREEMEM(wanted); if (mismatch) { CFCUtil_die("First arg type doesn't match class: '%s' '%s'", class_name, specifier); } } self->macro_sym = CFCUtil_strdup(macro_sym); self->full_override_sym = NULL; self->host_alias = NULL; self->is_final = is_final; self->is_abstract = is_abstract; self->is_excluded = false; // Assume that this method is novel until we discover when applying // inheritance that it overrides another. self->is_novel = true; return self; }
char* CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) { CFCParamList *param_list = CFCFunction_get_param_list(init_func); const char *self_type = CFCType_to_c(CFCFunction_get_return_type(init_func)); char *func_sym = CFCFunction_full_func_sym(init_func, invoker); char *decs = S_gen_decs(param_list, 1); char *increfs = S_gen_arg_increfs(param_list, 1); char *decrefs = S_gen_decrefs(param_list, 1); const char *class_var = CFCClass_full_class_var(invoker); const char *struct_sym = CFCClass_full_struct_sym(invoker); char *error = NULL; char *arg_parsing = S_gen_arg_parsing(param_list, 1, &error); if (error) { CFCUtil_die("%s in constructor for %s", error, CFCClass_get_name(invoker)); } if (!arg_parsing) { CFCUtil_die("Unexpected arg parsing error for %s", CFCClass_get_name(invoker)); } char *first_arg = CFCUtil_sprintf("(%s)CFISH_Class_Make_Obj(%s)", self_type, class_var); char *arg_list = S_gen_arg_list(param_list, first_arg); char pattern[] = "static PyObject*\n" "S_%s_PY_NEW(PyTypeObject *type, PyObject *args, PyObject *kwargs) {\n" "%s" // decs "%s" // arg_parsing "%s" // increfs " %s self = NULL;\n" " CFBIND_TRY(self = %s(%s));\n" "%s" // decrefs " if (CFBind_migrate_cferr()) {\n" " return NULL;\n" " }\n" " return (PyObject*)self;\n" "}\n" ; char *wrapper = CFCUtil_sprintf(pattern, struct_sym, decs, arg_parsing, increfs, self_type, func_sym, arg_list, decrefs); FREEMEM(arg_list); FREEMEM(first_arg); FREEMEM(func_sym); FREEMEM(decrefs); FREEMEM(increfs); FREEMEM(decs); FREEMEM(arg_parsing); return wrapper; }
static void S_parse_cf_files(CFCHierarchy *self, const char *source_dir, int is_included) { CFCFindFilesContext context; context.ext = ".cfh"; context.paths = (char**)CALLOCATE(1, sizeof(char*)); context.num_paths = 0; CFCUtil_walk(source_dir, S_find_files, &context); // Process any file that has at least one class declaration. for (int i = 0; context.paths[i] != NULL; i++) { // Derive the name of the class that owns the module file. char *source_path = context.paths[i]; char *path_part = S_extract_path_part(source_path, source_dir, ".cfh"); // Ignore hidden files. if (path_part[0] == '.' || strstr(path_part, CHY_DIR_SEP ".") != NULL) { continue; } CFCFileSpec *file_spec = CFCFileSpec_new(source_dir, path_part, ".cfh", is_included); // Slurp and parse file. size_t unused; char *content = CFCUtil_slurp_text(source_path, &unused); CFCFile *file = CFCParser_parse_file(self->parser, content, file_spec); FREEMEM(content); if (!file) { int lineno = CFCParser_get_lineno(self->parser); CFCUtil_die("%s:%d: parser error", source_path, lineno); } // Make sure path_part is unique because the name of the generated // C header is derived from it. CFCFile *existing = S_fetch_file(self, path_part); if (existing) { CFCUtil_die("File %s.cfh found twice in %s and %s", path_part, CFCFile_get_source_dir(existing), source_dir); } S_add_file(self, file); CFCBase_decref((CFCBase*)file); CFCBase_decref((CFCBase*)file_spec); FREEMEM(path_part); } CFCUtil_free_string_array(context.paths); }
/* Some of the ParseTuple conversion routines provided by the Python-flavored * CFBind module accept a CFBindArg instead of just a pointer to the value * itself. This routine generates the declarations for those CFBindArg * variables, as well as handling some default values. */ static char* S_gen_declaration(CFCVariable *var, const char *val) { CFCType *type = CFCVariable_get_type(var); const char *var_name = CFCVariable_get_name(var); const char *type_str = CFCType_to_c(type); char *result = NULL; if (CFCType_is_object(type)) { const char *specifier = CFCType_get_specifier(type); if (strcmp(specifier, "cfish_String") == 0) { if (val && strcmp(val, "NULL") != 0) { const char pattern[] = " const char arg_%s_DEFAULT[] = %s;\n" " %s_ARG = CFISH_SSTR_WRAP_UTF8(\n" " arg_%s_DEFAULT, sizeof(arg_%s_DEFAULT) - 1);\n" ; result = CFCUtil_sprintf(pattern, var_name, val, var_name, var_name, var_name); } } else { if (val && strcmp(val, "NULL") != 0) { CFCUtil_die("Can't assign a default of '%s' to a %s", val, type_str); } if (strcmp(specifier, "cfish_Hash") != 0 && strcmp(specifier, "cfish_Vector") != 0 ) { const char *class_var = CFCType_get_class_var(type); char pattern[] = " CFBindArg wrap_arg_%s = {%s, &%s_ARG};\n" ; result = CFCUtil_sprintf(pattern, var_name, class_var, var_name); } } } else if (CFCType_is_primitive(type)) { if (val) { char pattern[] = " %s_ARG = %s;\n"; result = CFCUtil_sprintf(pattern, var_name, val); } } else { CFCUtil_die("Unexpected type, can't gen declaration: %s", type_str); } return result; }
char* CFCPerlPod_constructors_pod(CFCPerlPod *self, CFCClass *klass) { if (!self->num_constructors) { return CFCUtil_strdup(""); } const char *class_name = CFCClass_get_name(klass); char *pod = CFCUtil_strdup("=head1 CONSTRUCTORS\n\n"); for (size_t i = 0; i < self->num_constructors; i++) { NamePod slot = self->constructors[i]; if (slot.pod) { pod = CFCUtil_cat(pod, slot.pod, "\n", NULL); } else { const char *func_name = slot.func ? slot.func : slot.alias; CFCFunction *pod_func = CFCClass_function(klass, func_name); if (!pod_func) { CFCUtil_die("Can't find constructor '%s' in class '%s'", func_name, CFCClass_get_name(klass)); } char *sub_pod = CFCPerlPod_gen_subroutine_pod((CFCCallable*)pod_func, slot.alias, klass, slot.sample, class_name, true); pod = CFCUtil_cat(pod, sub_pod, NULL); FREEMEM(sub_pod); } } return pod; }
static char* S_primitive_callback_def(CFCMethod *method, const char *callback_start, const char *refcount_mods) { const char *override_sym = CFCMethod_full_override_sym(method); const char *params = CFCParamList_to_c(CFCMethod_get_param_list(method)); CFCType *return_type = CFCMethod_get_return_type(method); const char *ret_type_str = CFCType_to_c(return_type); const char *micro_sym = CFCMethod_micro_sym(method); char callback_func[50]; if (CFCType_is_integer(return_type)) { strcpy(callback_func, "S_finish_callback_i64"); } else if (CFCType_is_floating(return_type)) { strcpy(callback_func, "S_finish_callback_f64"); } else { CFCUtil_die("Unexpected type: %s", ret_type_str); } char pattern[] = "%s\n" "%s(%s) {\n" "%s" " %s retval = (%s)%s(\"%s\");%s\n" " return retval;\n" "}\n"; char *callback_def = CFCUtil_sprintf(pattern, ret_type_str, override_sym, params, callback_start, ret_type_str, ret_type_str, callback_func, micro_sym, refcount_mods); return callback_def; }
void CFCClass_add_method(CFCClass *self, CFCMethod *method) { CFCUTIL_NULL_CHECK(method); if (self->tree_grown) { CFCUtil_die("Can't call add_method after grow_tree"); } if (self->is_inert) { CFCUtil_die("Can't add_method to an inert class"); } self->num_methods++; size_t size = (self->num_methods + 1) * sizeof(CFCMethod*); self->methods = (CFCMethod**)REALLOCATE(self->methods, size); self->methods[self->num_methods - 1] = (CFCMethod*)CFCBase_incref((CFCBase*)method); self->methods[self->num_methods] = NULL; }
CFCType* CFCType_new_float(int flags, const char *specifier) { // Validate specifier. for (size_t i = 0; ; i++) { if (!float_specifiers[i]) { CFCUtil_die("Unknown float specifier: '%s'", specifier); } if (strcmp(float_specifiers[i], specifier) == 0) { break; } } // Cache the C representation of this type. char c_string[32]; if (flags & CFCTYPE_CONST) { sprintf(c_string, "const %s", specifier); } else { strcpy(c_string, specifier); } flags |= CFCTYPE_PRIMITIVE; flags |= CFCTYPE_FLOATING; S_check_flags(flags, CFCTYPE_CONST | CFCTYPE_PRIMITIVE | CFCTYPE_FLOATING, "Floating"); return CFCType_new(flags, NULL, specifier, 0, c_string); }
static char* S_gen_positional_sample(const char *prologue, CFCParamList *param_list, int start) { int num_vars = CFCParamList_num_vars(param_list); CFCVariable **vars = CFCParamList_get_variables(param_list); const char **inits = CFCParamList_get_initial_values(param_list); if (num_vars - start != 1) { CFCUtil_die("Code samples with multiple positional parameters" " are not supported yet."); } const char *name = CFCVariable_get_name(vars[start]); char *sample = CFCUtil_sprintf(" %s($%s);\n", prologue, name); const char *init = inits[start]; if (init) { if (strcmp(init, "NULL") == 0) { init = "undef"; } char *def_sample = CFCUtil_sprintf(" %s(); # default: %s\n", prologue, init); sample = CFCUtil_cat(sample, def_sample, NULL); FREEMEM(def_sample); } return sample; }
void CFCGoClass_spec_method(CFCGoClass *self, const char *name, const char *sig) { CFCUTIL_NULL_CHECK(sig); S_lazy_init_method_bindings(self); if (!name) { CFCGoMethod *meth_binding = CFCGoMethod_new(NULL); CFCGoMethod_customize(meth_binding, sig); size_t size = (self->num_bound + 2) * sizeof(CFCGoMethod*); self->method_bindings = (CFCGoMethod**)REALLOCATE(self->method_bindings, size); self->method_bindings[self->num_bound] = meth_binding; self->num_bound++; self->method_bindings[self->num_bound] = NULL; } else { CFCGoMethod *binding = NULL; for (int i = 0; self->method_bindings[i] != NULL; i++) { CFCGoMethod *candidate = self->method_bindings[i]; CFCMethod *meth = CFCGoMethod_get_client(candidate); if (meth && strcmp(name, CFCMethod_get_name(meth)) == 0) { binding = candidate; break; } } if (!binding) { CFCUtil_die("Can't find a method named '%s'", name); } CFCGoMethod_customize(binding, sig); } }
static void S_set_prereqs(CFCParcel *self, CFCJson *node, const char *path) { size_t num_prereqs = CFCJson_get_num_children(node) / 2; CFCJson **children = CFCJson_get_children(node); CFCPrereq **prereqs = (CFCPrereq**)MALLOCATE((num_prereqs + 1) * sizeof(CFCPrereq*)); for (size_t i = 0; i < num_prereqs; ++i) { const char *name = CFCJson_get_string(children[2*i]); CFCJson *value = children[2*i+1]; int value_type = CFCJson_get_type(value); CFCVersion *version = NULL; if (value_type == CFCJSON_STRING) { version = CFCVersion_new(CFCJson_get_string(value)); } else if (value_type != CFCJSON_NULL) { CFCUtil_die("Invalid prereq value (filepath '%s')", path); } prereqs[i] = CFCPrereq_new(name, version); CFCBase_decref((CFCBase*)version); } prereqs[num_prereqs] = NULL; // Assume that prereqs are empty. FREEMEM(self->prereqs); self->prereqs = prereqs; self->num_prereqs = num_prereqs; }
static char* S_meth_top(CFCMethod *method) { CFCParamList *param_list = CFCMethod_get_param_list(method); if (CFCParamList_num_vars(param_list) == 1) { char pattern[] = "(PyObject *self, PyObject *unused) {\n" " CFISH_UNUSED_VAR(unused);\n" ; return CFCUtil_sprintf(pattern); } else { char *error = NULL; char *arg_parsing = S_gen_arg_parsing(param_list, 1, &error); if (error) { CFCUtil_die("%s in %s", error, CFCMethod_get_name(method)); } if (!arg_parsing) { return NULL; } char *decs = S_gen_decs(param_list, 1); char pattern[] = "(PyObject *self, PyObject *args, PyObject *kwargs) {\n" "%s" // decs "%s" ; char *result = CFCUtil_sprintf(pattern, decs, arg_parsing); FREEMEM(arg_parsing); return result; } }
char* CFCGoClass_boilerplate_funcs(CFCGoClass *self) { char *content = NULL; if (!self->client) { CFCUtil_die("Can't find class for %s", self->class_name); } else if (CFCClass_inert(self->client)) { content = CFCUtil_strdup(""); } else { const char *clownfish_dot = CFCParcel_is_cfish(self->parcel) ? "" : "clownfish."; const char *short_struct = CFCClass_get_struct_sym(self->client); char pattern[] = "func WRAP%s(ptr unsafe.Pointer) %s {\n" "\tobj := &%sIMP{}\n" "\tobj.INITOBJ(ptr)\n" "\treturn obj\n" "}\n" "\n" "func WRAP%sASOBJ(ptr unsafe.Pointer) %sObj {\n" "\treturn WRAP%s(ptr)\n" "}\n" ; content = CFCUtil_sprintf(pattern, short_struct, short_struct, short_struct, short_struct, clownfish_dot, short_struct); } return content; }
int S_do_propagate_modified(CFCHierarchy *self, CFCClass *klass, int modified) { const char *path_part = CFCClass_get_path_part(klass); CFCUTIL_NULL_CHECK(path_part); CFCFile *file = S_fetch_file(self, path_part); CFCUTIL_NULL_CHECK(file); const char *source_path = CFCFile_get_path(file); char *h_path = CFCFile_h_path(file, self->inc_dest); if (!CFCUtil_current(source_path, h_path)) { modified = true; } FREEMEM(h_path); if (modified) { CFCFile_set_modified(file, modified); } // Proceed to the next generation. int somebody_is_modified = modified; CFCClass **children = CFCClass_children(klass); for (size_t i = 0; children[i] != NULL; i++) { CFCClass *kid = children[i]; if (CFCClass_final(klass)) { CFCUtil_die("Attempt to inherit from final class '%s' by '%s'", CFCClass_get_name(klass), CFCClass_get_name(kid)); } if (S_do_propagate_modified(self, kid, modified)) { somebody_is_modified = 1; } } return somebody_is_modified; }
CFCPerlConstructor* CFCPerlConstructor_init(CFCPerlConstructor *self, CFCClass *klass, const char *alias, const char *initializer) { CFCUTIL_NULL_CHECK(alias); CFCUTIL_NULL_CHECK(klass); const char *class_name = CFCClass_get_class_name(klass); initializer = initializer ? initializer : "init"; // Find the implementing function. self->init_func = NULL; CFCFunction **funcs = CFCClass_functions(klass); for (size_t i = 0; funcs[i] != NULL; i++) { CFCFunction *func = funcs[i]; const char *func_name = CFCFunction_micro_sym(func); if (strcmp(initializer, func_name) == 0) { self->init_func = (CFCFunction*)CFCBase_incref((CFCBase*)func); break; } } if (!self->init_func) { CFCUtil_die("Missing or invalid '%s' function for '%s'", initializer, class_name); } CFCParamList *param_list = CFCFunction_get_param_list(self->init_func); CFCPerlSub_init((CFCPerlSub*)self, param_list, class_name, alias, true); return self; }
time_t CFCTest_get_file_mtime(const char *path) { struct stat buf; if (stat(path, &buf)) { CFCUtil_die("Can't stat '%s': %s", path, strerror(errno)); } return buf.st_mtime; }
static void S_register(CFCClass *self) { if (registry_size == registry_cap) { size_t new_cap = registry_cap + 10; registry = (CFCClassRegEntry*)REALLOCATE( registry, (new_cap + 1) * sizeof(CFCClassRegEntry)); for (size_t i = registry_cap; i <= new_cap; i++) { registry[i].key = NULL; registry[i].klass = NULL; } registry_cap = new_cap; } CFCParcel *parcel = CFCClass_get_parcel(self); const char *prefix = CFCParcel_get_prefix(parcel); const char *class_name = CFCClass_get_class_name(self); const char *cnick = CFCClass_get_cnick(self); const char *key = self->full_struct_sym; for (size_t i = 0; i < registry_size; i++) { CFCClass *other = registry[i].klass; CFCParcel *other_parcel = CFCClass_get_parcel(other); const char *other_prefix = CFCParcel_get_prefix(other_parcel); const char *other_class_name = CFCClass_get_class_name(other); const char *other_cnick = CFCClass_get_cnick(other); if (strcmp(class_name, other_class_name) == 0) { CFCUtil_die("Two classes with name %s", class_name); } if (strcmp(registry[i].key, key) == 0) { CFCUtil_die("Class name conflict between %s and %s", class_name, other_class_name); } if (strcmp(prefix, other_prefix) == 0 && strcmp(cnick, other_cnick) == 0 ) { CFCUtil_die("Class nickname conflict between %s and %s", class_name, other_class_name); } } registry[registry_size].key = CFCUtil_strdup(key); registry[registry_size].klass = (CFCClass*)CFCBase_incref((CFCBase*)self); registry_size++; }
CFCClass* CFCUri_get_class(CFCUri *self) { if (self->type == 0) { S_parse(self); } if (self->klass == NULL) { CFCUtil_die("Not a class URI"); } return self->klass; }
CFCDocument* CFCUri_get_document(CFCUri *self) { if (self->type == 0) { S_parse(self); } if (self->document == NULL) { CFCUtil_die("Not a document URI"); } return self->document; }
void CFCPerlClass_exclude_method(CFCPerlClass *self, const char *meth_name) { if (!self->client) { CFCUtil_die("Can't exclude_method %s -- can't find client for %s", meth_name, self->class_name); } CFCMethod *method = CFCClass_method(self->client, meth_name); if (!method) { CFCUtil_die("Can't exclude_method %s -- method not found in %s", meth_name, self->class_name); } if (strcmp(CFCMethod_get_class_name(method), self->class_name) != 0) { CFCUtil_die("Can't exclude_method %s -- method not fresh in %s", meth_name, self->class_name); } CFCMethod_exclude_from_host(method); }
const char* CFCUri_get_callable_name(CFCUri *self) { if (self->type == 0) { S_parse(self); } if (self->callable == NULL) { CFCUtil_die("Not a callable URI"); } return self->callable; }
void CFCMethod_exclude_from_host(CFCMethod *self) { if (!self->is_novel) { CFCUtil_die("Can't exclude_from_host -- method %s not novel in %s", self->macro_sym, CFCMethod_get_class_name(self)); } self->is_excluded = true; }
void CFCMethod_set_host_alias(CFCMethod *self, const char *alias) { if (!alias || !alias[0]) { CFCUtil_die("Missing required param 'alias'"); } if (!self->is_novel) { CFCUtil_die("Can't set_host_alias %s -- method %s not novel in %s", alias, self->macro_sym, CFCMethod_get_class_name(self)); } if (self->host_alias) { if (strcmp(self->host_alias, alias) == 0) { return; } CFCUtil_die("Can't set_host_alias %s -- already set to %s for method" " %s in %s", alias, self->host_alias, self->macro_sym, CFCMethod_get_class_name(self)); } self->host_alias = CFCUtil_strdup(alias); }
const char* CFCUri_get_error(CFCUri *self) { if (self->type == 0) { S_parse(self); } if (self->error == NULL) { CFCUtil_die("Not an error URI"); } return self->error; }