Repository: lucy-clownfish
Updated Branches:
  refs/heads/markdown [created] f57df2fc2


Rename CFCCClass to CFCCMan


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/3c667722
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/3c667722
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/3c667722

Branch: refs/heads/markdown
Commit: 3c667722e541d901c8d054c0f5d63d00ad5138ee
Parents: 846b230
Author: Nick Wellnhofer <[email protected]>
Authored: Sun Nov 23 12:57:15 2014 +0100
Committer: Nick Wellnhofer <[email protected]>
Committed: Sun Nov 23 17:33:55 2014 +0100

----------------------------------------------------------------------
 compiler/src/CFCC.c      |   4 +-
 compiler/src/CFCCClass.c | 516 ------------------------------------------
 compiler/src/CFCCClass.h |  36 ---
 compiler/src/CFCCMan.c   | 516 ++++++++++++++++++++++++++++++++++++++++++
 compiler/src/CFCCMan.h   |  36 +++
 5 files changed, 554 insertions(+), 554 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3c667722/compiler/src/CFCC.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCC.c b/compiler/src/CFCC.c
index e6763ce..067e84e 100644
--- a/compiler/src/CFCC.c
+++ b/compiler/src/CFCC.c
@@ -22,7 +22,7 @@
 #define CFC_NEED_BASE_STRUCT_DEF
 #include "CFCBase.h"
 #include "CFCC.h"
-#include "CFCCClass.h"
+#include "CFCCMan.h"
 #include "CFCClass.h"
 #include "CFCHierarchy.h"
 #include "CFCMethod.h"
@@ -163,7 +163,7 @@ CFCC_write_man_pages(CFCC *self) {
         CFCClass *klass = ordered[i];
         if (CFCClass_included(klass)) { continue; }
 
-        char *man_page = CFCCClass_create_man_page(klass);
+        char *man_page = CFCCMan_create_man_page(klass);
         man_pages[j++] = man_page;
     }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3c667722/compiler/src/CFCCClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCClass.c b/compiler/src/CFCCClass.c
deleted file mode 100644
index b413990..0000000
--- a/compiler/src/CFCCClass.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string.h>
-
-#include "charmony.h"
-#include "CFCCClass.h"
-#include "CFCClass.h"
-#include "CFCDocuComment.h"
-#include "CFCFunction.h"
-#include "CFCMethod.h"
-#include "CFCParamList.h"
-#include "CFCSymbol.h"
-#include "CFCType.h"
-#include "CFCUtil.h"
-#include "CFCVariable.h"
-
-#ifndef true
-    #define true 1
-    #define false 0
-#endif
-
-typedef struct CFCPodLink {
-    size_t      total_size;
-    const char *text;
-    size_t      text_size;
-} CFCPodLink;
-
-static char*
-S_man_create_name(CFCClass *klass);
-
-static char*
-S_man_create_synopsis(CFCClass *klass);
-
-static char*
-S_man_create_description(CFCClass *klass);
-
-static char*
-S_man_create_functions(CFCClass *klass);
-
-static char*
-S_man_create_methods(CFCClass *klass);
-
-static char*
-S_man_create_inherited_methods(CFCClass *klass);
-
-static char*
-S_man_create_func(CFCClass *klass, CFCFunction *func, const char *short_sym,
-                  const char *full_sym);
-
-static char*
-S_man_create_param_list(CFCFunction *func, const char *full_sym);
-
-static char*
-S_man_create_inheritance(CFCClass *klass);
-
-static char*
-S_man_escape_content(const char *content);
-
-static void
-S_parse_pod_link(const char *content, CFCPodLink *pod_link);
-
-char*
-CFCCClass_create_man_page(CFCClass *klass) {
-    if (!CFCSymbol_public((CFCSymbol*)klass)) { return NULL; }
-
-    const char *class_name = CFCClass_get_class_name(klass);
-
-    // Create NAME.
-    char *name = S_man_create_name(klass);
-
-    // Create SYNOPSIS.
-    char *synopsis = S_man_create_synopsis(klass);
-
-    // Create DESCRIPTION.
-    char *description = S_man_create_description(klass);
-
-    // Create CONSTRUCTORS.
-    char *functions_man = S_man_create_functions(klass);
-
-    // Create METHODS, possibly including an ABSTRACT METHODS section.
-    char *methods_man = S_man_create_methods(klass);
-
-    // Build an INHERITANCE section describing class ancestry.
-    char *inheritance = S_man_create_inheritance(klass);
-
-    // Put it all together.
-    const char pattern[] =
-        ".TH %s 3\n"
-        "%s"
-        "%s"
-        "%s"
-        "%s"
-        "%s"
-        "%s";
-    char *man_page
-        = CFCUtil_sprintf(pattern, class_name, name, synopsis, description,
-                          functions_man, methods_man, inheritance);
-
-    FREEMEM(name);
-    FREEMEM(synopsis);
-    FREEMEM(description);
-    FREEMEM(functions_man);
-    FREEMEM(methods_man);
-    FREEMEM(inheritance);
-
-    return man_page;
-}
-
-static char*
-S_man_create_name(CFCClass *klass) {
-    char *result = CFCUtil_strdup(".SH NAME\n");
-    result = CFCUtil_cat(result, CFCClass_get_class_name(klass), NULL);
-
-    CFCDocuComment *docucom = CFCClass_get_docucomment(klass);
-    if (docucom) {
-        const char *raw_brief = CFCDocuComment_get_brief(docucom);
-        if (raw_brief && raw_brief[0] != '\0') {
-            char *brief = S_man_escape_content(raw_brief);
-            result = CFCUtil_cat(result, " \\- ", brief, NULL);
-            FREEMEM(brief);
-        }
-    }
-
-    result = CFCUtil_cat(result, "\n", NULL);
-
-    return result;
-}
-
-static char*
-S_man_create_synopsis(CFCClass *klass) {
-    CHY_UNUSED_VAR(klass);
-    return CFCUtil_strdup("");
-}
-
-static char*
-S_man_create_description(CFCClass *klass) {
-    char *result  = CFCUtil_strdup("");
-
-    CFCDocuComment *docucom = CFCClass_get_docucomment(klass);
-    if (!docucom) { return result; }
-
-    const char *raw_description = CFCDocuComment_get_long(docucom);
-    if (!raw_description || raw_description[0] == '\0') { return result; }
-
-    char *description = S_man_escape_content(raw_description);
-    result = CFCUtil_cat(result, ".SH DESCRIPTION\n", description, "\n", NULL);
-    FREEMEM(description);
-
-    return result;
-}
-
-static char*
-S_man_create_functions(CFCClass *klass) {
-    CFCFunction **functions = CFCClass_functions(klass);
-    char         *result    = CFCUtil_strdup("");
-
-    for (int func_num = 0; functions[func_num] != NULL; func_num++) {
-        CFCFunction *func = functions[func_num];
-        if (!CFCFunction_public(func)) { continue; }
-
-        if (result[0] == '\0') {
-            result = CFCUtil_cat(result, ".SH FUNCTIONS\n", NULL);
-        }
-
-        const char *micro_sym     = CFCFunction_micro_sym(func);
-        const char *full_func_sym = CFCFunction_full_func_sym(func);
-
-        char *redman = S_man_create_func(klass, func, micro_sym,
-                                         full_func_sym);
-        result = CFCUtil_cat(result, redman, NULL);
-        FREEMEM(redman);
-    }
-
-    return result;
-}
-
-static char*
-S_man_create_methods(CFCClass *klass) {
-    CFCMethod **fresh_methods = CFCClass_fresh_methods(klass);
-    char       *methods_man   = CFCUtil_strdup("");
-    char       *novel_man     = CFCUtil_strdup("");
-    char       *result;
-
-    for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
-        CFCMethod *method = fresh_methods[meth_num];
-        if (!CFCMethod_public(method) || !CFCMethod_novel(method)) {
-            continue;
-        }
-
-        const char *macro_sym = CFCMethod_get_macro_sym(method);
-        char *full_method_sym = CFCMethod_full_method_sym(method, NULL);
-        char *method_man = S_man_create_func(klass, (CFCFunction*)method,
-                                             macro_sym, full_method_sym);
-
-        if (CFCMethod_abstract(method)) {
-            if (methods_man[0] == '\0') {
-                methods_man = CFCUtil_cat(methods_man,
-                                          ".SS Abstract methods\n", NULL);
-            }
-            methods_man = CFCUtil_cat(methods_man, method_man, NULL);
-        }
-        else {
-            if (novel_man[0] == '\0') {
-                novel_man = CFCUtil_cat(novel_man,
-                                        ".SS Novel methods\n", NULL);
-            }
-            novel_man = CFCUtil_cat(novel_man, method_man, NULL);
-        }
-
-        FREEMEM(method_man);
-        FREEMEM(full_method_sym);
-    }
-
-    methods_man = CFCUtil_cat(methods_man, novel_man, NULL);
-
-    // Add methods from parent classes excluding Clownfish::Obj
-    CFCClass *parent = CFCClass_get_parent(klass);
-    while (parent) {
-        if (strcmp(CFCClass_get_class_name(parent), "Clownfish::Obj") == 0) {
-            break;
-        }
-        char *inherited_man = S_man_create_inherited_methods(parent);
-        methods_man = CFCUtil_cat(methods_man, inherited_man, NULL);
-        FREEMEM(inherited_man);
-        parent = CFCClass_get_parent(parent);
-    }
-
-    if (methods_man[0] == '\0') {
-        result = CFCUtil_strdup("");
-    }
-    else {
-        result = CFCUtil_sprintf(".SH METHODS\n%s", methods_man);
-    }
-
-    FREEMEM(methods_man);
-    FREEMEM(novel_man);
-    FREEMEM(fresh_methods);
-    return result;
-}
-
-static char*
-S_man_create_inherited_methods(CFCClass *klass) {
-    CFCMethod **fresh_methods = CFCClass_fresh_methods(klass);
-    char       *result        = CFCUtil_strdup("");
-
-    for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
-        CFCMethod *method = fresh_methods[meth_num];
-        if (!CFCMethod_public(method) || !CFCMethod_novel(method)) {
-            continue;
-        }
-
-        if (result[0] == '\0') {
-            result = CFCUtil_cat(result, ".SS Methods inherited from ",
-                                 CFCClass_get_class_name(klass), "\n", NULL);
-        }
-
-        const char *macro_sym = CFCMethod_get_macro_sym(method);
-        char *full_method_sym = CFCMethod_full_method_sym(method, NULL);
-        char *method_man = S_man_create_func(klass, (CFCFunction*)method,
-                                             macro_sym, full_method_sym);
-        result = CFCUtil_cat(result, method_man, NULL);
-
-        FREEMEM(method_man);
-        FREEMEM(full_method_sym);
-    }
-
-    FREEMEM(fresh_methods);
-    return result;
-}
-
-static char*
-S_man_create_func(CFCClass *klass, CFCFunction *func, const char *short_sym,
-                  const char *full_sym) {
-    CFCType    *return_type   = CFCFunction_get_return_type(func);
-    const char *return_type_c = CFCType_to_c(return_type);
-    const char *incremented   = "";
-
-    if (CFCType_incremented(return_type)) {
-        incremented = " // incremented";
-    }
-
-    char *param_list = S_man_create_param_list(func, full_sym);
-
-    const char *pattern =
-        ".TP\n"
-        ".B %s\n"
-        ".na\n"
-        "%s%s\n"
-        ".br\n"
-        "%s"
-        ".ad\n";
-    char *result = CFCUtil_sprintf(pattern, short_sym, return_type_c,
-                                   incremented, param_list);
-
-    FREEMEM(param_list);
-
-    // Get documentation, which may be inherited.
-    CFCDocuComment *docucomment = CFCFunction_get_docucomment(func);
-    if (!docucomment) {
-        const char *micro_sym = CFCFunction_micro_sym(func);
-        CFCClass *parent = klass;
-        while (NULL != (parent = CFCClass_get_parent(parent))) {
-            CFCFunction *parent_func
-                = (CFCFunction*)CFCClass_method(parent, micro_sym);
-            if (!parent_func) { break; }
-            docucomment = CFCFunction_get_docucomment(parent_func);
-            if (docucomment) { break; }
-        }
-    }
-
-    if (docucomment) {
-        // Description
-        const char *raw_desc = CFCDocuComment_get_description(docucomment);
-        char *desc = S_man_escape_content(raw_desc);
-        result = CFCUtil_cat(result, ".IP\n", desc, "\n", NULL);
-        FREEMEM(desc);
-
-        // Params
-        const char **param_names
-            = CFCDocuComment_get_param_names(docucomment);
-        const char **param_docs
-            = CFCDocuComment_get_param_docs(docucomment);
-        if (param_names[0]) {
-            result = CFCUtil_cat(result, ".RS\n", NULL);
-            for (size_t i = 0; param_names[i] != NULL; i++) {
-                char *doc = S_man_escape_content(param_docs[i]);
-                result = CFCUtil_cat(result, ".TP\n.I ", param_names[i],
-                                     "\n", doc, "\n", NULL);
-                FREEMEM(doc);
-            }
-            result = CFCUtil_cat(result, ".RE\n", NULL);
-        }
-
-        // Return value
-        const char *retval_doc = CFCDocuComment_get_retval(docucomment);
-        if (retval_doc && strlen(retval_doc)) {
-            char *doc = S_man_escape_content(retval_doc);
-            result = CFCUtil_cat(result, ".IP\n.B Returns:\n", doc, "\n",
-                                 NULL);
-            FREEMEM(doc);
-        }
-    }
-
-    return result;
-}
-
-static char*
-S_man_create_param_list(CFCFunction *func, const char *full_sym) {
-    CFCParamList  *param_list = CFCFunction_get_param_list(func);
-    CFCVariable  **variables  = CFCParamList_get_variables(param_list);
-
-    if (!variables[0]) {
-        return CFCUtil_sprintf(".BR %s (void);\n", full_sym);
-    }
-
-    char *result = CFCUtil_sprintf(".BR %s (", full_sym);
-
-    for (int i = 0; variables[i]; ++i) {
-        CFCVariable *variable = variables[i];
-        CFCType     *type     = CFCVariable_get_type(variable);
-        const char  *type_c   = CFCType_to_c(type);
-        const char  *name     = CFCVariable_micro_sym(variable);
-
-        result = CFCUtil_cat(result, "\n.br\n.RB \"    ", type_c, " \" ", name,
-                             NULL);
-
-        if (variables[i+1] || CFCType_decremented(type)) {
-            result = CFCUtil_cat(result, " \"", NULL);
-            if (variables[i+1]) {
-                result = CFCUtil_cat(result, ",", NULL);
-            }
-            else {
-                result = CFCUtil_cat(result, " // decremented", NULL);
-            }
-            result = CFCUtil_cat(result, "\"", NULL);
-        }
-    }
-
-    result = CFCUtil_cat(result, "\n.br\n);\n.br\n", NULL);
-
-    return result;
-}
-
-static char*
-S_man_create_inheritance(CFCClass *klass) {
-    CFCClass *ancestor = CFCClass_get_parent(klass);
-    char     *result   = CFCUtil_strdup("");
-
-    if (!ancestor) { return result; }
-
-    const char *class_name = CFCClass_get_class_name(klass);
-    result = CFCUtil_cat(result, ".SH INHERITANCE\n", class_name, NULL);
-    while (ancestor) {
-        const char *ancestor_name = CFCClass_get_class_name(ancestor);
-        result = CFCUtil_cat(result, " is a ", ancestor_name, NULL);
-        ancestor = CFCClass_get_parent(ancestor);
-    }
-    result = CFCUtil_cat(result, ".\n", NULL);
-
-    return result;
-}
-
-static char*
-S_man_escape_content(const char *content) {
-    size_t  result_len = 0;
-    size_t  result_cap = strlen(content) + 256;
-    char   *result     = (char*)MALLOCATE(result_cap + 1);
-
-    for (size_t i = 0; content[i]; i++) {
-        const char *subst      = content + i;
-        size_t      subst_size = 1;
-
-        switch (content[i]) {
-            case '\\':
-                // Escape backslash.
-                subst      = "\\e";
-                subst_size = 2;
-                break;
-            case '-':
-                // Escape hyphen.
-                subst      = "\\-";
-                subst_size = 2;
-                break;
-            case '\n':
-                // Escape dot after newline.
-                if (content[i+1] == '.') {
-                    subst      = "\n\\";
-                    subst_size = 2;
-                }
-                break;
-            case '<':
-                // <code> markup.
-                if (strncmp(content + i + 1, "code>", 5) == 0) {
-                    subst      = "\\fI";
-                    subst_size = 3;
-                    i += 5;
-                }
-                else if (strncmp(content + i + 1, "/code>", 6) == 0) {
-                    subst      = "\\fP";
-                    subst_size = 3;
-                    i += 6;
-                }
-                break;
-            case 'L':
-                if (content[i+1] == '<') {
-                    // POD-style link.
-                    struct CFCPodLink pod_link;
-                    S_parse_pod_link(content + i + 2, &pod_link);
-                    if (pod_link.total_size) {
-                        subst      = pod_link.text;
-                        subst_size = pod_link.text_size;
-                        i += pod_link.total_size + 1;
-                    }
-                }
-                break;
-            default:
-                break;
-        }
-
-        if (result_len + subst_size > result_cap) {
-            result_cap += 256;
-            result = (char*)REALLOCATE(result, result_cap + 1);
-        }
-
-        memcpy(result + result_len, subst, subst_size);
-        result_len += subst_size;
-    }
-
-    result[result_len] = '\0';
-
-    return result;
-}
-
-// Quick and dirty parsing of POD links. The syntax isn't fully supported
-// and the result isn't man-escaped. But it should be good enough for now
-// since at some point we'll switch to another format anyway.
-static void
-S_parse_pod_link(const char *content, CFCPodLink *pod_link) {
-    int in_text = true;
-
-    for (size_t i = 0; i < 256 && content[i]; ++i) {
-        if (content[i] == '|') {
-            if (in_text) {
-                pod_link->text_size = i;
-                in_text = false;
-            }
-        }
-        else if (content[i] == '>') {
-            pod_link->total_size = i + 1;
-            pod_link->text       = content;
-            if (in_text) {
-                pod_link->text_size = i;
-            }
-            return;
-        }
-    }
-
-    pod_link->total_size = 0;
-    pod_link->text       = NULL;
-    pod_link->text_size  = 0;
-}
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3c667722/compiler/src/CFCCClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCClass.h b/compiler/src/CFCCClass.h
deleted file mode 100644
index 710278d..0000000
--- a/compiler/src/CFCCClass.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef H_CFCCCLASS
-#define H_CFCCCLASS
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct CFCClass;
-
-/** Return the man page for the class.
- */
-char*
-CFCCClass_create_man_page(struct CFCClass *klass);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* H_CFCCCLASS */
-

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3c667722/compiler/src/CFCCMan.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCMan.c b/compiler/src/CFCCMan.c
new file mode 100644
index 0000000..17ad340
--- /dev/null
+++ b/compiler/src/CFCCMan.c
@@ -0,0 +1,516 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#include "charmony.h"
+#include "CFCCMan.h"
+#include "CFCClass.h"
+#include "CFCDocuComment.h"
+#include "CFCFunction.h"
+#include "CFCMethod.h"
+#include "CFCParamList.h"
+#include "CFCSymbol.h"
+#include "CFCType.h"
+#include "CFCUtil.h"
+#include "CFCVariable.h"
+
+#ifndef true
+    #define true 1
+    #define false 0
+#endif
+
+typedef struct CFCPodLink {
+    size_t      total_size;
+    const char *text;
+    size_t      text_size;
+} CFCPodLink;
+
+static char*
+S_man_create_name(CFCClass *klass);
+
+static char*
+S_man_create_synopsis(CFCClass *klass);
+
+static char*
+S_man_create_description(CFCClass *klass);
+
+static char*
+S_man_create_functions(CFCClass *klass);
+
+static char*
+S_man_create_methods(CFCClass *klass);
+
+static char*
+S_man_create_inherited_methods(CFCClass *klass);
+
+static char*
+S_man_create_func(CFCClass *klass, CFCFunction *func, const char *short_sym,
+                  const char *full_sym);
+
+static char*
+S_man_create_param_list(CFCFunction *func, const char *full_sym);
+
+static char*
+S_man_create_inheritance(CFCClass *klass);
+
+static char*
+S_man_escape_content(const char *content);
+
+static void
+S_parse_pod_link(const char *content, CFCPodLink *pod_link);
+
+char*
+CFCCMan_create_man_page(CFCClass *klass) {
+    if (!CFCSymbol_public((CFCSymbol*)klass)) { return NULL; }
+
+    const char *class_name = CFCClass_get_class_name(klass);
+
+    // Create NAME.
+    char *name = S_man_create_name(klass);
+
+    // Create SYNOPSIS.
+    char *synopsis = S_man_create_synopsis(klass);
+
+    // Create DESCRIPTION.
+    char *description = S_man_create_description(klass);
+
+    // Create CONSTRUCTORS.
+    char *functions_man = S_man_create_functions(klass);
+
+    // Create METHODS, possibly including an ABSTRACT METHODS section.
+    char *methods_man = S_man_create_methods(klass);
+
+    // Build an INHERITANCE section describing class ancestry.
+    char *inheritance = S_man_create_inheritance(klass);
+
+    // Put it all together.
+    const char pattern[] =
+        ".TH %s 3\n"
+        "%s"
+        "%s"
+        "%s"
+        "%s"
+        "%s"
+        "%s";
+    char *man_page
+        = CFCUtil_sprintf(pattern, class_name, name, synopsis, description,
+                          functions_man, methods_man, inheritance);
+
+    FREEMEM(name);
+    FREEMEM(synopsis);
+    FREEMEM(description);
+    FREEMEM(functions_man);
+    FREEMEM(methods_man);
+    FREEMEM(inheritance);
+
+    return man_page;
+}
+
+static char*
+S_man_create_name(CFCClass *klass) {
+    char *result = CFCUtil_strdup(".SH NAME\n");
+    result = CFCUtil_cat(result, CFCClass_get_class_name(klass), NULL);
+
+    CFCDocuComment *docucom = CFCClass_get_docucomment(klass);
+    if (docucom) {
+        const char *raw_brief = CFCDocuComment_get_brief(docucom);
+        if (raw_brief && raw_brief[0] != '\0') {
+            char *brief = S_man_escape_content(raw_brief);
+            result = CFCUtil_cat(result, " \\- ", brief, NULL);
+            FREEMEM(brief);
+        }
+    }
+
+    result = CFCUtil_cat(result, "\n", NULL);
+
+    return result;
+}
+
+static char*
+S_man_create_synopsis(CFCClass *klass) {
+    CHY_UNUSED_VAR(klass);
+    return CFCUtil_strdup("");
+}
+
+static char*
+S_man_create_description(CFCClass *klass) {
+    char *result  = CFCUtil_strdup("");
+
+    CFCDocuComment *docucom = CFCClass_get_docucomment(klass);
+    if (!docucom) { return result; }
+
+    const char *raw_description = CFCDocuComment_get_long(docucom);
+    if (!raw_description || raw_description[0] == '\0') { return result; }
+
+    char *description = S_man_escape_content(raw_description);
+    result = CFCUtil_cat(result, ".SH DESCRIPTION\n", description, "\n", NULL);
+    FREEMEM(description);
+
+    return result;
+}
+
+static char*
+S_man_create_functions(CFCClass *klass) {
+    CFCFunction **functions = CFCClass_functions(klass);
+    char         *result    = CFCUtil_strdup("");
+
+    for (int func_num = 0; functions[func_num] != NULL; func_num++) {
+        CFCFunction *func = functions[func_num];
+        if (!CFCFunction_public(func)) { continue; }
+
+        if (result[0] == '\0') {
+            result = CFCUtil_cat(result, ".SH FUNCTIONS\n", NULL);
+        }
+
+        const char *micro_sym     = CFCFunction_micro_sym(func);
+        const char *full_func_sym = CFCFunction_full_func_sym(func);
+
+        char *redman = S_man_create_func(klass, func, micro_sym,
+                                         full_func_sym);
+        result = CFCUtil_cat(result, redman, NULL);
+        FREEMEM(redman);
+    }
+
+    return result;
+}
+
+static char*
+S_man_create_methods(CFCClass *klass) {
+    CFCMethod **fresh_methods = CFCClass_fresh_methods(klass);
+    char       *methods_man   = CFCUtil_strdup("");
+    char       *novel_man     = CFCUtil_strdup("");
+    char       *result;
+
+    for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
+        CFCMethod *method = fresh_methods[meth_num];
+        if (!CFCMethod_public(method) || !CFCMethod_novel(method)) {
+            continue;
+        }
+
+        const char *macro_sym = CFCMethod_get_macro_sym(method);
+        char *full_method_sym = CFCMethod_full_method_sym(method, NULL);
+        char *method_man = S_man_create_func(klass, (CFCFunction*)method,
+                                             macro_sym, full_method_sym);
+
+        if (CFCMethod_abstract(method)) {
+            if (methods_man[0] == '\0') {
+                methods_man = CFCUtil_cat(methods_man,
+                                          ".SS Abstract methods\n", NULL);
+            }
+            methods_man = CFCUtil_cat(methods_man, method_man, NULL);
+        }
+        else {
+            if (novel_man[0] == '\0') {
+                novel_man = CFCUtil_cat(novel_man,
+                                        ".SS Novel methods\n", NULL);
+            }
+            novel_man = CFCUtil_cat(novel_man, method_man, NULL);
+        }
+
+        FREEMEM(method_man);
+        FREEMEM(full_method_sym);
+    }
+
+    methods_man = CFCUtil_cat(methods_man, novel_man, NULL);
+
+    // Add methods from parent classes excluding Clownfish::Obj
+    CFCClass *parent = CFCClass_get_parent(klass);
+    while (parent) {
+        if (strcmp(CFCClass_get_class_name(parent), "Clownfish::Obj") == 0) {
+            break;
+        }
+        char *inherited_man = S_man_create_inherited_methods(parent);
+        methods_man = CFCUtil_cat(methods_man, inherited_man, NULL);
+        FREEMEM(inherited_man);
+        parent = CFCClass_get_parent(parent);
+    }
+
+    if (methods_man[0] == '\0') {
+        result = CFCUtil_strdup("");
+    }
+    else {
+        result = CFCUtil_sprintf(".SH METHODS\n%s", methods_man);
+    }
+
+    FREEMEM(methods_man);
+    FREEMEM(novel_man);
+    FREEMEM(fresh_methods);
+    return result;
+}
+
+static char*
+S_man_create_inherited_methods(CFCClass *klass) {
+    CFCMethod **fresh_methods = CFCClass_fresh_methods(klass);
+    char       *result        = CFCUtil_strdup("");
+
+    for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
+        CFCMethod *method = fresh_methods[meth_num];
+        if (!CFCMethod_public(method) || !CFCMethod_novel(method)) {
+            continue;
+        }
+
+        if (result[0] == '\0') {
+            result = CFCUtil_cat(result, ".SS Methods inherited from ",
+                                 CFCClass_get_class_name(klass), "\n", NULL);
+        }
+
+        const char *macro_sym = CFCMethod_get_macro_sym(method);
+        char *full_method_sym = CFCMethod_full_method_sym(method, NULL);
+        char *method_man = S_man_create_func(klass, (CFCFunction*)method,
+                                             macro_sym, full_method_sym);
+        result = CFCUtil_cat(result, method_man, NULL);
+
+        FREEMEM(method_man);
+        FREEMEM(full_method_sym);
+    }
+
+    FREEMEM(fresh_methods);
+    return result;
+}
+
+static char*
+S_man_create_func(CFCClass *klass, CFCFunction *func, const char *short_sym,
+                  const char *full_sym) {
+    CFCType    *return_type   = CFCFunction_get_return_type(func);
+    const char *return_type_c = CFCType_to_c(return_type);
+    const char *incremented   = "";
+
+    if (CFCType_incremented(return_type)) {
+        incremented = " // incremented";
+    }
+
+    char *param_list = S_man_create_param_list(func, full_sym);
+
+    const char *pattern =
+        ".TP\n"
+        ".B %s\n"
+        ".na\n"
+        "%s%s\n"
+        ".br\n"
+        "%s"
+        ".ad\n";
+    char *result = CFCUtil_sprintf(pattern, short_sym, return_type_c,
+                                   incremented, param_list);
+
+    FREEMEM(param_list);
+
+    // Get documentation, which may be inherited.
+    CFCDocuComment *docucomment = CFCFunction_get_docucomment(func);
+    if (!docucomment) {
+        const char *micro_sym = CFCFunction_micro_sym(func);
+        CFCClass *parent = klass;
+        while (NULL != (parent = CFCClass_get_parent(parent))) {
+            CFCFunction *parent_func
+                = (CFCFunction*)CFCClass_method(parent, micro_sym);
+            if (!parent_func) { break; }
+            docucomment = CFCFunction_get_docucomment(parent_func);
+            if (docucomment) { break; }
+        }
+    }
+
+    if (docucomment) {
+        // Description
+        const char *raw_desc = CFCDocuComment_get_description(docucomment);
+        char *desc = S_man_escape_content(raw_desc);
+        result = CFCUtil_cat(result, ".IP\n", desc, "\n", NULL);
+        FREEMEM(desc);
+
+        // Params
+        const char **param_names
+            = CFCDocuComment_get_param_names(docucomment);
+        const char **param_docs
+            = CFCDocuComment_get_param_docs(docucomment);
+        if (param_names[0]) {
+            result = CFCUtil_cat(result, ".RS\n", NULL);
+            for (size_t i = 0; param_names[i] != NULL; i++) {
+                char *doc = S_man_escape_content(param_docs[i]);
+                result = CFCUtil_cat(result, ".TP\n.I ", param_names[i],
+                                     "\n", doc, "\n", NULL);
+                FREEMEM(doc);
+            }
+            result = CFCUtil_cat(result, ".RE\n", NULL);
+        }
+
+        // Return value
+        const char *retval_doc = CFCDocuComment_get_retval(docucomment);
+        if (retval_doc && strlen(retval_doc)) {
+            char *doc = S_man_escape_content(retval_doc);
+            result = CFCUtil_cat(result, ".IP\n.B Returns:\n", doc, "\n",
+                                 NULL);
+            FREEMEM(doc);
+        }
+    }
+
+    return result;
+}
+
+static char*
+S_man_create_param_list(CFCFunction *func, const char *full_sym) {
+    CFCParamList  *param_list = CFCFunction_get_param_list(func);
+    CFCVariable  **variables  = CFCParamList_get_variables(param_list);
+
+    if (!variables[0]) {
+        return CFCUtil_sprintf(".BR %s (void);\n", full_sym);
+    }
+
+    char *result = CFCUtil_sprintf(".BR %s (", full_sym);
+
+    for (int i = 0; variables[i]; ++i) {
+        CFCVariable *variable = variables[i];
+        CFCType     *type     = CFCVariable_get_type(variable);
+        const char  *type_c   = CFCType_to_c(type);
+        const char  *name     = CFCVariable_micro_sym(variable);
+
+        result = CFCUtil_cat(result, "\n.br\n.RB \"    ", type_c, " \" ", name,
+                             NULL);
+
+        if (variables[i+1] || CFCType_decremented(type)) {
+            result = CFCUtil_cat(result, " \"", NULL);
+            if (variables[i+1]) {
+                result = CFCUtil_cat(result, ",", NULL);
+            }
+            else {
+                result = CFCUtil_cat(result, " // decremented", NULL);
+            }
+            result = CFCUtil_cat(result, "\"", NULL);
+        }
+    }
+
+    result = CFCUtil_cat(result, "\n.br\n);\n.br\n", NULL);
+
+    return result;
+}
+
+static char*
+S_man_create_inheritance(CFCClass *klass) {
+    CFCClass *ancestor = CFCClass_get_parent(klass);
+    char     *result   = CFCUtil_strdup("");
+
+    if (!ancestor) { return result; }
+
+    const char *class_name = CFCClass_get_class_name(klass);
+    result = CFCUtil_cat(result, ".SH INHERITANCE\n", class_name, NULL);
+    while (ancestor) {
+        const char *ancestor_name = CFCClass_get_class_name(ancestor);
+        result = CFCUtil_cat(result, " is a ", ancestor_name, NULL);
+        ancestor = CFCClass_get_parent(ancestor);
+    }
+    result = CFCUtil_cat(result, ".\n", NULL);
+
+    return result;
+}
+
+static char*
+S_man_escape_content(const char *content) {
+    size_t  result_len = 0;
+    size_t  result_cap = strlen(content) + 256;
+    char   *result     = (char*)MALLOCATE(result_cap + 1);
+
+    for (size_t i = 0; content[i]; i++) {
+        const char *subst      = content + i;
+        size_t      subst_size = 1;
+
+        switch (content[i]) {
+            case '\\':
+                // Escape backslash.
+                subst      = "\\e";
+                subst_size = 2;
+                break;
+            case '-':
+                // Escape hyphen.
+                subst      = "\\-";
+                subst_size = 2;
+                break;
+            case '\n':
+                // Escape dot after newline.
+                if (content[i+1] == '.') {
+                    subst      = "\n\\";
+                    subst_size = 2;
+                }
+                break;
+            case '<':
+                // <code> markup.
+                if (strncmp(content + i + 1, "code>", 5) == 0) {
+                    subst      = "\\fI";
+                    subst_size = 3;
+                    i += 5;
+                }
+                else if (strncmp(content + i + 1, "/code>", 6) == 0) {
+                    subst      = "\\fP";
+                    subst_size = 3;
+                    i += 6;
+                }
+                break;
+            case 'L':
+                if (content[i+1] == '<') {
+                    // POD-style link.
+                    struct CFCPodLink pod_link;
+                    S_parse_pod_link(content + i + 2, &pod_link);
+                    if (pod_link.total_size) {
+                        subst      = pod_link.text;
+                        subst_size = pod_link.text_size;
+                        i += pod_link.total_size + 1;
+                    }
+                }
+                break;
+            default:
+                break;
+        }
+
+        if (result_len + subst_size > result_cap) {
+            result_cap += 256;
+            result = (char*)REALLOCATE(result, result_cap + 1);
+        }
+
+        memcpy(result + result_len, subst, subst_size);
+        result_len += subst_size;
+    }
+
+    result[result_len] = '\0';
+
+    return result;
+}
+
+// Quick and dirty parsing of POD links. The syntax isn't fully supported
+// and the result isn't man-escaped. But it should be good enough for now
+// since at some point we'll switch to another format anyway.
+static void
+S_parse_pod_link(const char *content, CFCPodLink *pod_link) {
+    int in_text = true;
+
+    for (size_t i = 0; i < 256 && content[i]; ++i) {
+        if (content[i] == '|') {
+            if (in_text) {
+                pod_link->text_size = i;
+                in_text = false;
+            }
+        }
+        else if (content[i] == '>') {
+            pod_link->total_size = i + 1;
+            pod_link->text       = content;
+            if (in_text) {
+                pod_link->text_size = i;
+            }
+            return;
+        }
+    }
+
+    pod_link->total_size = 0;
+    pod_link->text       = NULL;
+    pod_link->text_size  = 0;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3c667722/compiler/src/CFCCMan.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCMan.h b/compiler/src/CFCCMan.h
new file mode 100644
index 0000000..4c7b8e4
--- /dev/null
+++ b/compiler/src/CFCCMan.h
@@ -0,0 +1,36 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef H_CFCCMAN
+#define H_CFCCMAN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct CFCClass;
+
+/** Return the man page for the class.
+ */
+char*
+CFCCMan_create_man_page(struct CFCClass *klass);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CFCCMAN */
+

Reply via email to