static void _gen_func(const Eolian_Unit *src, const Eolian_Function *fid, Eolian_Function_Type ftype, Eina_Strbuf *buf, char *cname, char *cnameu, Eina_Bool legacy) { Eina_Stringshare *fcn = eolian_function_full_c_name_get(fid, ftype, legacy); if (!fcn) return; Eina_Bool var_as_ret = EINA_FALSE; const Eolian_Type *rtp = eolian_function_return_type_get(fid, ftype); if (ftype == EOLIAN_PROP_GET && !rtp) { void *d1, *d2; Eina_Iterator *itr = eolian_property_values_get(fid, ftype); if (eina_iterator_next(itr, &d1) && !eina_iterator_next(itr, &d2)) { rtp = eolian_parameter_type_get((Eolian_Function_Parameter *)d1); var_as_ret = EINA_TRUE; } eina_iterator_free(itr); } Eolian_Object_Scope fsc = eolian_function_scope_get(fid, ftype); /* this one will never be satisfied in legacy */ if (eolian_function_is_beta(fid)) eina_strbuf_append_printf(buf, "#ifdef %s_BETA\n", cnameu); /* XXX: is this right? we expose potentially internal stuff into legacy */ if (!legacy && (fsc == EOLIAN_SCOPE_PROTECTED)) eina_strbuf_append_printf(buf, "#ifdef %s_PROTECTED\n", cnameu); const Eolian_Implement *fimp = eolian_function_implement_get(fid); Eina_Bool hasdoc = !!eolian_implement_documentation_get(fimp, ftype); if (!hasdoc && ((ftype == EOLIAN_PROP_GET) || (ftype == EOLIAN_PROP_SET))) hasdoc = !!eolian_implement_documentation_get(fimp, EOLIAN_PROPERTY); if (hasdoc) { Eina_Strbuf *dbuf = eo_gen_docs_func_gen(src, fid, ftype, 0, legacy); eina_strbuf_append(buf, eina_strbuf_string_get(dbuf)); eina_strbuf_append_char(buf, '\n'); eina_strbuf_free(dbuf); } eina_strbuf_append(buf, legacy ? "EAPI " : "EOAPI "); if (rtp) { Eina_Stringshare *rtps = eolian_type_c_type_get(rtp); eina_strbuf_append(buf, rtps); if (rtps[strlen(rtps) - 1] != '*') eina_strbuf_append_char(buf, ' '); eina_stringshare_del(rtps); } else eina_strbuf_append(buf, "void "); eina_strbuf_append(buf, fcn); eina_stringshare_del(fcn); Eina_Bool first = EINA_TRUE; Eina_Strbuf *flagbuf = NULL; int nidx = !legacy || !eolian_function_is_class(fid); eina_strbuf_append_char(buf, '('); if (nidx) { if ((ftype == EOLIAN_PROP_GET) || eolian_function_object_is_const(fid) || eolian_function_is_class(fid)) { eina_strbuf_append(buf, "const "); } if (legacy) eina_strbuf_append_printf(buf, "%s *obj", cname); else eina_strbuf_append(buf, "Eo *obj"); first = EINA_FALSE; } { Eolian_Function_Parameter *pr = NULL; Eina_Iterator *itr = eolian_property_keys_get(fid, ftype); EINA_ITERATOR_FOREACH(itr, pr) { const Eolian_Type *prt = eolian_parameter_type_get(pr); const char *prn = eolian_parameter_name_get(pr); Eina_Stringshare *prtn = eolian_type_c_type_get(prt); ++nidx; if (!first) eina_strbuf_append(buf, ", "); eina_strbuf_append_printf(buf, "%s %s", prtn, prn); eina_stringshare_del(prtn); first = EINA_FALSE; if (!eolian_parameter_is_nonull(pr)) continue; if (!flagbuf) { flagbuf = eina_strbuf_new(); eina_strbuf_append_printf(flagbuf, " EINA_ARG_NONNULL(%d", nidx); } else eina_strbuf_append_printf(flagbuf, ", %d", nidx); } eina_iterator_free(itr); } if (!var_as_ret) { Eina_Iterator *itr = NULL; if (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET) itr = eolian_property_values_get(fid, ftype); else itr = eolian_function_parameters_get(fid); Eolian_Function_Parameter *pr = NULL; EINA_ITERATOR_FOREACH(itr, pr) { const Eolian_Type *prt = eolian_parameter_type_get(pr); const char *prn = eolian_parameter_name_get(pr); Eina_Stringshare *prtn = eolian_type_c_type_get(prt); ++nidx; if (!first) eina_strbuf_append(buf, ", "); eina_strbuf_append(buf, prtn); if (prtn[strlen(prtn) - 1] != '*') eina_strbuf_append_char(buf, ' '); eina_strbuf_append(buf, _get_add_star(ftype, eolian_parameter_direction_get(pr))); eina_strbuf_append(buf, prn); eina_stringshare_del(prtn); first = EINA_FALSE; if (!eolian_parameter_is_nonull(pr)) continue; if (!flagbuf) { flagbuf = eina_strbuf_new(); eina_strbuf_append_printf(flagbuf, " EINA_ARG_NONNULL(%d", nidx); } else eina_strbuf_append_printf(flagbuf, ", %d", nidx); } eina_iterator_free(itr); }
static void _gen_func(const Eolian_Unit *src, const Eolian_Class *cl, const Eolian_Function *fid, Eolian_Function_Type ftype, Eina_Strbuf *buf, const Eolian_Implement *impl, Eina_Strbuf *lbuf) { Eina_Bool is_empty = eolian_implement_is_empty(impl, ftype); Eina_Bool is_auto = eolian_implement_is_auto(impl, ftype); if ((ftype != EOLIAN_PROP_GET) && (ftype != EOLIAN_PROP_SET)) ftype = eolian_function_type_get(fid); Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET); Eina_Bool var_as_ret = EINA_FALSE; const Eolian_Expression *def_ret = NULL; const Eolian_Type *rtp = eolian_function_return_type_get(fid, ftype); if (rtp) { is_auto = EINA_FALSE; /* can't do auto if func returns */ def_ret = eolian_function_return_default_value_get(fid, ftype); } const char *func_suffix = ""; if (ftype == EOLIAN_PROP_GET) { func_suffix = "_get"; if (!rtp) { void *d1, *d2; Eina_Iterator *itr = eolian_property_values_get(fid, ftype); if (eina_iterator_next(itr, &d1) && !eina_iterator_next(itr, &d2)) { Eolian_Function_Parameter *pr = d1; rtp = eolian_parameter_type_get(pr); var_as_ret = EINA_TRUE; def_ret = eolian_parameter_default_value_get(pr); } eina_iterator_free(itr); } } else if (ftype == EOLIAN_PROP_SET) func_suffix = "_set"; Eina_Strbuf *params = eina_strbuf_new(); /* par1, par2, par3, ... */ Eina_Strbuf *params_full = eina_strbuf_new(); /* T par1, U par2, ... for decl */ Eina_Strbuf *params_full_imp = eina_strbuf_new(); /* as above, for impl */ Eina_Strbuf *params_init = eina_strbuf_new(); /* default value inits */ Eina_Stringshare *promise_param_name = NULL; Eina_Stringshare *promise_param_type = NULL; /* property keys */ { Eina_Iterator *itr = eolian_property_keys_get(fid, ftype); Eolian_Function_Parameter *pr; EINA_ITERATOR_FOREACH(itr, pr) { const char *prn = eolian_parameter_name_get(pr); const Eolian_Type *pt = eolian_parameter_type_get(pr); Eina_Stringshare *ptn = eolian_type_c_type_get(pt); if (eina_strbuf_length_get(params)) eina_strbuf_append(params, ", "); eina_strbuf_append(params, prn); eina_strbuf_append_printf(params_full, ", %s", ptn); eina_strbuf_append_printf(params_full_imp, ", %s", ptn); if (ptn[strlen(ptn) - 1] != '*') { eina_strbuf_append_char(params_full, ' '); eina_strbuf_append_char(params_full_imp, ' '); } eina_strbuf_append(params_full, prn); eina_strbuf_append(params_full_imp, prn); if (is_empty || is_auto) eina_strbuf_append(params_full_imp, " EINA_UNUSED"); eina_stringshare_del(ptn); } eina_iterator_free(itr); } /* property values or method params if applicable */ if (!var_as_ret) { Eina_Iterator *itr; if (is_prop) itr = eolian_property_values_get(fid, ftype); else itr = eolian_function_parameters_get(fid); Eolian_Function_Parameter *pr; EINA_ITERATOR_FOREACH(itr, pr) { Eolian_Parameter_Dir pd = eolian_parameter_direction_get(pr); const Eolian_Expression *dfv = eolian_parameter_default_value_get(pr); const char *prn = eolian_parameter_name_get(pr); const Eolian_Type *pt = eolian_parameter_type_get(pr); Eina_Stringshare *ptn = eolian_type_c_type_get(pt); Eina_Bool had_star = ptn[strlen(ptn) - 1] == '*'; const char *add_star = _get_add_star(ftype, pd); if (eina_strbuf_length_get(params)) eina_strbuf_append(params, ", "); eina_strbuf_append(params_full_imp, ", "); eina_strbuf_append(params_full_imp, ptn); if (!had_star) eina_strbuf_append_char(params_full_imp, ' '); eina_strbuf_append(params_full_imp, add_star); eina_strbuf_append(params_full_imp, prn); if (!dfv && is_empty) eina_strbuf_append(params_full_imp, " EINA_UNUSED"); eina_strbuf_append(params, prn); eina_strbuf_append(params_full, ", "); eina_strbuf_append(params_full, ptn); if (!had_star) eina_strbuf_append_char(params_full, ' '); eina_strbuf_append(params_full, add_star); eina_strbuf_append(params_full, prn); if (is_auto) { if (ftype == EOLIAN_PROP_SET) eina_strbuf_append_printf(params_init, " %s = pd->%s;\n", prn, prn); else { eina_strbuf_append_printf(params_init, " if (%s) *%s = pd->%s;\n", prn, prn, prn); } } else if ((ftype != EOLIAN_PROP_SET) && dfv) { Eolian_Value val = eolian_expression_eval(src, dfv, EOLIAN_MASK_ALL); if (val.type) { Eina_Stringshare *vals = eolian_expression_value_to_literal(&val); eina_strbuf_append_printf(params_init, " if (%s) *%s = %s;", prn, prn, vals); eina_stringshare_del(vals); if (eolian_expression_type_get(dfv) == EOLIAN_EXPR_NAME) { Eina_Stringshare *vs = eolian_expression_serialize(dfv); eina_strbuf_append_printf(params_init, " /* %s */", vs); eina_stringshare_del(vs); } eina_strbuf_append_char(params_init, '\n'); } } eina_stringshare_del(ptn); }
Eina_Strbuf * docs_generate_function(const Eolian_Function *fid, Eolian_Function_Type ftype, int indent, Eina_Bool use_legacy) { const Eolian_Function_Parameter *par = NULL; const Eolian_Function_Parameter *vpar = NULL; const Eolian_Documentation *doc, *pdoc, *rdoc; Eina_Iterator *itr = NULL; Eina_Iterator *vitr = NULL; Eina_Bool force_out = EINA_FALSE; Eina_Strbuf *buf = eina_strbuf_new(); Eina_Strbuf *wbuf = NULL; const char *sum = NULL, *desc = NULL, *since = NULL; int curl = 0; const char *group = eolian_class_full_name_get(eolian_function_class_get(fid)); if (ftype == EOLIAN_UNRESOLVED) ftype = EOLIAN_METHOD; if (ftype == EOLIAN_METHOD) { doc = eolian_function_documentation_get(fid, EOLIAN_METHOD); pdoc = NULL; } else { doc = eolian_function_documentation_get(fid, EOLIAN_PROPERTY); pdoc = eolian_function_documentation_get(fid, ftype); if (!doc && pdoc) doc = pdoc; if (pdoc == doc) pdoc = NULL; } rdoc = eolian_function_return_documentation_get(fid, ftype); if (doc) { sum = eolian_documentation_summary_get(doc); desc = eolian_documentation_description_get(doc); since = eolian_documentation_since_get(doc); if (pdoc && eolian_documentation_since_get(pdoc)) since = eolian_documentation_since_get(pdoc); } if (ftype == EOLIAN_METHOD) { itr = eolian_function_parameters_get(fid); if (!itr || !eina_iterator_next(itr, (void**)&par)) { eina_iterator_free(itr); itr = NULL; } } else { itr = eolian_property_keys_get(fid, ftype); vitr = eolian_property_values_get(fid, ftype); if (!vitr || !eina_iterator_next(vitr, (void**)&vpar)) { eina_iterator_free(vitr); vitr = NULL; } } if (!itr || !eina_iterator_next(itr, (void**)&par)) { eina_iterator_free(itr); itr = NULL; } /* when return is not set on getter, value becomes return instead of param */ if (ftype == EOLIAN_PROP_GET && !eolian_function_return_type_get(fid, ftype)) { if (!eina_iterator_next(vitr, (void**)&vpar)) { /* one value - not out param */ eina_iterator_free(vitr); rdoc = eolian_parameter_documentation_get(vpar); vitr = NULL; vpar = NULL; } else { /* multiple values - always out params */ eina_iterator_free(vitr); vitr = eolian_property_values_get(fid, ftype); if (!vitr) vpar = NULL; else if (!eina_iterator_next(vitr, (void**)&vpar)) { eina_iterator_free(vitr); vitr = NULL; vpar = NULL; } } } if (!par) { /* no keys, try values */ itr = vitr; par = vpar; vitr = NULL; vpar = NULL; if (ftype == EOLIAN_PROP_GET) force_out = EINA_TRUE; } /* only summary, nothing else; generate standard brief doc */ if (!desc && !par && !vpar && !rdoc && (ftype == EOLIAN_METHOD || !pdoc)) { _gen_doc_brief(sum ? sum : "No description supplied.", since, group, indent, buf, use_legacy); return buf; } wbuf = eina_strbuf_new(); eina_strbuf_append(buf, "/**\n"); curl += _indent_line(buf, indent); eina_strbuf_append(buf, " * @brief "); curl += sizeof(" * @brief ") - 1; _append_section(sum ? sum : "No description supplied.", indent, curl, buf, wbuf, use_legacy); eina_strbuf_append_char(buf, '\n'); if (desc || since || par || rdoc || pdoc) { _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); } if (desc) { curl = _indent_line(buf, indent); eina_strbuf_append(buf, " * "); _append_section(desc, indent, curl + 3, buf, wbuf, use_legacy); eina_strbuf_append_char(buf, '\n'); if (par || rdoc || pdoc || since) { _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); } } if (pdoc) { const char *pdesc = eolian_documentation_description_get(pdoc); curl = _indent_line(buf, indent); eina_strbuf_append(buf, " * "); _append_section(eolian_documentation_summary_get(pdoc), indent, curl + 3, buf, wbuf, use_legacy); eina_strbuf_append_char(buf, '\n'); if (pdesc) { _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); curl = _indent_line(buf, indent); eina_strbuf_append(buf, " * "); _append_section(pdesc, indent, curl + 3, buf, wbuf, use_legacy); eina_strbuf_append_char(buf, '\n'); } if (par || rdoc || since) { _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); } } while (par) { const Eolian_Documentation *adoc = eolian_parameter_documentation_get(par); curl = _indent_line(buf, indent); Eolian_Parameter_Dir dir = EOLIAN_OUT_PARAM; if (!force_out) dir = eolian_parameter_direction_get(par); switch (dir) { case EOLIAN_IN_PARAM: eina_strbuf_append(buf, " * @param[in] "); curl += sizeof(" * @param[in] ") - 1; break; case EOLIAN_OUT_PARAM: eina_strbuf_append(buf, " * @param[out] "); curl += sizeof(" * @param[out] ") - 1; break; case EOLIAN_INOUT_PARAM: eina_strbuf_append(buf, " * @param[in,out] "); curl += sizeof(" * @param[in,out] ") - 1; break; } const char *nm = eolian_parameter_name_get(par); eina_strbuf_append(buf, nm); curl += strlen(nm); if (adoc) { eina_strbuf_append_char(buf, ' '); curl += 1; _append_section(eolian_documentation_summary_get(adoc), indent, curl, buf, wbuf, use_legacy); } eina_strbuf_append_char(buf, '\n'); if (!eina_iterator_next(itr, (void**)&par)) { par = NULL; if (vpar) { eina_iterator_free(itr); itr = vitr; par = vpar; vitr = NULL; vpar = NULL; if (ftype == EOLIAN_PROP_GET) force_out = EINA_TRUE; } } if (!par && (rdoc || since)) { _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); } } eina_iterator_free(itr); if (rdoc) { curl = _indent_line(buf, indent); eina_strbuf_append(buf, " * @return "); curl += sizeof(" * @return ") - 1; _append_section(eolian_documentation_summary_get(rdoc), indent, curl, buf, wbuf, use_legacy); eina_strbuf_append_char(buf, '\n'); if (since) { _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); } } if (since) { curl = _indent_line(buf, indent); eina_strbuf_append(buf, " * @since "); eina_strbuf_append(buf, since); eina_strbuf_append_char(buf, '\n'); } _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); _indent_line(buf, indent); _append_group(buf, _sanitize_group(group), indent); eina_strbuf_append(buf, " */"); eina_strbuf_free(wbuf); return buf; }