예제 #1
0
// Generate C code which initializes method metadata.
char*
CFCPerlClass_method_metadata_code(CFCPerlClass *self) {
    const char *class_var = CFCClass_full_class_var(self->client);
    CFCMethod **fresh_methods = CFCClass_fresh_methods(self->client);
    char *code = CFCUtil_strdup("");

    for (int i = 0; fresh_methods[i] != NULL; i++) {
        CFCMethod *method = fresh_methods[i];
        if (!CFCMethod_novel(method)) { continue; }

        const char *macro_sym = CFCMethod_get_macro_sym(method);
        const char *alias     = CFCMethod_get_host_alias(method);
        if (alias) {
            code = CFCUtil_cat(code, "    CFISH_Class_Add_Host_Method_Alias(",
                               class_var, ", \"", alias, "\", \"", macro_sym,
                               "\");\n", NULL);
        }
        if (CFCMethod_excluded_from_host(method)) {
            code = CFCUtil_cat(code, "    CFISH_Class_Exclude_Host_Method(",
                               class_var, ", \"", macro_sym, "\");\n", NULL);
        }
    }

    return code;
}
예제 #2
0
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;
}
예제 #3
0
static char*
S_callback_refcount_mods(CFCParamList *param_list) {
    char *refcount_mods = CFCUtil_strdup("");
    CFCVariable **arg_vars = CFCParamList_get_variables(param_list);

    // Adjust refcounts of arguments per method signature, so that Perl code
    // does not have to.
    for (int i = 0; arg_vars[i] != NULL; i++) {
        CFCVariable *var  = arg_vars[i];
        CFCType     *type = CFCVariable_get_type(var);
        const char  *name = CFCVariable_get_name(var);
        if (!CFCType_is_object(type)) {
            continue;
        }
        else if (CFCType_incremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "    CFISH_INCREF(",
                                        name, ");\n", NULL);
        }
        else if (CFCType_decremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "    CFISH_DECREF(",
                                        name, ");\n", NULL);
        }
    }

    return refcount_mods;
}
예제 #4
0
파일: CFCPerl.c 프로젝트: hernan604/lucy
static char*
S_add_xs_init(char *xs_init, CFCPerlSub *xsub) {
    const char *c_name = CFCPerlSub_c_name(xsub);
    const char *perl_name = CFCPerlSub_perl_name(xsub);
    if (strlen(xs_init)) {
        xs_init = CFCUtil_cat(xs_init, "\n    ", NULL);
    }
    xs_init = CFCUtil_cat(xs_init, "newXS(\"", perl_name, "\", ", c_name,
                          ", file);", NULL);
    return xs_init;
}
예제 #5
0
static char*
S_gen_code_sample(CFCCallable *func, const char *alias, CFCClass *klass,
                  int is_constructor) {
    char *prologue       = CFCUtil_sprintf("");
    char *class_var_name = S_camel_to_lower(CFCClass_get_struct_sym(klass));

    CFCType *ret_type = CFCCallable_get_return_type(func);
    if (!CFCType_is_void(ret_type)) {
        char *ret_name = S_perl_var_name(ret_type, is_constructor);

        if (!is_constructor && strcmp(ret_name, class_var_name) == 0) {
            // Return type equals `klass`. Use a generic variable name
            // to avoid confusing code samples like
            // `my $string = $string->trim`.
            prologue = CFCUtil_cat(prologue, "my $result = ", NULL);
        }
        else {
            prologue = CFCUtil_cat(prologue, "my $", ret_name, " = ", NULL);
        }

        FREEMEM(ret_name);
    }

    if (is_constructor) {
        const char *invocant = CFCClass_get_name(klass);
        prologue = CFCUtil_cat(prologue, invocant, NULL);
    }
    else {
        prologue = CFCUtil_cat(prologue, "$", class_var_name, NULL);
    }

    prologue = CFCUtil_cat(prologue, "->", alias, NULL);

    CFCParamList *param_list = CFCCallable_get_param_list(func);
    int           num_vars   = CFCParamList_num_vars(param_list);
    int           start      = is_constructor ? 0 : 1;
    char         *sample     = NULL;

    if (start == num_vars) {
        sample = CFCUtil_sprintf("    %s();\n", prologue);
    }
    else if (is_constructor || num_vars - start >= 2) {
        sample = S_gen_labeled_sample(prologue, param_list, start);
    }
    else {
        sample = S_gen_positional_sample(prologue, param_list, start);
    }

    FREEMEM(class_var_name);
    FREEMEM(prologue);
    return sample;
}
예제 #6
0
void
CFCPerlClass_append_xs(CFCPerlClass *self, const char *xs) {
    if (!self->xs_code) {
        self->xs_code = CFCUtil_strdup("");
    }
    self->xs_code = CFCUtil_cat(self->xs_code, xs, NULL);
}
예제 #7
0
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;
}
예제 #8
0
static void
S_add_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
                      int meth_index) {
    const char *sep = meth_index == 0 ? "" : ",\n";

    char *imp_func        = CFCMethod_imp_func(method, klass);
    char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
    char *parent_offset   = S_parent_offset(self, method, klass, "overridden",
                                            meth_index);

    char pattern[] =
        "    {\n"
        "        &%s, /* offset */\n"
        "        %s, /* parent_offset */\n"
        "        (cfish_method_t)%s /* func */\n"
        "    }";
    char *def
        = CFCUtil_sprintf(pattern, full_offset_sym, parent_offset, imp_func);
    self->overridden_specs
        = CFCUtil_cat(self->overridden_specs, sep, def, NULL);

    FREEMEM(def);
    FREEMEM(parent_offset);
    FREEMEM(full_offset_sym);
    FREEMEM(imp_func);
}
예제 #9
0
static char*
S_parent_offset(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
                const char *meth_type, int meth_index) {
    CFCClass *parent = CFCClass_get_parent(klass);

    if (!parent) {
        return CFCUtil_strdup("NULL");
    }

    char *parent_offset = NULL;
    char *parent_offset_sym = CFCMethod_full_offset_sym(method, parent);

    if (CFCClass_in_same_parcel(klass, parent)) {
        parent_offset = CFCUtil_sprintf("&%s", parent_offset_sym);
    }
    else {
        parent_offset = CFCUtil_strdup("NULL");

        char pattern[] = "    %s_specs[%d].parent_offset = &%s;\n";
        char *code = CFCUtil_sprintf(pattern, meth_type, meth_index,
                                     parent_offset_sym);
        self->init_code = CFCUtil_cat(self->init_code, code, NULL);
        FREEMEM(code);
    }

    FREEMEM(parent_offset_sym);

    return parent_offset;
}
예제 #10
0
static void
S_add_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
                 int meth_index) {
    const char *meth_name = CFCMethod_get_name(method);
    const char *sep = meth_index == 0 ? "" : ",\n";

    char *full_override_sym;
    if (!CFCMethod_final(method) && !CFCMethod_excluded_from_host(method)) {
        full_override_sym = CFCMethod_full_override_sym(method, klass);
    }
    else {
        full_override_sym = CFCUtil_strdup("NULL");
    }

    char *imp_func        = CFCMethod_imp_func(method, klass);
    char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);

    char pattern[] =
        "    {\n"
        "        &%s, /* offset */\n"
        "        \"%s\", /* name */\n"
        "        (cfish_method_t)%s, /* func */\n"
        "        (cfish_method_t)%s /* callback_func */\n"
        "    }";
    char *def
        = CFCUtil_sprintf(pattern, full_offset_sym, meth_name, imp_func,
                          full_override_sym);
    self->novel_specs = CFCUtil_cat(self->novel_specs, sep, def, NULL);

    FREEMEM(def);
    FREEMEM(full_offset_sym);
    FREEMEM(imp_func);
    FREEMEM(full_override_sym);
}
예제 #11
0
char*
CFCPerlPod_methods_pod(CFCPerlPod *self, CFCClass *klass) {
    const char *class_name = CFCClass_get_class_name(klass);
    char *abstract_pod = CFCUtil_strdup("");
    char *methods_pod  = CFCUtil_strdup("");
    for (size_t i = 0; i < self->num_methods; i++) {
        NamePod meth_spec = self->methods[i];
        CFCMethod *method = CFCClass_method(klass, meth_spec.func);
        if (!method) {
            method = CFCClass_method(klass, meth_spec.alias);
        }
        if (!method) {
            CFCUtil_die("Can't find method '%s' in class '%s'",
                        meth_spec.alias, CFCClass_get_class_name(klass));
        }
        char *meth_pod;
        if (meth_spec.pod) {
            meth_pod = CFCUtil_sprintf("%s\n", meth_spec.pod);
        }
        else {
            meth_pod
                = CFCPerlPod_gen_subroutine_pod(self, (CFCFunction*)method,
                                                meth_spec.alias, klass,
                                                meth_spec.sample, class_name,
                                                false);
        }
        if (CFCMethod_abstract(method)) {
            abstract_pod = CFCUtil_cat(abstract_pod, meth_pod, NULL);
        }
        else {
            methods_pod = CFCUtil_cat(methods_pod, meth_pod, NULL);
        }
        FREEMEM(meth_pod);
    }

    char *pod = CFCUtil_strdup("");
    if (strlen(abstract_pod)) {
        pod = CFCUtil_cat(pod, "=head1 ABSTRACT METHODS\n\n", abstract_pod, NULL);
    }
    FREEMEM(abstract_pod);
    if (strlen(methods_pod)) {
        pod = CFCUtil_cat(pod, "=head1 METHODS\n\n", methods_pod, NULL);
    }
    FREEMEM(methods_pod);

    return pod;
}
예제 #12
0
char*
CFCPerlSub_build_allot_params(CFCPerlSub *self) {
    CFCParamList *param_list = self->param_list;
    CFCVariable **arg_vars   = CFCParamList_get_variables(param_list);
    const char  **arg_inits  = CFCParamList_get_initial_values(param_list);
    size_t        num_vars   = CFCParamList_num_vars(param_list);
    char *allot_params = CFCUtil_strdup("");

    // Declare variables and assign default values.
    for (size_t i = 1; i < num_vars; i++) {
        CFCVariable *arg_var  = arg_vars[i];
        const char  *val      = arg_inits[i];
        const char  *var_name = CFCVariable_micro_sym(arg_var);
        if (val == NULL) {
            CFCType *arg_type = CFCVariable_get_type(arg_var);
            val = CFCType_is_object(arg_type)
                  ? "NULL"
                  : "0";
        }
        allot_params = CFCUtil_cat(allot_params, "arg_", var_name, " = ", val,
                                   ";\n    ", NULL);
    }

    // Iterate over args in param list.
    allot_params
        = CFCUtil_cat(allot_params,
                      "args_ok = XSBind_allot_params(\n"
                      "        &(ST(0)), 1, items,\n", NULL);
    for (size_t i = 1; i < num_vars; i++) {
        CFCVariable *var = arg_vars[i];
        const char  *val = arg_inits[i];
        int required = val ? 0 : 1;
        const char *name = CFCVariable_micro_sym(var);
        CFCType *type = CFCVariable_get_type(var);
        char *arg = S_allot_params_arg(type, name, required);
        allot_params
            = CFCUtil_cat(allot_params, "        ", arg, ",\n", NULL);
        FREEMEM(arg);
    }
    allot_params
        = CFCUtil_cat(allot_params, "        NULL);\n",
                      "    if (!args_ok) {\n"
                      "        CFISH_RETHROW(CFISH_INCREF(cfish_Err_get_error()));\n"
                      "    }", NULL);

    return allot_params;
}
예제 #13
0
static char*
S_charmony_alloca_defines() {
    char *defines = CFCUtil_strdup("");

#if defined(CHY_HAS_ALLOCA_H)
    defines = CFCUtil_cat(defines, "#include <alloca.h>\n", NULL);
#elif defined(CHY_HAS_MALLOC_H)
    defines = CFCUtil_cat(defines, "#include <malloc.h>\n", NULL);
#elif defined(CHY_ALLOCA_IN_STDLIB_H)
    defines = CFCUtil_cat(defines, "#include <stdlib.h>\n", NULL);
#endif

    defines = CFCUtil_cat(defines, "#define cfish_alloca ",
                          XSTRING(chy_alloca), "\n", NULL);

    return defines;
}
예제 #14
0
char*
CFCPerlConstructor_xsub_def(CFCPerlConstructor *self) {
    const char *c_name = self->sub.c_name;
    CFCParamList *param_list = self->sub.param_list;
    const char   *name_list  = CFCParamList_name_list(param_list);
    CFCVariable **arg_vars   = CFCParamList_get_variables(param_list);
    const char   *func_sym   = CFCFunction_full_func_sym(self->init_func);
    char *allot_params = CFCPerlSub_build_allot_params((CFCPerlSub*)self);
    CFCVariable *self_var       = arg_vars[0];
    CFCType     *self_type      = CFCVariable_get_type(self_var);
    const char  *self_type_str  = CFCType_to_c(self_type);

    // Compensate for swallowed refcounts.
    char *refcount_mods = CFCUtil_strdup("");
    for (size_t i = 0; arg_vars[i] != NULL; i++) {
        CFCVariable *var = arg_vars[i];
        CFCType *type = CFCVariable_get_type(var);
        if (CFCType_is_object(type) && CFCType_decremented(type)) {
            const char *name = CFCVariable_micro_sym(var);
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_INCREF(",
                                        name, ");", NULL);
        }
    }

    const char pattern[] =
        "XS(%s);\n"
        "XS(%s) {\n"
        "    dXSARGS;\n"
        "    CFISH_UNUSED_VAR(cv);\n"
        "    if (items < 1) { CFISH_THROW(CFISH_ERR, \"Usage: %%s(class_name, ...)\",  GvNAME(CvGV(cv))); }\n"
        "    SP -= items;\n"
        "\n"
        "    %s\n"
        // Create "self" last, so that earlier exceptions while fetching
        // params don't trigger a bad invocation of DESTROY.
        "    %s self = (%s)XSBind_new_blank_obj(ST(0));%s\n"
        "\n"
        "    %s retval = %s(%s);\n"
        "    if (retval) {\n"
        "        ST(0) = (SV*)CFISH_Obj_To_Host((cfish_Obj*)retval);\n"
        "        CFISH_Obj_Dec_RefCount((cfish_Obj*)retval);\n"
        "    }\n"
        "    else {\n"
        "        ST(0) = newSV(0);\n"
        "    }\n"
        "    sv_2mortal(ST(0));\n"
        "    XSRETURN(1);\n"
        "}\n\n";
    char *xsub_def
        = CFCUtil_sprintf(pattern, c_name, c_name, allot_params, self_type_str,
                          self_type_str, refcount_mods, self_type_str,
                          func_sym, name_list);

    FREEMEM(refcount_mods);
    FREEMEM(allot_params);

    return xsub_def;
}
예제 #15
0
static char*
S_add_xsub_spec(char *xsub_specs, CFCPerlSub *xsub) {
    const char *c_name = CFCPerlSub_c_name(xsub);
    const char *alias = CFCPerlSub_get_alias(xsub);
    const char *sep = xsub_specs[0] == '\0' ? "" : ",\n";
    xsub_specs = CFCUtil_cat(xsub_specs, sep, "        { \"", alias, "\", ",
                             c_name, " }", NULL);
    return xsub_specs;
}
예제 #16
0
static char*
S_build_py_args(CFCParamList *param_list) {
    int num_vars = CFCParamList_num_vars(param_list);
    CFCVariable **vars = CFCParamList_get_variables(param_list);
    char pattern[] = "    PyObject *cfcb_ARGS = S_pack_tuple(%d";
    char *py_args = CFCUtil_sprintf(pattern, num_vars - 1);

    for (int i = 1; vars[i] != NULL; i++) {
        const char *var_name = CFCVariable_get_name(vars[i]);
        CFCType *type = CFCVariable_get_type(vars[i]);
        char *conversion = CFCPyTypeMap_c_to_py(type, var_name);
        py_args = CFCUtil_cat(py_args, ",\n        ", conversion, NULL);
        FREEMEM(conversion);
    }
    py_args = CFCUtil_cat(py_args, ");", NULL);

    return py_args;
}
예제 #17
0
static char*
S_gen_arg_list(CFCParamList *param_list, const char *first_arg) {
    CFCVariable **vars = CFCParamList_get_variables(param_list);
    int num_vars = CFCParamList_num_vars(param_list);
    char *arg_list = CFCUtil_strdup("");
    for (int i = 0; i < num_vars; i++) {
        if (i > 0) {
            arg_list = CFCUtil_cat(arg_list, ", ", NULL);
        }
        if (i == 0 && first_arg != NULL) {
            arg_list = CFCUtil_cat(arg_list, first_arg, NULL);
        }
        else {
            arg_list = CFCUtil_cat(arg_list, CFCVariable_get_name(vars[i]),
                                   "_ARG", NULL);
        }
    }
    return arg_list;
}
예제 #18
0
static char*
S_charmony_feature_defines() {
    char *defines = CFCUtil_strdup("");

#ifdef CHY_LITTLE_END
    // Needed by NumberUtils.cfh.
    defines = CFCUtil_cat(defines, "#define CFISH_LITTLE_END\n", NULL);
#endif
#ifdef CHY_BIG_END
    // Needed by NumberUtils.cfh.
    defines = CFCUtil_cat(defines, "#define CFISH_BIG_END\n", NULL);
#endif
#ifdef CHY_HAS_FUNC_MACRO
    // Needed by Err.cfh.
    defines = CFCUtil_cat(defines, "#define CFISH_HAS_FUNC_MACRO\n", NULL);
#endif
#ifdef CHY_HAS_VARIADIC_MACROS
    // Needed by Err.cfh.
    defines = CFCUtil_cat(defines, "#define CFISH_HAS_VARIADIC_MACROS\n",
                          NULL);
#endif
#ifdef CHY_HAS_ISO_VARIADIC_MACROS
    // Needed by Err.cfh.
    defines = CFCUtil_cat(defines, "#define CFISH_HAS_ISO_VARIADIC_MACROS\n",
                          NULL);
#endif
#ifdef CHY_HAS_GNUC_VARIADIC_MACROS
    // Needed by Err.cfh.
    defines = CFCUtil_cat(defines, "#define CFISH_HAS_GNUC_VARIADIC_MACROS\n",
                          NULL);
#endif

    return defines;
}
예제 #19
0
char*
CFCGoClass_gen_meth_glue(CFCGoClass *self) {
    S_lazy_init_method_bindings(self);
    char *meth_defs = CFCUtil_strdup("");
    for (size_t i = 0; self->method_bindings[i] != NULL; i++) {
        CFCGoMethod *meth_binding = self->method_bindings[i];
        char *method_def
            = CFCGoMethod_func_def(meth_binding, self->client);
        meth_defs = CFCUtil_cat(meth_defs, method_def, "\n", NULL);
        FREEMEM(method_def);
    }
    return meth_defs;
}
예제 #20
0
static char*
S_gen_decs(CFCParamList *param_list, int first_tick) {
    char *decs = CFCUtil_strdup("");
    int num_vars = CFCParamList_num_vars(param_list);
    CFCVariable **vars = CFCParamList_get_variables(param_list);
    for (int i = first_tick; i < num_vars; i++) {
        CFCType *type = CFCVariable_get_type(vars[i]);
        const char *name = CFCVariable_get_name(vars[i]);
        decs = CFCUtil_cat(decs, "    ", CFCType_to_c(type), " ", name,
                           "_ARG = 0;\n", NULL);
    }
    return decs;
}
예제 #21
0
void
CFCPerlTypeMap_write_xs_typemap(CFCHierarchy *hierarchy) {
    CFCClass **classes = CFCHierarchy_ordered_classes(hierarchy);
    char *start  = CFCUtil_strdup("");
    char *input  = CFCUtil_strdup("");
    char *output = CFCUtil_strdup("");
    for (int i = 0; classes[i] != NULL; i++) {
        CFCClass *klass = classes[i];
        if (CFCClass_included(klass)) { continue; }

        const char *full_struct_sym = CFCClass_full_struct_sym(klass);
        const char *vtable_var      = CFCClass_full_vtable_var(klass);

        start = CFCUtil_cat(start, full_struct_sym, "*\t", vtable_var, "_\n",
                            NULL);
        input = CFCUtil_cat(input, vtable_var, "_\n"
                            "    $var = (", full_struct_sym,
                            "*)XSBind_sv_to_cfish_obj($arg, ", vtable_var,
                            ", NULL);\n\n", NULL);

        output = CFCUtil_cat(output, vtable_var, "_\n"
                             "    $arg = (SV*)Cfish_Obj_To_Host((cfish_Obj*)$var);\n"
                             "    CFISH_DECREF($var);\n"
                             "\n", NULL);
    }

    char *content = CFCUtil_strdup("");
    content = CFCUtil_cat(content, typemap_start, start, "\n\n",
                          typemap_input, input, "\n\n",
                          typemap_output, output, "\n\n", NULL);
    CFCUtil_write_if_changed("typemap", content, strlen(content));

    FREEMEM(content);
    FREEMEM(output);
    FREEMEM(input);
    FREEMEM(start);
    FREEMEM(classes);
}
예제 #22
0
char*
CFCPerlPod_constructors_pod(CFCPerlPod *self, CFCClass *klass) {
    if (!self->num_constructors) {
        return CFCUtil_strdup("");
    }
    const char *class_name = CFCClass_get_class_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 {
            CFCFunction *init_func = CFCClass_function(klass, slot.func);
            char *sub_pod
                = CFCPerlPod_gen_subroutine_pod(self, init_func, slot.alias, klass,
                                                slot.sample, class_name, true);
            pod = CFCUtil_cat(pod, sub_pod, NULL);
            FREEMEM(sub_pod);
        }
    }
    return pod;
}
예제 #23
0
// Convert a node and its siblings.
static char*
S_nodes_to_pod(cmark_node *node, CFCClass *klass, int header_level) {
    char *result = CFCUtil_strdup("");

    while (node != NULL) {
        char *pod = S_node_to_pod(node, klass, header_level);
        result = CFCUtil_cat(result, pod, NULL);
        FREEMEM(pod);

        node = cmark_node_next(node);
    }

    return result;
}
예제 #24
0
char*
CFCPerlSub_params_hash_def(CFCPerlSub *self) {
    if (!self->use_labeled_params) {
        return NULL;
    }

    char *def = CFCUtil_strdup("");
    def = CFCUtil_cat(def, "%", self->perl_name, "_PARAMS = (", NULL);

    CFCVariable **arg_vars = CFCParamList_get_variables(self->param_list);
    const char **vals = CFCParamList_get_initial_values(self->param_list);

    // No labeled params means an empty params hash def.
    if (!arg_vars[1]) {
        def = CFCUtil_cat(def, ");\n", NULL);
        return def;
    }

    for (int i = 1; arg_vars[i] != NULL; i++) {
        CFCVariable *var = arg_vars[i];
        const char *micro_sym = CFCVariable_micro_sym(var);
        const char *val = vals[i];
        val = val == NULL
              ? "undef"
              : strcmp(val, "NULL") == 0
              ? "undef"
              : strcmp(val, "true") == 0
              ? "1"
              : strcmp(val, "false") == 0
              ? "0"
              : val;
        def = CFCUtil_cat(def, "\n    ", micro_sym, " => ", val, ",", NULL);
    }
    def = CFCUtil_cat(def, "\n);\n", NULL);

    return def;
}
예제 #25
0
static char*
S_gen_labeled_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);

    size_t max_name_len = 0;

    // Find maximum length of parameter name.
    for (int i = start; i < num_vars; i++) {
        const char *name = CFCVariable_get_name(vars[i]);
        size_t name_len = strlen(name);
        if (name_len > max_name_len) { max_name_len = name_len; }
    }

    char *params = CFCUtil_strdup("");

    for (int i = start; i < num_vars; i++) {
        const char *name    = CFCVariable_get_name(vars[i]);
        const char *init    = inits[i];
        char       *comment = NULL;

        if (init) {
            if (strcmp(init, "NULL") == 0) { init = "undef"; }
            comment = CFCUtil_sprintf("default: %s", init);
        }
        else {
            comment = CFCUtil_strdup("required");
        }

        char *line = CFCUtil_sprintf("        %-*s => $%-*s  # %s\n",
                                     (int)max_name_len, name,
                                     (int)max_name_len, name,
                                     comment);
        params = CFCUtil_cat(params, line, NULL);
        FREEMEM(line);
        FREEMEM(comment);
    }

    const char pattern[] =
        "    %s(\n"
        "%s"
        "    );\n";
    char *sample = CFCUtil_sprintf(pattern, prologue, params);

    FREEMEM(params);
    return sample;
}
예제 #26
0
static char*
S_callback_refcount_mods(CFCMethod *method) {
    char *refcount_mods = CFCUtil_strdup("");
    CFCType *return_type = CFCMethod_get_return_type(method);
    CFCParamList *param_list = CFCMethod_get_param_list(method);
    CFCVariable **arg_vars = CFCParamList_get_variables(param_list);

    // Host_callback_obj returns an incremented object.  If this method does
    // not return an incremented object, we must cancel out that refcount.
    // (No function can return a decremented object.)
    if (CFCType_is_object(return_type) && !CFCType_incremented(return_type)) {
        refcount_mods = CFCUtil_cat(refcount_mods,
                                    "\n    CFISH_DECREF(retval);", NULL);
    }

    // The Host_callback_xxx functions have no effect on the refcounts of
    // arguments, so we need to adjust them after the fact.
    for (int i = 0; arg_vars[i] != NULL; i++) {
        CFCVariable *var  = arg_vars[i];
        CFCType     *type = CFCVariable_get_type(var);
        const char  *name = CFCVariable_micro_sym(var);
        if (!CFCType_is_object(type)) {
            continue;
        }
        else if (CFCType_incremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_INCREF(",
                                        name, ");", NULL);
        }
        else if (CFCType_decremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_DECREF(",
                                        name, ");", NULL);
        }
    }
    
    return refcount_mods;
}
예제 #27
0
파일: CFCPerlMethod.c 프로젝트: theory/lucy
static char*
S_callback_refcount_mods(CFCMethod *method) {
    char *refcount_mods = CFCUtil_strdup("");
    CFCType *return_type = CFCMethod_get_return_type(method);
    CFCParamList *param_list = CFCMethod_get_param_list(method);
    CFCVariable **arg_vars = CFCParamList_get_variables(param_list);

    // `XSBind_perl_to_cfish()` returns an incremented object.  If this method
    // does not return an incremented object, we must cancel out that
    // refcount.  (No function can return a decremented object.)
    if (CFCType_is_object(return_type) && !CFCType_incremented(return_type)) {
        refcount_mods = CFCUtil_cat(refcount_mods,
                                    "\n    CFISH_DECREF(retval);", NULL);
    }

    // Adjust refcounts of arguments per method signature, so that Perl code
    // does not have to.
    for (int i = 0; arg_vars[i] != NULL; i++) {
        CFCVariable *var  = arg_vars[i];
        CFCType     *type = CFCVariable_get_type(var);
        const char  *name = CFCVariable_micro_sym(var);
        if (!CFCType_is_object(type)) {
            continue;
        }
        else if (CFCType_incremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_INCREF(",
                                        name, ");", NULL);
        }
        else if (CFCType_decremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_DECREF(",
                                        name, ");", NULL);
        }
    }

    return refcount_mods;
}
예제 #28
0
char*
CFCPerlSub_arg_name_list(CFCPerlSub *self) {
    CFCParamList  *param_list = self->param_list;
    CFCVariable  **arg_vars   = CFCParamList_get_variables(param_list);
    size_t        num_vars   = CFCParamList_num_vars(param_list);
    char          *name_list  = CFCUtil_strdup("arg_self");

    for (int i = 1; i < num_vars; i++) {
        CFCVariable *arg_var  = arg_vars[i];
        const char  *var_name = CFCVariable_micro_sym(arg_vars[i]);
        name_list = CFCUtil_cat(name_list, ", arg_", var_name, NULL);
    }

    return name_list;
}
예제 #29
0
static char*
S_callback_decs(CFCClass *klass) {
    CFCMethod **fresh_methods = CFCClass_fresh_methods(klass);
    char       *cb_decs       = CFCUtil_strdup("");

    for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
        CFCMethod *method = fresh_methods[meth_num];

        // Define callback to NULL.
        if (CFCMethod_novel(method) && !CFCMethod_final(method)) {
            const char *override_sym = CFCMethod_full_override_sym(method);
            cb_decs = CFCUtil_cat(cb_decs, "#define ", override_sym, " NULL\n",
                                  NULL);
        }
    }

    return cb_decs;
}
예제 #30
0
static char*
S_gen_arg_increfs(CFCParamList *param_list, int first_tick) {
    CFCVariable **vars = CFCParamList_get_variables(param_list);
    int num_vars = CFCParamList_num_vars(param_list);
    char *content = CFCUtil_strdup("");
    for (int i = first_tick;i < num_vars; i++) {
        CFCType *type = CFCVariable_get_type(vars[i]);
        if (CFCType_decremented(type)) {
            const char *name = CFCVariable_get_name(vars[i]);
            const char *specifier = CFCType_get_specifier(type);
            char pattern[] =
                "    %s_ARG = (%s*)CFISH_INCREF(%s_ARG);\n";
            char *incref = CFCUtil_sprintf(pattern, name, specifier, name);
            content = CFCUtil_cat(content, incref, NULL);
            FREEMEM(incref);
        }
    }
    return content;
}