Add functions to create C API POD
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/1a19ac4d Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/1a19ac4d Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/1a19ac4d Branch: refs/heads/documentation Commit: 1a19ac4de9824b7b8a81a3fdefd4a0556da31b3c Parents: 19011e0 Author: Nick Wellnhofer <[email protected]> Authored: Sun Aug 31 14:36:30 2014 +0200 Committer: Nick Wellnhofer <[email protected]> Committed: Sun Aug 31 15:32:07 2014 +0200 ---------------------------------------------------------------------- compiler/include/CFC.h | 1 + compiler/perl/lib/Clownfish/CFC.xs | 11 ++ compiler/src/CFCPerlCPod.c | 275 ++++++++++++++++++++++++++++++++ compiler/src/CFCPerlCPod.h | 36 +++++ 4 files changed, 323 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1a19ac4d/compiler/include/CFC.h ---------------------------------------------------------------------- diff --git a/compiler/include/CFC.h b/compiler/include/CFC.h index 9a13607..996e2d3 100644 --- a/compiler/include/CFC.h +++ b/compiler/include/CFC.h @@ -47,6 +47,7 @@ #include "CFCPerlClass.h" #include "CFCPerlConstructor.h" #include "CFCPerlPod.h" +#include "CFCPerlCPod.h" #include "CFCPerlTypeMap.h" #include "CFCRuby.h" http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1a19ac4d/compiler/perl/lib/Clownfish/CFC.xs ---------------------------------------------------------------------- diff --git a/compiler/perl/lib/Clownfish/CFC.xs b/compiler/perl/lib/Clownfish/CFC.xs index a6ea249..38aa3fc 100644 --- a/compiler/perl/lib/Clownfish/CFC.xs +++ b/compiler/perl/lib/Clownfish/CFC.xs @@ -2487,6 +2487,17 @@ CODE: OUTPUT: RETVAL +MODULE = Clownfish PACKAGE = Clownfish::CFC::Binding::Perl::CPod + +SV* +c_api_pod(unused, klass) + SV *unused; + CFCClass *klass; +CODE: + RETVAL = S_sv_eat_c_string(CFCPerlCPod_c_api_pod(klass)); +OUTPUT: RETVAL + + MODULE = Clownfish PACKAGE = Clownfish::CFC::Binding::Perl::TypeMap SV* http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1a19ac4d/compiler/src/CFCPerlCPod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCPerlCPod.c b/compiler/src/CFCPerlCPod.c new file mode 100644 index 0000000..b58fa2f --- /dev/null +++ b/compiler/src/CFCPerlCPod.c @@ -0,0 +1,275 @@ +/* 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 <stddef.h> +#include <string.h> + +#include "CFCPerlCPod.h" + +#include "CFCClass.h" +#include "CFCDocuComment.h" +#include "CFCFunction.h" +#include "CFCMethod.h" +#include "CFCParamList.h" +#include "CFCType.h" +#include "CFCUtil.h" +#include "CFCVariable.h" + +static char* +S_name_pod(CFCClass *klass); + +static char* +S_description_pod(CFCClass *klass); + +static char* +S_functions_pod(CFCClass *klass); + +static char* +S_methods_pod(CFCClass *klass); + +static char* +S_function_pod(CFCClass *klass, CFCFunction *func, const char *short_sym, + const char *full_sym); + +static char* +S_param_list_pod(CFCFunction *func); + +char* +CFCPerlCPod_c_api_pod(CFCClass *klass) { + const char *full_struct_sym = CFCClass_full_struct_sym(klass); + char *name_pod = S_name_pod(klass); + char *description_pod = S_description_pod(klass); + char *functions_pod = S_functions_pod(klass); + char *methods_pod = S_methods_pod(klass); + + const char pattern[] = + "%s" + "%s" + "%s" + "%s"; + char *result + = CFCUtil_sprintf(pattern, name_pod, description_pod, functions_pod, + methods_pod); + + FREEMEM(methods_pod); + return result; +} + +static char* +S_name_pod(CFCClass *klass) { + char *result = CFCUtil_sprintf("=head1 NAME\n\n%s", + CFCClass_get_class_name(klass)); + + CFCDocuComment *docucom = CFCClass_get_docucomment(klass); + if (docucom) { + const char *brief = CFCDocuComment_get_brief(docucom); + if (brief && brief[0] != '\0') { + result = CFCUtil_cat(result, " - ", brief, NULL); + } + } + + result = CFCUtil_cat(result, "\n\n", NULL); + + return result; +} + +static char* +S_description_pod(CFCClass *klass) { + char *result = CFCUtil_strdup(""); + + CFCDocuComment *docucom = CFCClass_get_docucomment(klass); + if (!docucom) { return result; } + + const char *description = CFCDocuComment_get_long(docucom); + if (description && description[0] != '\0') { + result = CFCUtil_cat(result, "=head1 DESCRIPTION\n\n", description, + "\n\n", NULL); + } + + return result; +} + +static char* +S_functions_pod(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 (result[0] == '\0') { + result = CFCUtil_cat(result, "=head1 FUNCTIONS\n\n", NULL); + } + + const char *micro_sym = CFCFunction_micro_sym(func); + const char *full_func_sym = CFCFunction_full_func_sym(func); + + char *function_pod = S_function_pod(klass, func, micro_sym, + full_func_sym); + result = CFCUtil_cat(result, function_pod, NULL); + FREEMEM(function_pod); + } + + return result; +} + +static char* +S_methods_pod(CFCClass *klass) { + CFCMethod **fresh_methods = CFCClass_fresh_methods(klass); + char *abstract_pod = CFCUtil_strdup(""); + char *novel_pod = CFCUtil_strdup(""); + + for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) { + CFCMethod *method = fresh_methods[meth_num]; + if (!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_pod = S_function_pod(klass, (CFCFunction*)method, + macro_sym, full_method_sym); + + if (CFCMethod_abstract(method)) { + if (abstract_pod[0] == '\0') { + abstract_pod + = CFCUtil_cat(abstract_pod, "=head1 ABSTRACT METHODS\n\n", + NULL); + } + abstract_pod = CFCUtil_cat(abstract_pod, method_pod, NULL); + } + else { + if (novel_pod[0] == '\0') { + novel_pod + = CFCUtil_cat(novel_pod, "=head1 NOVEL METHODS\n\n", NULL); + } + novel_pod = CFCUtil_cat(novel_pod, method_pod, NULL); + } + + FREEMEM(method_pod); + FREEMEM(full_method_sym); + } + + char *result = CFCUtil_sprintf("%s%s", abstract_pod, novel_pod); + + FREEMEM(abstract_pod); + FREEMEM(novel_pod); + FREEMEM(fresh_methods); + return result; +} + +static char* +S_function_pod(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_param_list_pod(func); + + const char *pattern = + "=head2 %s\n" + "\n" + " %s%s\n" + " %s%s;\n\n"; + char *result = CFCUtil_sprintf(pattern, short_sym, return_type_c, + incremented, full_sym, 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 *desc = CFCDocuComment_get_description(docucomment); + if (desc && desc[0] != '\0') { + result = CFCUtil_cat(result, desc, "\n\n", NULL); + } + + // 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, "=over\n\n", NULL); + for (size_t i = 0; param_names[i] != NULL; i++) { + result = CFCUtil_cat(result, "=item *\n\nB<", param_names[i], + "> - ", param_docs[i], "\n\n", NULL); + } + result = CFCUtil_cat(result, "=back\n\n", NULL); + } + + // Return value + const char *retval_doc = CFCDocuComment_get_retval(docucomment); + if (retval_doc && strlen(retval_doc)) { + result = CFCUtil_cat(result, "Returns: ", retval_doc, "\n\n", + NULL); + } + } + + return result; +} + +static char* +S_param_list_pod(CFCFunction *func) { + CFCParamList *param_list = CFCFunction_get_param_list(func); + CFCVariable **variables = CFCParamList_get_variables(param_list); + + if (!variables[0]) { + return CFCUtil_strdup("(void);\n"); + } + + char *result = CFCUtil_strdup("("); + + 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 ", type_c, " ", name, + NULL); + + if (variables[i+1]) { + result = CFCUtil_cat(result, ",", NULL); + } + if (CFCType_decremented(type)) { + result = CFCUtil_cat(result, " // decremented", NULL); + } + } + + result = CFCUtil_cat(result, "\n )", NULL); + + return result; +} + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1a19ac4d/compiler/src/CFCPerlCPod.h ---------------------------------------------------------------------- diff --git a/compiler/src/CFCPerlCPod.h b/compiler/src/CFCPerlCPod.h new file mode 100644 index 0000000..b687167 --- /dev/null +++ b/compiler/src/CFCPerlCPod.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_CFCPERLCPOD +#define H_CFCPERLCPOD + +#ifdef __cplusplus +extern "C" { +#endif + +struct CFCClass; + +/** Create POD for the C API of a class. + */ +char* +CFCPerlCPod_c_api_pod(struct CFCClass *klass); + +#ifdef __cplusplus +} +#endif + +#endif /* H_CFCPERL */ +
