Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
    }
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
/* 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;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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);
}
Ejemplo n.º 15
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;
}
Ejemplo n.º 16
0
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);
    }
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
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;
    }
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
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;
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
0
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++;
}
Ejemplo n.º 24
0
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;
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
0
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);
}
Ejemplo n.º 27
0
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;
}
Ejemplo n.º 28
0
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;
}
Ejemplo n.º 29
0
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);
}
Ejemplo n.º 30
0
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;
}