char* CFCBindMeth_abstract_method_def(CFCMethod *method, CFCClass *klass) { CFCType *ret_type = CFCMethod_get_return_type(method); const char *ret_type_str = CFCType_to_c(ret_type); CFCType *type = CFCMethod_self_type(method); const char *class_var = CFCType_get_class_var(type); const char *meth_name = CFCMethod_get_name(method); CFCParamList *param_list = CFCMethod_get_param_list(method); const char *params = CFCParamList_to_c(param_list); CFCVariable **vars = CFCParamList_get_variables(param_list); const char *invocant = CFCVariable_get_name(vars[0]); // All variables other than the invocant are unused, and the return is // unreachable. char *unused = CFCUtil_strdup(""); for (int i = 1; vars[i] != NULL; i++) { const char *var_name = CFCVariable_get_name(vars[i]); size_t size = strlen(unused) + strlen(var_name) + 80; unused = (char*)REALLOCATE(unused, size); strcat(unused, "\n CFISH_UNUSED_VAR("); strcat(unused, var_name); strcat(unused, ");"); } char *unreachable; if (!CFCType_is_void(ret_type)) { unreachable = CFCUtil_sprintf(" CFISH_UNREACHABLE_RETURN(%s);\n", ret_type_str); } else { unreachable = CFCUtil_strdup(""); } char *full_func_sym = CFCMethod_imp_func(method, klass); char pattern[] = "%s\n" "%s(%s) {\n" "%s" " cfish_Err_abstract_method_call((cfish_Obj*)%s, %s, \"%s\");\n" "%s" "}\n"; char *abstract_def = CFCUtil_sprintf(pattern, ret_type_str, full_func_sym, params, unused, invocant, class_var, meth_name, unreachable); FREEMEM(unused); FREEMEM(unreachable); FREEMEM(full_func_sym); return abstract_def; }
/* 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; }
static char* S_allot_params_arg(CFCType *type, const char *label, int required) { const char *type_c_string = CFCType_to_c(type); unsigned label_len = (unsigned)strlen(label); const char *req_string = required ? "true" : "false"; if (CFCType_is_object(type)) { const char *struct_sym = CFCType_get_specifier(type); const char *class_var = CFCType_get_class_var(type); // Share buffers rather than copy between Perl scalars and Clownfish // string types. int use_sv_buffer = false; if (strcmp(struct_sym, "cfish_String") == 0 || strcmp(struct_sym, "cfish_Obj") == 0 ) { use_sv_buffer = true; } const char *allocation = use_sv_buffer ? "alloca(cfish_SStr_size())" : "NULL"; const char pattern[] = "ALLOT_OBJ(&arg_%s, \"%s\", %u, %s, %s, %s)"; char *arg = CFCUtil_sprintf(pattern, label, label, label_len, req_string, class_var, allocation); return arg; } else if (CFCType_is_primitive(type)) { for (int i = 0; prim_type_to_allot_macro[i].prim_type != NULL; i++) { const char *prim_type = prim_type_to_allot_macro[i].prim_type; if (strcmp(prim_type, type_c_string) == 0) { const char *allot = prim_type_to_allot_macro[i].allot_macro; char pattern[] = "%s(&arg_%s, \"%s\", %u, %s)"; char *arg = CFCUtil_sprintf(pattern, allot, label, label, label_len, req_string); return arg; } } } CFCUtil_die("Missing typemap for %s", type_c_string); return NULL; // unreachable }
static char* S_build_pymeth_invocation(CFCMethod *method) { CFCType *return_type = CFCMethod_get_return_type(method); const char *micro_sym = CFCSymbol_get_name((CFCSymbol*)method); char *invocation = NULL; const char *ret_type_str = CFCType_to_c(return_type); if (CFCType_is_void(return_type)) { const char pattern[] = " CALL_PYMETH_VOID((PyObject*)self, \"%s\", cfcb_ARGS);"; invocation = CFCUtil_sprintf(pattern, micro_sym); } else if (CFCType_is_object(return_type)) { const char *nullable = CFCType_nullable(return_type) ? "true" : "false"; const char *ret_class = CFCType_get_class_var(return_type); const char pattern[] = " %s cfcb_RESULT = (%s)CALL_PYMETH_OBJ((PyObject*)self, \"%s\", cfcb_ARGS, %s, %s);"; invocation = CFCUtil_sprintf(pattern, ret_type_str, ret_type_str, micro_sym, ret_class, nullable); } else if (CFCType_is_primitive(return_type)) { char type_upcase[64]; if (strlen(ret_type_str) > 63) { CFCUtil_die("Unexpectedly long type name: %s", ret_type_str); } for (int i = 0, max = strlen(ret_type_str) + 1; i < max; i++) { type_upcase[i] = toupper(ret_type_str[i]); } const char pattern[] = " %s cfcb_RESULT = CALL_PYMETH_%s((PyObject*)self, \"%s\", cfcb_ARGS);"; invocation = CFCUtil_sprintf(pattern, ret_type_str, type_upcase, micro_sym); } else { CFCUtil_die("Unexpected return type: %s", CFCType_to_c(return_type)); } return invocation; }