static char* S_camel_to_lower(const char *camel) { if (camel[0] == '\0') { return CFCUtil_strdup(""); } size_t alloc = 1; for (size_t i = 1; camel[i]; i++) { if (CFCUtil_isupper(camel[i]) && CFCUtil_islower(camel[i+1])) { alloc += 1; } alloc += 1; } char *lower = (char*)MALLOCATE(alloc + 1); lower[0] = CFCUtil_tolower(camel[0]); size_t j = 1; for (size_t i = 1; camel[i]; i++) { // Only insert underscore if next char is lowercase. if (CFCUtil_isupper(camel[i]) && CFCUtil_islower(camel[i+1])) { lower[j++] = '_'; } lower[j++] = CFCUtil_tolower(camel[i]); } lower[j] = '\0'; return lower; }
static char* S_convert_link(cmark_node *link, CFCClass *doc_class, int header_level) { cmark_node *child = cmark_node_first_child(link); const char *uri = cmark_node_get_url(link); char *text = S_nodes_to_pod(child, doc_class, header_level); 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, doc_class); CFCUriType type = CFCUri_get_type(uri_obj); switch (type) { case CFC_URI_ERROR: { const char *error = CFCUri_get_error(uri_obj); new_text = CFCUtil_sprintf("[%s]", error); break; } case CFC_URI_NULL: // Change all instances of NULL to 'undef' new_text = CFCUtil_strdup("undef"); break; case CFC_URI_CLASS: { CFCClass *klass = CFCUri_get_class(uri_obj); if (klass != doc_class) { const char *class_name = CFCClass_get_name(klass); new_uri = CFCUtil_strdup(class_name); } if (text[0] == '\0') { const char *src = CFCClass_included(klass) ? CFCClass_get_name(klass) : CFCClass_get_struct_sym(klass); new_text = CFCUtil_strdup(src); } break; } case CFC_URI_FUNCTION: case CFC_URI_METHOD: { CFCClass *klass = CFCUri_get_class(uri_obj); const char *name = CFCUri_get_callable_name(uri_obj); // Convert "Err_get_error" to "Clownfish->error". if (strcmp(CFCClass_full_struct_sym(klass), "cfish_Err") == 0 && strcmp(name, "get_error") == 0 ) { new_text = CFCUtil_strdup("Clownfish->error"); break; } char *perl_name = CFCUtil_strdup(name); for (size_t i = 0; perl_name[i] != '\0'; ++i) { perl_name[i] = CFCUtil_tolower(perl_name[i]); } // The Perl POD only contains sections for novel methods. Link // to the class where the method is declared first. if (type == CFC_URI_METHOD) { CFCClass *parent = CFCClass_get_parent(klass); while (parent && CFCClass_method(parent, name)) { klass = parent; parent = CFCClass_get_parent(klass); } } if (klass == doc_class) { new_uri = CFCUtil_sprintf("/%s", perl_name); } else { const char *class_name = CFCClass_get_name(klass); new_uri = CFCUtil_sprintf("%s/%s", class_name, perl_name); } if (text[0] == '\0') { new_text = CFCUtil_sprintf("%s()", perl_name); } FREEMEM(perl_name); break; } case CFC_URI_DOCUMENT: { CFCDocument *doc = CFCUri_get_document(uri_obj); const char *path_part = CFCDocument_get_path_part(doc); new_uri = CFCUtil_global_replace(path_part, CHY_DIR_SEP, "::"); if (text[0] == '\0') { const char *name = CFCDocument_get_name(doc); new_text = CFCUtil_strdup(name); } 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; }
CFCParcel* CFCParcel_init(CFCParcel *self, const char *name, const char *nickname, CFCVersion *version, CFCVersion *major_version, CFCFileSpec *file_spec) { // Validate name. if (!name || !S_validate_name_or_nickname(name)) { CFCUtil_die("Invalid name: '%s'", name ? name : "[NULL]"); } self->name = CFCUtil_strdup(name); // Validate or derive nickname. if (nickname) { if (!S_validate_name_or_nickname(nickname)) { CFCUtil_die("Invalid nickname: '%s'", nickname); } self->nickname = CFCUtil_strdup(nickname); } else { // Default nickname to name. self->nickname = CFCUtil_strdup(name); } // Default to version v0. if (version) { self->version = (CFCVersion*)CFCBase_incref((CFCBase*)version); } else { self->version = CFCVersion_new("v0"); } if (major_version) { self->major_version = (CFCVersion*)CFCBase_incref((CFCBase*)major_version); } else { self->major_version = CFCVersion_new("v0"); } // Set file_spec. self->file_spec = (CFCFileSpec*)CFCBase_incref((CFCBase*)file_spec); // Derive prefix, Prefix, PREFIX. size_t nickname_len = strlen(self->nickname); size_t prefix_len = nickname_len ? nickname_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->nickname, nickname_len); if (nickname_len) { self->Prefix[nickname_len] = '_'; self->Prefix[nickname_len + 1] = '\0'; } else { self->Prefix[nickname_len] = '\0'; } for (size_t i = 0; i < amount; i++) { self->prefix[i] = CFCUtil_tolower(self->Prefix[i]); self->PREFIX[i] = CFCUtil_toupper(self->Prefix[i]); } self->prefix[prefix_len] = '\0'; self->Prefix[prefix_len] = '\0'; self->PREFIX[prefix_len] = '\0'; // Derive privacy symbol. size_t privacy_sym_len = nickname_len + 4; self->privacy_sym = (char*)MALLOCATE(privacy_sym_len + 1); memcpy(self->privacy_sym, "CFP_", 4); for (size_t i = 0; i < nickname_len; i++) { self->privacy_sym[i+4] = CFCUtil_toupper(self->nickname[i]); } self->privacy_sym[privacy_sym_len] = '\0'; // Initialize flags. self->is_installed = false; // Initialize arrays. self->classes = (CFCClass**)CALLOCATE(1, sizeof(CFCClass*)); self->num_classes = 0; self->prereqs = (CFCPrereq**)CALLOCATE(1, sizeof(CFCPrereq*)); self->num_prereqs = 0; return self; }