Beispiel #1
0
static char*
S_convert_link(CFCClass *klass, cmark_node *link) {
    cmark_node *child = cmark_node_first_child(link);
    const char *uri   = cmark_node_get_url(link);
    char       *text  = S_nodes_to_pod(klass, child);
    char       *retval;

    if (!CFCUri_is_clownfish_uri(uri)) {
        retval = S_pod_link(text, uri);
        FREEMEM(text);
        return retval;
    }

    char   *new_uri  = NULL;
    char   *new_text = NULL;
    CFCUri *uri_obj  = CFCUri_new(uri, klass);
    int     type     = CFCUri_get_type(uri_obj);

    switch (type) {
        case CFC_URI_NULL:
            // Change all instances of NULL to 'undef'
            new_text = CFCUtil_strdup("undef");
            break;

        case CFC_URI_CLASS: {
            const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
            CFCClass *uri_class
                = CFCClass_fetch_by_struct_sym(full_struct_sym);

            if (!uri_class) {
                CFCUtil_warn("URI class not found: %s", full_struct_sym);
            }
            else if (uri_class != klass) {
                const char *class_name = CFCClass_get_class_name(uri_class);
                new_uri = CFCUtil_strdup(class_name);
            }

            if (text[0] != '\0') {
                // Keep text.
                break;
            }

            if (strcmp(CFCUri_get_prefix(uri_obj),
                       CFCClass_get_prefix(klass)) == 0
            ) {
                // Same parcel.
                const char *struct_sym = CFCUri_get_struct_sym(uri_obj);
                new_text = CFCUtil_strdup(struct_sym);
            }
            else {
                // Other parcel.
                if (!uri_class) {
                    new_text = CFCUtil_strdup(full_struct_sym);
                }
                else {
                    const char *class_name
                        = CFCClass_get_class_name(uri_class);
                    new_text = CFCUtil_strdup(class_name);
                }
            }

            break;
        }

        case CFC_URI_FUNCTION:
        case CFC_URI_METHOD: {
            const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
            const char *func_sym        = CFCUri_get_func_sym(uri_obj);

            // Convert "Err_get_error" to "Clownfish->error".
            if (strcmp(full_struct_sym, "cfish_Err") == 0
                && strcmp(func_sym, "get_error") == 0
            ) {
                new_text = CFCUtil_strdup("Clownfish->error");
                break;
            }

            CFCClass *uri_class
                = CFCClass_fetch_by_struct_sym(full_struct_sym);

            // TODO: Link to relevant POD section. This isn't easy because
            // the section headers for functions also contain a description
            // of the parameters.

            if (!uri_class) {
                CFCUtil_warn("URI class not found: %s", full_struct_sym);
            }
            else if (uri_class != klass) {
                const char *class_name = CFCClass_get_class_name(uri_class);
                new_uri = CFCUtil_strdup(class_name);
            }

            new_text = CFCUtil_sprintf("%s()", func_sym);
            for (size_t i = 0; new_text[i] != '\0'; ++i) {
                new_text[i] = tolower(new_text[i]);
            }

            break;
        }
    }

    if (new_text) {
        FREEMEM(text);
        text = new_text;
    }

    if (new_uri) {
        retval = S_pod_link(text, new_uri);
        FREEMEM(new_uri);
        FREEMEM(text);
    }
    else {
        retval = text;
    }

    CFCBase_decref((CFCBase*)uri_obj);

    return retval;
}
Beispiel #2
0
static void
S_resolve(CFCUri *self, const char *parcel, const char *struct_sym,
          const char *callable) {

    // Try to find a CFCClass.
    CFCClass *doc_class = self->doc_class;
    CFCClass *klass     = NULL;

    if (parcel) {
        char *full_struct_sym = CFCUtil_sprintf("%s_%s", parcel, struct_sym);
        klass = CFCClass_fetch_by_struct_sym(full_struct_sym);
        FREEMEM(full_struct_sym);
    }
    else if (struct_sym && doc_class) {
        const char *prefix = CFCClass_get_prefix(doc_class);
        char *full_struct_sym = CFCUtil_sprintf("%s%s", prefix, struct_sym);
        klass = CFCClass_fetch_by_struct_sym(full_struct_sym);
        FREEMEM(full_struct_sym);
    }
    else if (callable) {
        klass = doc_class;
    }

    if (klass) {
        if (!CFCClass_public(klass)) {
            CFCUtil_warn("Non-public class '%s' in Clownfish URI: %s",
                          CFCClass_get_struct_sym(klass), self->string);
        }

        self->type  = CFC_URI_CLASS;
        self->klass = klass;
        CFCBase_incref((CFCBase*)klass);

        if (callable) {
            if (islower(callable[0])) {
                CFCFunction *function = CFCClass_function(klass, callable);

                if (!function) {
                    CFCUtil_warn("Unknown function '%s' in Clownfish URI: %s",
                                 callable, self->string);
                }
                else if (!CFCFunction_public(function)) {
                    CFCUtil_warn("Non-public function '%s' in Clownfish URI:"
                                 " %s", callable, self->string);
                }

                self->type     = CFC_URI_FUNCTION;
                self->callable = CFCUtil_strdup(callable);
            }
            else {
                CFCMethod *method = CFCClass_method(klass, callable);

                if (!method) {
                    CFCUtil_warn("Unknown method '%s' in Clownfish URI: %s",
                                 callable, self->string);
                }
                else if (!CFCMethod_public(method)) {
                    CFCUtil_warn("Non-public method '%s' in Clownfish URI:"
                                 " %s", callable, self->string);
                }

                self->type     = CFC_URI_METHOD;
                self->callable = CFCUtil_strdup(callable);
            }
        }

        return;
    }

    // Try to find a CFCDocument.
    if (!parcel && struct_sym && !callable) {
        CFCDocument *doc = CFCDocument_fetch(struct_sym);

        if (doc) {
            self->type     = CFC_URI_DOCUMENT;
            self->document = doc;
            CFCBase_incref((CFCBase*)doc);
            return;
        }
    }

    S_set_error(self, "Couldn't resolve Clownfish URI");
}
Beispiel #3
0
char*
CFCC_link_text(CFCUri *uri_obj, CFCClass *klass) {
    char *link_text = NULL;
    int   type      = CFCUri_get_type(uri_obj);

    switch (type) {
        case CFC_URI_CLASS: {
            if (strcmp(CFCUri_get_prefix(uri_obj),
                       CFCClass_get_prefix(klass)) == 0
            ) {
                // Same parcel.
                const char *struct_sym = CFCUri_get_struct_sym(uri_obj);
                link_text = CFCUtil_strdup(struct_sym);
            }
            else {
                // Other parcel.
                const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
                CFCClass *uri_class
                    = CFCClass_fetch_by_struct_sym(full_struct_sym);
                if (!uri_class) {
                    CFCUtil_warn("URI class not found: %s", full_struct_sym);
                }
                else {
                    const char *class_name
                        = CFCClass_get_class_name(uri_class);
                    link_text = CFCUtil_strdup(class_name);
                }
            }

            break;
        }

        case CFC_URI_FUNCTION:
        case CFC_URI_METHOD: {
#if 1
            const char *func_sym = CFCUri_get_func_sym(uri_obj);
            link_text = CFCUtil_sprintf("%s()", func_sym);
#else
            // Full function sym.
            const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
            const char *func_sym        = CFCUri_get_func_sym(uri_obj);

            if (strcmp(full_struct_sym,
                       CFCClass_full_struct_sym(klass)) == 0
            ) {
                // Same class.
                link_text = CFCUtil_sprintf("%s()", func_sym);
            }
            else {
                CFCClass *uri_class
                    = CFCClass_fetch_by_struct_sym(full_struct_sym);

                if (!uri_class) {
                    CFCUtil_warn("URI class not found: %s", full_struct_sym);
                    link_text = CFCUtil_sprintf("%s()", func_sym);
                }
                else {
                    const char *prefix   = CFCUri_get_prefix(uri_obj);
                    const char *nickname = CFCClass_get_nickname(uri_class);

                    if (strcmp(prefix, CFCClass_get_prefix(klass)) == 0) {
                        // Same parcel.
                        link_text = CFCUtil_sprintf("%s_%s()", nickname,
                                                    func_sym);
                    }
                    else {
                        // Other parcel.
                        link_text = CFCUtil_sprintf("%s%s_%s()", prefix,
                                                    nickname, func_sym);
                    }
                }
            }
#endif
            break;
        }
    }

    return link_text;
}