diff --git a/src/bin/eolian/docs.c b/src/bin/eolian/docs.c index c01508dab6..2f27a107b2 100644 --- a/src/bin/eolian/docs.c +++ b/src/bin/eolian/docs.c @@ -1,719 +1,719 @@ #include #include "docs.h" static int _indent_line(Eina_Strbuf *buf, int ind) { int i; for (i = 0; i < ind; ++i) eina_strbuf_append_char(buf, ' '); return ind; } #define DOC_LINE_LIMIT 79 #define DOC_LINE_TEST 59 #define DOC_LINE_OVER 39 #define DOC_LIMIT(ind) ((ind > DOC_LINE_TEST) ? (ind + DOC_LINE_OVER) \ : DOC_LINE_LIMIT) #define SUMMARY_OR_DEFAULT(sum) (sum ? sum : "No description supplied.") static void _generate_ref(const Eolian_State *state, const char *refn, Eina_Strbuf *wbuf) { const Eolian_Object *decl = eolian_state_object_by_name_get(state, refn); if (decl) { char *n = strdup(eolian_object_name_get(decl)); char *p = n; while ((p = strchr(p, '.'))) *p = '_'; if (eolian_object_type_get(decl) == EOLIAN_OBJECT_CONSTANT) eina_str_toupper(&n); eina_strbuf_append(wbuf, n); free(n); return; } /* not a plain declaration, so it must be struct/enum field or func */ const char *sfx = strrchr(refn, '.'); if (!sfx) goto noref; Eina_Stringshare *bname = eina_stringshare_add_length(refn, sfx - refn); const Eolian_Typedecl *tp = eolian_state_struct_by_name_get(state, bname); if (tp) { if (!eolian_typedecl_struct_field_get(tp, sfx + 1)) { eina_stringshare_del(bname); goto noref; } _generate_ref(state, bname, wbuf); eina_strbuf_append(wbuf, sfx); eina_stringshare_del(bname); return; } tp = eolian_state_enum_by_name_get(state, bname); if (tp) { const Eolian_Enum_Type_Field *efl = eolian_typedecl_enum_field_get(tp, sfx + 1); if (!efl) { eina_stringshare_del(bname); goto noref; } Eina_Stringshare *str = eolian_typedecl_enum_field_c_constant_get(efl); eina_strbuf_append(wbuf, str); eina_stringshare_del(bname); return; } const Eolian_Class *cl = eolian_state_class_by_name_get(state, bname); const Eolian_Function *fn = NULL; /* match methods and properties; we're only figuring out existence */ Eolian_Function_Type ftype = EOLIAN_UNRESOLVED; if (!cl) { const char *mname = NULL; if (!strcmp(sfx, ".get")) ftype = EOLIAN_PROP_GET; else if (!strcmp(sfx, ".set")) ftype = EOLIAN_PROP_SET; if (ftype != EOLIAN_UNRESOLVED) { eina_stringshare_del(bname); mname = sfx - 1; while ((mname != refn) && (*mname != '.')) --mname; if (mname == refn) goto noref; bname = eina_stringshare_add_length(refn, mname - refn); cl = eolian_state_class_by_name_get(state, bname); eina_stringshare_del(bname); } if (cl) { char *meth = eina_strndup(mname + 1, sfx - mname - 1); fn = eolian_class_function_by_name_get(cl, meth, ftype); if (ftype == EOLIAN_UNRESOLVED) ftype = eolian_function_type_get(fn); free(meth); } } else { fn = eolian_class_function_by_name_get(cl, sfx + 1, ftype); ftype = eolian_function_type_get(fn); } if (!fn) goto noref; Eina_Stringshare *fcn = eolian_function_full_c_name_get(fn, ftype); if (!fcn) goto noref; eina_strbuf_append(wbuf, fcn); eina_stringshare_del(fcn); return; noref: eina_strbuf_append(wbuf, refn); } static int _append_section(const Eolian_State *state, const char *desc, int ind, int curl, Eina_Strbuf *buf, Eina_Strbuf *wbuf) { Eina_Bool try_note = EINA_TRUE; while (*desc) { while (*desc && isspace(*desc) && (*desc != '\n')) eina_strbuf_append_char(wbuf, *desc++); if (try_note) { #define CHECK_NOTE(str) !strncmp(desc, str ": ", sizeof(str ":")) if (CHECK_NOTE("Note")) { eina_strbuf_append(wbuf, "@note "); desc += sizeof("Note:"); } else if (CHECK_NOTE("Warning")) { eina_strbuf_append(wbuf, "@warning "); desc += sizeof("Warning:"); } else if (CHECK_NOTE("Remark")) { eina_strbuf_append(wbuf, "@remark "); desc += sizeof("Remark:"); } else if (CHECK_NOTE("TODO")) { eina_strbuf_append(wbuf, "@todo "); desc += sizeof("TODO:"); } #undef CHECK_NOTE try_note = EINA_FALSE; } int limit = DOC_LIMIT(ind); int wlen; if (*desc == '\\') { desc++; if ((*desc != '@') && (*desc != '$')) eina_strbuf_append_char(wbuf, '\\'); eina_strbuf_append_char(wbuf, *desc++); } else if (*desc == '@') { const char *ref = ++desc; if (isalpha(*desc) || (*desc == '_')) { eina_strbuf_append(wbuf, "@ref "); while (isalnum(*desc) || (*desc == '.') || (*desc == '_')) ++desc; if (*(desc - 1) == '.') --desc; Eina_Stringshare *refn = eina_stringshare_add_length(ref, desc - ref); _generate_ref(state, refn, wbuf); eina_stringshare_del(refn); } else eina_strbuf_append_char(wbuf, '@'); } else if (*desc == '$') { if (*++desc == '[') { ++desc; eina_strbuf_append(wbuf, ""); wlen = eina_strbuf_length_get(wbuf); while ((*desc != '\0') && (*desc != ']') && (*desc != '\n')) { if (*desc == ' ') { eina_strbuf_append_char(wbuf, ' '); wlen = eina_strbuf_length_get(wbuf); if ((int)(curl + wlen) > limit) { curl = 3; eina_strbuf_append_char(buf, '\n'); curl += _indent_line(buf, ind); eina_strbuf_append(buf, " * "); if (*eina_strbuf_string_get(wbuf) == ' ') eina_strbuf_remove(wbuf, 0, 1); } curl += eina_strbuf_length_get(wbuf); eina_strbuf_append(buf, eina_strbuf_string_get(wbuf)); eina_strbuf_reset(wbuf); ++desc; continue; } /* skip escape */ if (*desc == '\\') { ++desc; if ((*desc == '\0') || (*desc == '\n')) break; } eina_strbuf_append_char(wbuf, *desc++); } if (*desc == ']') ++desc; eina_strbuf_append(wbuf, ""); curl += 5; goto split; } if (isalpha(*desc)) eina_strbuf_append(wbuf, "@c "); else eina_strbuf_append_char(wbuf, '$'); } while (*desc && !isspace(*desc)) eina_strbuf_append_char(wbuf, *desc++); split: wlen = eina_strbuf_length_get(wbuf); if ((int)(curl + wlen) > limit) { curl = 3; eina_strbuf_append_char(buf, '\n'); curl += _indent_line(buf, ind); eina_strbuf_append(buf, " * "); if (*eina_strbuf_string_get(wbuf) == ' ') eina_strbuf_remove(wbuf, 0, 1); } curl += eina_strbuf_length_get(wbuf); eina_strbuf_append(buf, eina_strbuf_string_get(wbuf)); eina_strbuf_reset(wbuf); if (*desc == '\n') { desc++; eina_strbuf_append_char(buf, '\n'); while (*desc == '\n') { _indent_line(buf, ind); eina_strbuf_append(buf, " *\n"); desc++; try_note = EINA_TRUE; } curl = _indent_line(buf, ind) + 3; eina_strbuf_append(buf, " * "); } } return curl; } static int _append_since(const char *since, int indent, int curl, Eina_Strbuf *buf) { if (since) { eina_strbuf_append_char(buf, '\n'); _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); curl = _indent_line(buf, indent); eina_strbuf_append(buf, " * @since "); eina_strbuf_append(buf, since); curl += strlen(since) + sizeof(" * @since ") - 1; } return curl; } static int _append_extra(const char *el, int indent, int curl, Eina_Bool nl, Eina_Strbuf *buf) { if (el) { eina_strbuf_append_char(buf, '\n'); if (nl) { _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); } curl = _indent_line(buf, indent); eina_strbuf_append(buf, " * "); eina_strbuf_append(buf, el); curl += strlen(el) + sizeof(" * ") - 1; } return curl; } static char * _sanitize_group(const char *group) { if (!group) return NULL; char *ret = strdup(group); char *p; while ((p = strchr(ret, '.'))) *p = '_'; return ret; } static void _append_group(Eina_Strbuf *buf, char *sgrp, int indent) { if (!sgrp) return; eina_strbuf_append(buf, " * @ingroup "); eina_strbuf_append(buf, sgrp); eina_strbuf_append_char(buf, '\n'); _indent_line(buf, indent); free(sgrp); } static void _gen_doc_brief(const Eolian_State *state, const char *summary, const char *since, const char *group, const char *el, int indent, Eina_Strbuf *buf) { int curl = 4 + indent; Eina_Strbuf *wbuf = eina_strbuf_new(); if (indent) eina_strbuf_append(buf, "/**< "); else eina_strbuf_append(buf, "/** "); curl = _append_section(state, summary, indent, curl, buf, wbuf); eina_strbuf_free(wbuf); curl = _append_extra(el, indent, curl, EINA_FALSE, buf); curl = _append_since(since, indent, curl, buf); char *sgrp = _sanitize_group(group); if (((curl + 3) > DOC_LIMIT(indent)) || sgrp) { eina_strbuf_append_char(buf, '\n'); _indent_line(buf, indent); if (sgrp) eina_strbuf_append(buf, " *"); } if (sgrp) { eina_strbuf_append_char(buf, '\n'); _indent_line(buf, indent); } _append_group(buf, sgrp, indent); eina_strbuf_append(buf, " */"); } static void _gen_doc_full(const Eolian_State *state, const char *summary, const char *description, const char *since, const char *group, const char *el, int indent, Eina_Strbuf *buf) { int curl = 0; Eina_Strbuf *wbuf = eina_strbuf_new(); if (indent) eina_strbuf_append(buf, "/**<\n"); else eina_strbuf_append(buf, "/**\n"); curl += _indent_line(buf, indent); eina_strbuf_append(buf, " * @brief "); curl += sizeof(" * @brief ") - 1; _append_section(state, summary, indent, curl, buf, wbuf); eina_strbuf_append_char(buf, '\n'); _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); curl = _indent_line(buf, indent); eina_strbuf_append(buf, " * "); _append_section(state, description, indent, curl + 3, buf, wbuf); curl = _append_extra(el, indent, curl, EINA_TRUE, buf); curl = _append_since(since, indent, curl, buf); eina_strbuf_append_char(buf, '\n'); _indent_line(buf, indent); char *sgrp = _sanitize_group(group); if (sgrp) { eina_strbuf_append(buf, " *\n"); _indent_line(buf, indent); } _append_group(buf, sgrp, indent); eina_strbuf_append(buf, " */"); eina_strbuf_free(wbuf); } static Eina_Strbuf * _gen_doc_buf(const Eolian_State *state, const Eolian_Documentation *doc, const char *group, const char *el, int indent) { if (!doc) return NULL; const char *sum = eolian_documentation_summary_get(doc); sum = SUMMARY_OR_DEFAULT(sum); const char *desc = eolian_documentation_description_get(doc); const char *since = eolian_documentation_since_get(doc); Eina_Strbuf *buf = eina_strbuf_new(); if (!desc) _gen_doc_brief(state, sum, since, group, el, indent, buf); else _gen_doc_full(state, sum, desc, since, group, el, indent, buf); return buf; } Eina_Strbuf * eo_gen_docs_full_gen(const Eolian_State *state, const Eolian_Documentation *doc, const char *group, int indent) { return _gen_doc_buf(state, doc, group, NULL, indent); } Eina_Strbuf * eo_gen_docs_event_gen(const Eolian_State *state, const Eolian_Event *ev, const char *group) { if (!ev) return NULL; const Eolian_Documentation *doc = eolian_event_documentation_get(ev); char buf[1024]; const Eolian_Type *rt = eolian_event_type_get(ev); const char *p = NULL; if (rt) { p = buf; Eina_Stringshare *rts = eolian_type_c_type_get(rt); snprintf(buf, sizeof(buf), "@return %s", rts); eina_stringshare_del(rts); } if (!doc) { Eina_Strbuf *bufs = eina_strbuf_new(); eina_strbuf_append(bufs, "/**\n * No description\n"); if (p) { eina_strbuf_append(bufs, " * "); eina_strbuf_append(bufs, p); eina_strbuf_append_char(bufs, '\n'); } eina_strbuf_append(bufs, " */"); return bufs; } return _gen_doc_buf(state, doc, group, p, 0); } Eina_Strbuf * eo_gen_docs_func_gen(const Eolian_State *state, const Eolian_Function *fid, Eolian_Function_Type ftype, int indent) { 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_name_get(eolian_function_class_get(fid)); + const char *group = eolian_class_c_name_get(eolian_function_class_get(fid)); const Eolian_Implement *fimp = eolian_function_implement_get(fid); if (ftype == EOLIAN_METHOD) { doc = eolian_implement_documentation_get(fimp, EOLIAN_METHOD); pdoc = NULL; } else { doc = eolian_implement_documentation_get(fimp, EOLIAN_PROPERTY); pdoc = eolian_implement_documentation_get(fimp, 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); } 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)) { const Eolian_Function_Parameter *rvpar = vpar; if (!eina_iterator_next(vitr, (void**)&vpar)) { /* one value - not out param */ eina_iterator_free(vitr); rdoc = rvpar ? eolian_parameter_documentation_get(rvpar) : NULL; 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(state, SUMMARY_OR_DEFAULT(sum), since, group, NULL, indent, buf); 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(state, SUMMARY_OR_DEFAULT(sum), indent, curl, buf, wbuf); 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(state, desc, indent, curl + 3, buf, wbuf); 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, " * "); const char *psum = eolian_documentation_summary_get(pdoc); _append_section(state, SUMMARY_OR_DEFAULT(psum), indent, curl + 3, buf, wbuf); 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(state, pdesc, indent, curl + 3, buf, wbuf); eina_strbuf_append_char(buf, '\n'); } if (par || rdoc || since) { _indent_line(buf, indent); eina_strbuf_append(buf, " *\n"); } } if (!eolian_function_is_static(fid)) { _indent_line(buf, indent); eina_strbuf_append(buf, " * @param[in] obj The object.\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_Direction dir = EOLIAN_PARAMETER_OUT; if (!force_out) dir = eolian_parameter_direction_get(par); switch (dir) { case EOLIAN_PARAMETER_OUT: eina_strbuf_append(buf, " * @param[out] "); curl += sizeof(" * @param[out] ") - 1; break; case EOLIAN_PARAMETER_INOUT: eina_strbuf_append(buf, " * @param[in,out] "); curl += sizeof(" * @param[in,out] ") - 1; break; default: eina_strbuf_append(buf, " * @param[in] "); curl += sizeof(" * @param[in] ") - 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; const char *asum = eolian_documentation_summary_get(adoc); _append_section(state, SUMMARY_OR_DEFAULT(asum), indent, curl, buf, wbuf); } 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; const char *rsum = eolian_documentation_summary_get(rdoc); _append_section(state, SUMMARY_OR_DEFAULT(rsum), indent, curl, buf, wbuf); 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; } diff --git a/src/bin/eolian/headers.c b/src/bin/eolian/headers.c index ead40d8f75..0ba05ee88e 100644 --- a/src/bin/eolian/headers.c +++ b/src/bin/eolian/headers.c @@ -1,311 +1,311 @@ #include "main.h" #include "docs.h" static const char * _get_add_star(Eolian_Function_Type ftype, Eolian_Parameter_Direction pdir) { if (ftype == EOLIAN_PROP_GET) return "*"; if ((pdir == EOLIAN_PARAMETER_OUT) || (pdir == EOLIAN_PARAMETER_INOUT)) return "*"; return ""; } static int _gen_param(Eina_Strbuf *buf, Eolian_Function_Parameter *pr, Eolian_Function_Type ftype, int *rpid) { const Eolian_Type *prt = eolian_parameter_type_get(pr); const Eolian_Typedecl *ptd = eolian_type_typedecl_get(prt); const char *prn = eolian_parameter_name_get(pr); Eina_Stringshare *prtn = eolian_parameter_c_type_get(pr, EINA_FALSE); if (ptd && (eolian_typedecl_type_get(ptd) == EOLIAN_TYPEDECL_FUNCTION_POINTER)) { eina_strbuf_append_printf(buf, "void *%s_data, %s %s, Eina_Free_Cb %s_free_cb", prn, prtn, prn, prn); eina_stringshare_del(prtn); *rpid = 1; return 3; } 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); if (eolian_parameter_is_move(pr)) eina_strbuf_append(buf, " EFL_TRANSFER_OWNERSHIP"); *rpid = 0; return 1; } void eo_gen_params(Eina_Iterator *itr, Eina_Strbuf *buf, Eina_Strbuf **flagbuf, int *nidx, Eolian_Function_Type ftype) { Eolian_Function_Parameter *pr; EINA_ITERATOR_FOREACH(itr, pr) { int rpid = 0; if (*nidx) eina_strbuf_append(buf, ", "); *nidx += _gen_param(buf, pr, ftype, &rpid); /* Keep the logic for when there's a better way to emit NONNULL */ #if 0 if (!eolian_parameter_is_nonull(pr) || !flagbuf) continue; if (!*flagbuf) { *flagbuf = eina_strbuf_new(); eina_strbuf_append_printf(*flagbuf, " EINA_ARG_NONNULL(%d", *nidx - rpid); } else eina_strbuf_append_printf(*flagbuf, ", %d", *nidx - rpid); #else (void)flagbuf; #endif } eina_iterator_free(itr); } static void _gen_func(const Eolian_State *state, const Eolian_Function *fid, Eolian_Function_Type ftype, Eina_Strbuf *buf, char *cnameu) { Eina_Stringshare *fcn = eolian_function_full_c_name_get(fid, ftype); if (!fcn) return; Eina_Bool var_as_ret = EINA_FALSE; const Eolian_Type *rtp = eolian_function_return_type_get(fid, ftype); Eina_Bool return_move = eolian_function_return_is_move(fid, ftype); Eina_Stringshare *rtps = NULL; 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)) { Eolian_Function_Parameter *pr = (Eolian_Function_Parameter *)d1; rtp = eolian_parameter_type_get(pr); return_move = eolian_parameter_is_move(pr); rtps = eolian_parameter_c_type_get(pr, EINA_TRUE); var_as_ret = EINA_TRUE; } eina_iterator_free(itr); } Eolian_Object_Scope fsc = eolian_function_scope_get(fid, ftype); if (eolian_function_is_beta(fid)) eina_strbuf_append(buf, "#ifdef EFL_BETA_API_SUPPORT\n"); if (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(state, fid, ftype, 0); eina_strbuf_append(buf, eina_strbuf_string_get(dbuf)); eina_strbuf_append_char(buf, '\n'); eina_strbuf_free(dbuf); } eina_strbuf_append(buf, "EOAPI "); if (rtp) { if (!rtps) rtps = eolian_function_return_c_type_get(fid, ftype); eina_strbuf_append(buf, rtps); if (rtps[strlen(rtps) - 1] != '*') eina_strbuf_append_char(buf, ' '); } else eina_strbuf_append(buf, "void "); eina_strbuf_append(buf, fcn); eina_stringshare_del(fcn); eina_stringshare_del(rtps); Eina_Strbuf *flagbuf = NULL; int nidx = !eolian_function_is_static(fid); eina_strbuf_append_char(buf, '('); if (nidx) { if ((ftype == EOLIAN_PROP_GET) || eolian_function_object_is_const(fid) || eolian_function_is_static(fid)) { eina_strbuf_append(buf, "const "); } eina_strbuf_append(buf, "Eo *obj"); } eo_gen_params(eolian_property_keys_get(fid, ftype), buf, &flagbuf, &nidx, EOLIAN_PROPERTY); 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); eo_gen_params(itr, buf, &flagbuf, &nidx, ftype); } if (flagbuf) eina_strbuf_append_char(flagbuf, ')'); /* zero-arg funcs in C need void for arguments */ if (eina_strbuf_string_get(buf)[eina_strbuf_length_get(buf) - 1] == '(') eina_strbuf_append(buf, "void"); eina_strbuf_append(buf, ")"); if (!eolian_function_return_allow_unused(fid, ftype) || return_move) { if (!flagbuf) flagbuf = eina_strbuf_new(); eina_strbuf_prepend(flagbuf, " EINA_WARN_UNUSED_RESULT"); } if (return_move) eina_strbuf_append(buf, " EFL_TRANSFER_OWNERSHIP"); if (flagbuf) { eina_strbuf_append(buf, eina_strbuf_string_get(flagbuf)); eina_strbuf_free(flagbuf); } eina_strbuf_append(buf, ";\n"); if (fsc == EOLIAN_SCOPE_PROTECTED) eina_strbuf_append_printf(buf, "#endif\n"); if (eolian_function_is_beta(fid)) eina_strbuf_append_printf(buf, "#endif /* EFL_BETA_API_SUPPORT */\n"); } void eo_gen_header_gen(const Eolian_State *state, const Eolian_Class *cl, Eina_Strbuf *buf) { if (!cl) return; Eina_Iterator *itr; Eolian_Event *ev; char *cnameu = NULL; eo_gen_class_names_get(cl, NULL, &cnameu, NULL); /* class definition */ if (eolian_class_is_beta(cl)) { eina_strbuf_append(buf, "#ifdef EFL_BETA_API_SUPPORT\n"); } const Eolian_Documentation *doc = eolian_class_documentation_get(cl); if (doc) { Eina_Strbuf *cdoc = eo_gen_docs_full_gen(state, doc, - eolian_class_name_get(cl), 0); + eolian_class_c_name_get(cl), 0); if (cdoc) { eina_strbuf_append(buf, eina_strbuf_string_get(cdoc)); eina_strbuf_append_char(buf, '\n'); eina_strbuf_free(cdoc); } } Eina_Stringshare *mname = eolian_class_c_macro_get(cl); Eina_Stringshare *gname = eolian_class_c_get_function_name_get(cl); eina_strbuf_append_printf(buf, "#define %s %s()\n\n", mname, gname); eina_stringshare_del(mname); eina_strbuf_append_printf(buf, "EWAPI const Efl_Class *%s(void);\n", gname); eina_stringshare_del(gname); /* method section */ itr = eolian_class_implements_get(cl); if (!itr) goto events; const Eolian_Implement *imp; EINA_ITERATOR_FOREACH(itr, imp) { if (eolian_implement_class_get(imp) != cl) continue; Eolian_Function_Type ftype = EOLIAN_UNRESOLVED; const Eolian_Function *fid = eolian_implement_function_get(imp, &ftype); eina_strbuf_append_char(buf, '\n'); switch (ftype) { case EOLIAN_PROP_GET: case EOLIAN_PROP_SET: _gen_func(state, fid, ftype, buf, cnameu); break; case EOLIAN_PROPERTY: _gen_func(state, fid, EOLIAN_PROP_SET, buf, cnameu); eina_strbuf_append_char(buf, '\n'); _gen_func(state, fid, EOLIAN_PROP_GET, buf, cnameu); break; default: _gen_func(state, fid, EOLIAN_METHOD, buf, cnameu); } } eina_iterator_free(itr); events: /* event section */ itr = eolian_class_events_get(cl); EINA_ITERATOR_FOREACH(itr, ev) { Eina_Stringshare *evn = eolian_event_c_macro_get(ev); Eolian_Object_Scope evs = eolian_event_scope_get(ev); if (evs == EOLIAN_SCOPE_PRIVATE) continue; if (eolian_event_is_beta(ev)) { eina_strbuf_append(buf, "#ifdef EFL_BETA_API_SUPPORT\n"); } if (evs == EOLIAN_SCOPE_PROTECTED) { if (!eolian_event_is_beta(ev)) eina_strbuf_append_char(buf, '\n'); eina_strbuf_append_printf(buf, "#ifdef %s_PROTECTED\n", cnameu); } if (!eolian_event_is_beta(ev) && evs == EOLIAN_SCOPE_PUBLIC) eina_strbuf_append_char(buf, '\n'); eina_strbuf_append_printf(buf, "EWAPI extern const " "Efl_Event_Description _%s;\n\n", evn); Eina_Strbuf *evdbuf = eo_gen_docs_event_gen(state, ev, - eolian_class_name_get(cl)); + eolian_class_c_name_get(cl)); eina_strbuf_append(buf, eina_strbuf_string_get(evdbuf)); eina_strbuf_append_char(buf, '\n'); eina_strbuf_free(evdbuf); eina_strbuf_append_printf(buf, "#define %s (&(_%s))\n", evn, evn); if (evs == EOLIAN_SCOPE_PROTECTED) eina_strbuf_append(buf, "#endif\n"); if (eolian_event_is_beta(ev)) eina_strbuf_append(buf, "#endif /* EFL_BETA_API_SUPPORT */\n"); eina_stringshare_del(evn); } eina_iterator_free(itr); if (eolian_class_is_beta(cl)) { eina_strbuf_append(buf, "#endif /* EFL_BETA_API_SUPPORT */\n"); } free(cnameu); } diff --git a/src/bin/eolian/main.c b/src/bin/eolian/main.c index 114f989ac4..8e965e25b2 100644 --- a/src/bin/eolian/main.c +++ b/src/bin/eolian/main.c @@ -1,673 +1,673 @@ #include #include #include "main.h" #include "types.h" #include "headers.h" #include "sources.h" int _eolian_gen_log_dom = -1; enum { GEN_H = 1 << 0, GEN_H_STUB = 1 << 1, GEN_C = 1 << 2, GEN_C_IMPL = 1 << 3, GEN_D = 1 << 4, GEN_D_FULL = 1 << 5 }; static const char *_dexts[6] = { ".h", ".stub.h", ".c", ".c", ".d", ".d" }; static int _get_bit_pos(int flag) { int pos = 0; for (; !(flag & 1); flag >>= 1) ++pos; return pos; } static void _print_usage(const char *progn, FILE *outf) { fprintf(outf, "Usage: %s [options] [input]\n", progn); fprintf(outf, "Options:\n" " -I inc include path \"inc\"\n" " -S do not scan system dir for eo files\n" " -g type generate file of type \"type\"\n" " -o name specify the base name for output\n" " -o type:name specify a particular output filename\n" " -h print this message and exit\n" " -v print version and exit\n" "\n" "Available types:\n" " h: C header file (.eo.h/.eot.h)\n" " s: Stub C header file (.eo.stub.h/.eot.stub.h)\n" " c: C source file (.eo.c)\n" " i: Implementation file (.c, merged with existing)\n" " d: Make-style dependencies, only for headers (.d)\n" " D: Like 'd' but for all generated files (.d)\n" "\n" "By default, the 'hc' set is used ('h' for .eot files).\n\n" "The system-wide Eolian directory is scanned for eo files\n" "by default, together with all specified '-I' flags.\n\n" "Output filenames are determined from input .eo filename.\n" "Default output path is where the input file is.\n\n" "Also, specifying a type-dependent input file automatically\n" "adds it to generated files, so if you specify those, you\n" "don't need to explicitly specify -g for those types anymore.\n\n" "Explicit output base name is without extension. The extension\n" "is determined from the input file name. If that is not possible\n" "for some reason, it defaults to \".eo\". Obviously, this does not\n" "affect specific filenames (-o x:y) as these are full names.\n" "Implementation files are a special case (no \".eo\" added).\n"); } static void _print_version(FILE *outf) { fprintf(outf, "Eolian C generator version: " PACKAGE_VERSION "\n"); } static Eina_Bool _try_set_out(char t, char **outs, const char *val, int *what) { int pos = -1; switch (t) { case 'h': pos = _get_bit_pos(GEN_H); *what |= GEN_H; break; case 's': pos = _get_bit_pos(GEN_H_STUB); *what |= GEN_H_STUB; break; case 'c': pos = _get_bit_pos(GEN_C); *what |= GEN_C; break; case 'i': pos = _get_bit_pos(GEN_C_IMPL); *what |= GEN_C_IMPL; break; case 'd': pos = _get_bit_pos(GEN_D); *what |= GEN_D; break; case 'D': pos = _get_bit_pos(GEN_D_FULL); *what |= GEN_D_FULL; break; } if (pos < 0) return EINA_FALSE; if (outs[pos]) free(outs[pos]); outs[pos] = strdup(val); return EINA_TRUE; } static void _fill_all_outs(char **outs, const char *val, char *base) { const char *ext = strrchr(val, '.'); if (!ext) ext = ".eo"; char *basen = base; if (!basen) { basen = strdup(val); char *p = strrchr(basen, '.'); if (p) *p = '\0'; } size_t blen = strlen(basen), elen = strlen(ext); for (size_t i = 0; i < (sizeof(_dexts) / sizeof(char *)); ++i) { if (outs[i]) continue; size_t dlen = strlen(_dexts[i]); char *str = malloc(blen + elen + dlen + 1); char *p = str; memcpy(p, basen, blen); p += blen; if ((1 << i) != GEN_C_IMPL) { memcpy(p, ext, elen); p += elen; } memcpy(p, _dexts[i], dlen); p[dlen] = '\0'; outs[i] = str; } if (!base) free(basen); } static Eina_Strbuf * _include_guard(const char *fname, const char *gname, Eina_Strbuf *buf) { if (!buf) return NULL; if (!gname) gname = ""; char iname[256] = {0}; strncpy(iname, fname, sizeof(iname) - 1); char *inamep = iname; eina_str_toupper(&inamep); Eina_Strbuf *g = eina_strbuf_new(); eina_strbuf_append_printf(g, "#ifndef _%s_%s\n", iname, gname); eina_strbuf_append_printf(g, "#define _%s_%s\n\n", iname, gname); eina_strbuf_replace_all(g, ".", "_"); eina_strbuf_append(g, eina_strbuf_string_get(buf)); eina_strbuf_append(g, "\n#endif\n"); eina_strbuf_free(buf); return g; } static const char * _get_filename(const char *path) { if (!path) return NULL; const char *ret1 = strrchr(path, '/'); const char *ret2 = strrchr(path, '\\'); if (!ret1 && !ret2) return path; if (ret1 && ret2) { if (ret1 > ret2) return ret1 + 1; else return ret2 + 1; } if (ret1) return ret1 + 1; return ret2 + 1; } static Eina_Bool _write_file(const char *fname, const Eina_Strbuf *buf) { FILE *f = fopen(fname, "wb"); if (!f) { fprintf(stderr, "eolian: could not open '%s' (%s)\n", fname, strerror(errno)); return EINA_FALSE; } Eina_Bool fret = EINA_TRUE; size_t bl = eina_strbuf_length_get(buf); if (!bl) goto end; if (fwrite(eina_strbuf_string_get(buf), 1, bl, f) != bl) { fprintf(stderr, "eolian: could not write '%s' (%s)\n", fname, strerror(errno)); fret = EINA_FALSE; } end: fclose(f); return fret; } static Eina_Bool _read_file(const char *fname, Eina_Strbuf **buf) { FILE *f = fopen(fname, "rb"); if (!f) { *buf = eina_strbuf_new(); return EINA_TRUE; } fseek(f, 0, SEEK_END); long fs = ftell(f); if (fs < 0) { fprintf(stderr, "eolian: could not get length of '%s'\n", fname); fclose(f); return EINA_FALSE; } fseek(f, 0, SEEK_SET); char *cont = malloc(fs + 1); if (!cont) { fprintf(stderr, "eolian: could not allocate memory for '%s'\n", fname); fclose(f); return EINA_FALSE; } long as = fread(cont, 1, fs, f); if (as != fs) { fprintf(stderr, "eolian: could not read %ld bytes from '%s' (got %ld)\n", fs, fname, as); free(cont); fclose(f); return EINA_FALSE; } cont[fs] = '\0'; fclose(f); *buf = eina_strbuf_manage_new_length(cont, fs); return EINA_TRUE; } char *eo_gen_c_full_name_get(const char *nm) { if (!nm) return NULL; char *buf = strdup(nm); if (!buf) abort(); for (char *p = strchr(buf, '.'); p; p = strchr(p, '.')) *p = '_'; return buf; } void eo_gen_class_names_get(const Eolian_Class *cl, char **cname, char **cnameu, char **cnamel) { char *cn = NULL, *cnu = NULL, *cnl = NULL; - cn = eo_gen_c_full_name_get(eolian_class_name_get(cl)); + cn = eo_gen_c_full_name_get(eolian_class_c_name_get(cl)); if (!cn) abort(); if (cname) *cname = cn; if (cnameu) { cnu = strdup(cn); if (!cnu) { free(cn); abort(); } eina_str_toupper(&cnu); *cnameu = cnu; } if (cnamel) { cnl = strdup(cn); if (!cnl) { free(cn); free(cnu); abort(); } eina_str_tolower(&cnl); *cnamel = cnl; } if (!cname) free(cn); } static Eina_Bool _write_header(const Eolian_State *eos, const Eolian_State *state, const char *ofname, const char *ifname) { INF("generating header: %s", ofname); Eina_Strbuf *buf = eina_strbuf_new(); eo_gen_types_header_gen(state, eolian_state_objects_by_file_get(eos, ifname), buf, EINA_TRUE); buf = _include_guard(ifname, "TYPES", buf); Eina_Strbuf *cltd = eo_gen_class_typedef_gen(eos, ifname); if (cltd) { cltd = _include_guard(ifname, "CLASS_TYPE", cltd); eina_strbuf_prepend_char(buf, '\n'); eina_strbuf_prepend(buf, eina_strbuf_string_get(cltd)); eina_strbuf_free(cltd); } eo_gen_header_gen(state, eolian_state_class_by_file_get(eos, ifname), buf); buf = _include_guard(_get_filename(ofname), NULL, buf); if (_write_file(ofname, buf)) { eina_strbuf_free(buf); return EINA_TRUE; } eina_strbuf_free(buf); return EINA_FALSE; } static Eina_Bool _write_stub_header(const Eolian_State *eos, const Eolian_State *state, const char *ofname, const char *ifname) { INF("generating stub header: %s", ofname); Eina_Strbuf *buf = eina_strbuf_new(); eo_gen_types_header_gen(state, eolian_state_objects_by_file_get(eos, ifname), buf, EINA_FALSE); Eina_Strbuf *cltd = eo_gen_class_typedef_gen(eos, ifname); if (cltd) { eina_strbuf_prepend_char(buf, '\n'); eina_strbuf_prepend(buf, eina_strbuf_string_get(cltd)); eina_strbuf_free(cltd); } buf = _include_guard(_get_filename(ofname), "STUBS", buf); Eina_Bool ret = _write_file(ofname, buf); eina_strbuf_free(buf); return ret; } static Eina_Bool _write_source(const Eolian_State *eos, const char *ofname, const char *ifname, Eina_Bool eot) { INF("generating source: %s", ofname); Eina_Strbuf *buf = eina_strbuf_new(); Eina_Bool ret = EINA_FALSE; const Eolian_Class *cl = eolian_state_class_by_file_get(eos, ifname); eo_gen_types_source_gen(eolian_state_objects_by_file_get(eos, ifname), buf); eo_gen_source_gen(cl, buf); if (cl || eot) { /* always have at least a stub in order to allow unconditional generation */ if (!eina_strbuf_length_get(buf)) eina_strbuf_append(buf, "/* Nothing to implement. */\n"); if (!_write_file(ofname, buf)) goto done; ret = EINA_TRUE; } done: eina_strbuf_free(buf); return ret; } static Eina_Bool _write_impl(const Eolian_State *eos, const char *ofname, const char *ifname) { INF("generating impl: %s", ofname); const Eolian_Class *cl = eolian_state_class_by_file_get(eos, ifname); if (!cl) return EINA_FALSE; Eina_Strbuf *buf; if (!_read_file(ofname, &buf)) return EINA_FALSE; eo_gen_impl_gen(cl, buf); Eina_Bool ret = _write_file(ofname, buf); eina_strbuf_free(buf); return ret; } static void _append_dep_line(Eina_Strbuf *buf, Eina_Strbuf *dbuf, char **outs, int gen_what, int what) { if (!(gen_what & what)) return; eina_strbuf_append(buf, outs[_get_bit_pos(what)]); eina_strbuf_append_buffer(buf, dbuf); } static Eina_Bool _write_deps(const Eolian_State *eos, const char *ofname, const char *ifname, char **outs, int gen_what) { INF("generating deps: %s", ofname); Eina_Bool ret = EINA_TRUE; Eina_Strbuf *buf = eina_strbuf_new(); Eina_Strbuf *dbuf = eina_strbuf_new(); const Eolian_Unit *un = eolian_state_unit_by_file_get(eos, ifname); if (!un) { ret = EINA_FALSE; goto result; } eina_strbuf_append(dbuf, ": "); /* every generated file depends on its .eo/.eot file */ eina_strbuf_append(dbuf, eolian_unit_file_path_get(un)); const Eolian_Unit *dun; Eina_Iterator *deps = eolian_unit_children_get(un); EINA_ITERATOR_FOREACH(deps, dun) { const char *dpath = eolian_unit_file_path_get(dun); if (!dpath) continue; eina_strbuf_append_char(dbuf, ' '); eina_strbuf_append(dbuf, dpath); } eina_iterator_free(deps); eina_strbuf_append_char(dbuf, '\n'); _append_dep_line(buf, dbuf, outs, gen_what, GEN_H); _append_dep_line(buf, dbuf, outs, gen_what, GEN_H_STUB); if (gen_what & GEN_D_FULL) { _append_dep_line(buf, dbuf, outs, gen_what, GEN_C); _append_dep_line(buf, dbuf, outs, gen_what, GEN_C_IMPL); } ret = _write_file(ofname, buf); result: eina_strbuf_free(dbuf); eina_strbuf_free(buf); return ret; } int main(int argc, char **argv) { int pret = 1; char *outs[sizeof(_dexts) / sizeof(void *)] = { NULL, NULL, NULL, NULL, NULL, NULL }; char *basen = NULL; Eina_List *includes = NULL; eina_init(); eolian_init(); Eolian_State *eos = eolian_state_new(); const char *dom = "eolian_gen"; _eolian_gen_log_dom = eina_log_domain_register(dom, EINA_COLOR_GREEN); if (_eolian_gen_log_dom < 0) { EINA_LOG_ERR("Could not register log domain: %s", dom); goto end; } eina_log_timing(_eolian_gen_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT); int gen_what = 0; Eina_Bool scan_system = EINA_TRUE; for (int opt; (opt = getopt(argc, argv, "SI:g:o:hv")) != -1;) switch (opt) { case 0: break; case 'S': scan_system = EINA_FALSE; break; case 'I': /* just a pointer to argv contents, so it persists */ includes = eina_list_append(includes, optarg); break; case 'g': for (const char *wstr = optarg; *wstr; ++wstr) switch (*wstr) { case 'h': gen_what |= GEN_H; break; case 's': gen_what |= GEN_H_STUB; break; case 'c': gen_what |= GEN_C; break; case 'i': gen_what |= GEN_C_IMPL; break; case 'd': gen_what |= GEN_D; break; case 'D': gen_what |= GEN_D_FULL; break; default: fprintf(stderr, "unknown type: '%c'\n", *wstr); goto end; } break; case 'o': if (strchr(optarg, ':')) { const char *abeg = optarg; const char *cpos = strchr(abeg, ':'); if (((cpos - abeg) != 1) || !_try_set_out(*abeg, outs, cpos + 1, &gen_what)) { char *oa = strdup(abeg); oa[cpos - abeg] = '\0'; fprintf(stderr, "unknown type: '%s'\n", oa); free(oa); goto end; } } else { if (basen) free(basen); basen = strdup(optarg); } break; case 'h': _print_usage(argv[0], stdout); pret = 0; goto end; case 'v': _print_version(stdout); pret = 0; goto end; default: _print_usage(argv[0], stderr); goto end; } const char *input = argv[optind]; if (!input) { fprintf(stderr, "eolian: no input file\n"); goto end; } const char *ext = strrchr(input, '.'); if (!ext || (strcmp(ext, ".eo") && strcmp(ext, ".eot"))) { fprintf(stderr, "eolian: invalid input file '%s'\n", input); goto end; } if (scan_system) { if (!eolian_state_system_directory_add(eos)) { fprintf(stderr, "eolian: could not scan system directory\n"); goto end; } } const char *inc; EINA_LIST_FREE(includes, inc) { if (!eolian_state_directory_add(eos, inc)) { fprintf(stderr, "eolian: could not scan '%s'\n", inc); goto end; } } if (!eolian_state_file_path_parse(eos, input)) { fprintf(stderr, "eolian: could not parse file '%s'\n", input); goto end; } _fill_all_outs(outs, input, basen); const char *eobn = _get_filename(input); if (!gen_what) gen_what = GEN_H | GEN_C; Eina_Bool succ = EINA_TRUE; if (gen_what & GEN_H) succ = _write_header(eos, eos, outs[_get_bit_pos(GEN_H)], eobn); if (succ && (gen_what & GEN_H_STUB)) succ = _write_stub_header(eos, eos, outs[_get_bit_pos(GEN_H_STUB)], eobn); if (succ && (gen_what & GEN_C)) succ = _write_source(eos, outs[_get_bit_pos(GEN_C)], eobn, !strcmp(ext, ".eot")); if (succ && (gen_what & GEN_C_IMPL)) succ = _write_impl(eos, outs[_get_bit_pos(GEN_C_IMPL)], eobn); if (succ && (gen_what & GEN_D_FULL)) succ = _write_deps(eos, outs[_get_bit_pos(GEN_D_FULL)], eobn, outs, gen_what); else if (succ && (gen_what & GEN_D)) succ = _write_deps(eos, outs[_get_bit_pos(GEN_D)], eobn, outs, gen_what); if (!succ) goto end; pret = 0; end: if (_eolian_gen_log_dom >= 0) { eina_log_timing(_eolian_gen_log_dom, EINA_LOG_STATE_START, EINA_LOG_STATE_SHUTDOWN); eina_log_domain_unregister(_eolian_gen_log_dom); } eina_list_free(includes); for (size_t i = 0; i < (sizeof(_dexts) / sizeof(char *)); ++i) free(outs[i]); free(basen); eolian_state_free(eos); eolian_shutdown(); eina_shutdown(); return pret; } diff --git a/src/bin/eolian/types.c b/src/bin/eolian/types.c index 96232833cd..9b44279d98 100644 --- a/src/bin/eolian/types.c +++ b/src/bin/eolian/types.c @@ -1,395 +1,395 @@ #include #include "main.h" #include "headers.h" #include "docs.h" static Eina_Strbuf * _type_generate(const Eolian_State *state, const Eolian_Typedecl *tp, Eina_Bool full) { - char *grp = strdup(eolian_typedecl_name_get(tp)); + char *grp = strdup(eolian_typedecl_c_name_get(tp)); char *p = strrchr(grp, '.'); if (p) *p = '\0'; Eina_Strbuf *buf = eo_gen_docs_full_gen(state, eolian_typedecl_documentation_get(tp), grp, 0); free(grp); if (!buf) buf = eina_strbuf_new(); else eina_strbuf_append_char(buf, '\n'); Eolian_Typedecl_Type tpt = eolian_typedecl_type_get(tp); switch (tpt) { case EOLIAN_TYPEDECL_ALIAS: { Eina_Stringshare *tn = eolian_typedecl_c_type_get(tp); eina_strbuf_append(buf, tn); eina_stringshare_del(tn); break; } case EOLIAN_TYPEDECL_STRUCT: case EOLIAN_TYPEDECL_STRUCT_OPAQUE: { const Eolian_Struct_Type_Field *memb; - char *fn = eo_gen_c_full_name_get(eolian_typedecl_name_get(tp)); + char *fn = eo_gen_c_full_name_get(eolian_typedecl_c_name_get(tp)); if (tpt == EOLIAN_TYPEDECL_STRUCT_OPAQUE || !full) { eina_strbuf_append_printf(buf, "typedef struct _%s %s", fn, fn); free(fn); break; } eina_strbuf_append_printf(buf, "typedef struct _%s\n{\n", fn); Eina_Iterator *membs = eolian_typedecl_struct_fields_get(tp); EINA_ITERATOR_FOREACH(membs, memb) { Eina_Stringshare *ct = NULL; ct = eolian_typedecl_struct_field_c_type_get(memb); eina_strbuf_append_printf(buf, " %s%s%s;", ct, strchr(ct, '*') ? "" : " ", eolian_typedecl_struct_field_name_get(memb)); eina_stringshare_del(ct); const Eolian_Documentation *fdoc = eolian_typedecl_struct_field_documentation_get(memb); if (fdoc) { const char *nl = strrchr(eina_strbuf_string_get(buf), '\n'); if (nl) { Eina_Strbuf *fbuf = eo_gen_docs_full_gen(state, fdoc, NULL, strlen(nl)); if (fbuf) eina_strbuf_append_printf(buf, " %s", eina_strbuf_string_get(fbuf)); eina_strbuf_free(fbuf); } } eina_strbuf_append(buf, "\n"); } eina_iterator_free(membs); eina_strbuf_append_printf(buf, "} %s", fn); free(fn); break; } case EOLIAN_TYPEDECL_ENUM: { const Eolian_Enum_Type_Field *memb; if (!full) break; eina_strbuf_append_printf(buf, "typedef enum\n{\n"); Eina_Iterator *membs = eolian_typedecl_enum_fields_get(tp); Eina_Bool next = eina_iterator_next(membs, (void **)&memb); while (next) { const Eolian_Expression *vale = eolian_typedecl_enum_field_value_get(memb, EINA_FALSE); Eina_Stringshare *membn = eolian_typedecl_enum_field_c_constant_get(memb); if (!vale) eina_strbuf_append_printf(buf, " %s", membn); else { Eolian_Value val = eolian_expression_eval(vale, EOLIAN_MASK_INT); const char *lit = eolian_expression_value_to_literal(&val); eina_strbuf_append_printf(buf, " %s = %s", membn, lit); const char *exp = eolian_expression_serialize(vale); if (exp && strcmp(lit, exp)) eina_strbuf_append_printf(buf, " /* %s */", exp); eina_stringshare_del(exp); eina_stringshare_del(lit); } eina_stringshare_del(membn); const Eolian_Documentation *fdoc = eolian_typedecl_enum_field_documentation_get(memb); next = eina_iterator_next(membs, (void **)&memb); if (next) eina_strbuf_append(buf, ","); if (fdoc) { const char *nl = strrchr(eina_strbuf_string_get(buf), '\n'); if (nl) { Eina_Strbuf *fbuf = eo_gen_docs_full_gen(state, fdoc, NULL, strlen(nl)); if (fbuf) eina_strbuf_append_printf(buf, " %s", eina_strbuf_string_get(fbuf)); eina_strbuf_free(fbuf); } } eina_strbuf_append(buf, "\n"); } eina_iterator_free(membs); - char *fn = eo_gen_c_full_name_get(eolian_typedecl_name_get(tp)); + char *fn = eo_gen_c_full_name_get(eolian_typedecl_c_name_get(tp)); eina_strbuf_append_printf(buf, "} %s", fn); free(fn); break; } case EOLIAN_TYPEDECL_FUNCTION_POINTER: { const Eolian_Function *fid = eolian_typedecl_function_pointer_get(tp); eina_strbuf_append(buf, "typedef "); /* Return type */ const Eolian_Type *rtp = eolian_function_return_type_get(fid, EOLIAN_FUNCTION_POINTER); if (!rtp) eina_strbuf_append(buf, "void "); else { Eina_Stringshare *ct = eolian_function_return_c_type_get(fid, EOLIAN_FUNCTION_POINTER); eina_strbuf_append_printf(buf, "%s ", ct); eina_stringshare_del(ct); } /* Function name */ - char *fn = eo_gen_c_full_name_get(eolian_typedecl_name_get(tp)); + char *fn = eo_gen_c_full_name_get(eolian_typedecl_c_name_get(tp)); eina_strbuf_append_printf(buf, "(*%s)", fn); free(fn); /* Parameters */ eina_strbuf_append(buf, "(void *data"); int nidx = 1; eo_gen_params(eolian_function_parameters_get(fid), buf, NULL, &nidx, EOLIAN_FUNCTION_POINTER); eina_strbuf_append(buf, ")"); break; } default: eina_strbuf_reset(buf); break; } eina_strbuf_append_char(buf, ';'); if (eolian_typedecl_is_beta(tp)) { eina_strbuf_prepend(buf, "#ifdef EFL_BETA_API_SUPPORT\n"); eina_strbuf_append(buf, "\n#endif /* EFL_BETA_API_SUPPORT */"); } return buf; } static Eina_Strbuf * _const_generate(const Eolian_State *state, const Eolian_Constant *vr) { - char *fn = strdup(eolian_constant_name_get(vr)); + char *fn = strdup(eolian_constant_c_name_get(vr)); char *p = strrchr(fn, '.'); if (p) *p = '\0'; Eina_Strbuf *buf = eo_gen_docs_full_gen(state, eolian_constant_documentation_get(vr), fn, 0); if (p) { *p = '_'; while ((p = strchr(fn, '.'))) *p = '_'; } eina_str_toupper(&fn); if (!buf) buf = eina_strbuf_new(); else eina_strbuf_append_char(buf, '\n'); /* we generate a define macro here, as it's a constant */ eina_strbuf_prepend_printf(buf, "#ifndef %s\n", fn); eina_strbuf_append_printf(buf, "#define %s ", fn); const Eolian_Expression *vv = eolian_constant_value_get(vr); Eolian_Value val = eolian_expression_eval(vv, EOLIAN_MASK_ALL); Eina_Stringshare *lit = eolian_expression_value_to_literal(&val); eina_strbuf_append(buf, lit); Eina_Stringshare *exp = eolian_expression_serialize(vv); if (exp && strcmp(lit, exp)) eina_strbuf_append_printf(buf, " /* %s */", exp); eina_stringshare_del(lit); eina_stringshare_del(exp); eina_strbuf_append(buf, "\n#endif"); free(fn); if (eolian_constant_is_beta(vr)) { eina_strbuf_prepend(buf, "#ifdef EFL_BETA_API_SUPPORT\n"); eina_strbuf_append(buf, "\n#endif /* EFL_BETA_API_SUPPORT */"); } return buf; } static Eina_Strbuf * _err_generate(const Eolian_State *state, const Eolian_Error *err) { - char *fn = strdup(eolian_error_name_get(err)); + char *fn = strdup(eolian_error_c_name_get(err)); char *p = strrchr(fn, '.'); if (p) *p = '\0'; Eina_Strbuf *buf = eo_gen_docs_full_gen(state, eolian_error_documentation_get(err), fn, 0); if (p) { *p = '_'; while ((p = strchr(fn, '.'))) *p = '_'; } eina_str_tolower(&fn); if (!buf) buf = eina_strbuf_new(); else eina_strbuf_append_char(buf, '\n'); eina_strbuf_prepend_printf(buf, "EWAPI Eina_Error %s_get(void);\n\n", fn); char *ufn = strdup(fn); eina_str_toupper(&ufn); eina_strbuf_append_printf(buf, "#define %s %s_get()", ufn, fn); free(ufn); free(fn); if (eolian_error_is_beta(err)) { eina_strbuf_prepend(buf, "#ifdef EFL_BETA_API_SUPPORT\n"); eina_strbuf_append(buf, "\n#endif /* EFL_BETA_API_SUPPORT */"); } return buf; } void eo_gen_types_header_gen(const Eolian_State *state, Eina_Iterator *itr, Eina_Strbuf *buf, Eina_Bool full) { const Eolian_Object *decl; EINA_ITERATOR_FOREACH(itr, decl) { Eolian_Object_Type dt = eolian_object_type_get(decl); if (dt == EOLIAN_OBJECT_CONSTANT) { const Eolian_Constant *vr = (const Eolian_Constant *)decl; if (!vr || eolian_constant_is_extern(vr)) continue; Eina_Strbuf *vbuf = _const_generate(state, vr); if (vbuf) { eina_strbuf_append(buf, eina_strbuf_string_get(vbuf)); eina_strbuf_append(buf, "\n\n"); eina_strbuf_free(vbuf); } continue; } else if (dt == EOLIAN_OBJECT_ERROR) { const Eolian_Error *err = (const Eolian_Error *)decl; if (!err || eolian_error_is_extern(err)) continue; Eina_Strbuf *ebuf = _err_generate(state, err); if (ebuf) { eina_strbuf_append(buf, eina_strbuf_string_get(ebuf)); eina_strbuf_append(buf, "\n\n"); eina_strbuf_free(ebuf); } continue; } if (dt != EOLIAN_OBJECT_TYPEDECL) continue; const Eolian_Typedecl *tp = (const Eolian_Typedecl *)decl; if (eolian_typedecl_is_extern(tp)) continue; Eolian_Typedecl_Type tpt = eolian_typedecl_type_get(tp); if (tpt == EOLIAN_TYPEDECL_ENUM && !full) continue; if (tpt == EOLIAN_TYPEDECL_ALIAS) { const Eolian_Type *btp = eolian_typedecl_base_type_get(tp); if (eolian_type_type_get(btp) == EOLIAN_TYPE_UNDEFINED) continue; } Eina_Strbuf *tbuf = _type_generate(state, tp, full); if (tbuf) { eina_strbuf_append(buf, eina_strbuf_string_get(tbuf)); eina_strbuf_append(buf, "\n\n"); eina_strbuf_free(tbuf); } } eina_iterator_free(itr); } static void _source_gen_error(Eina_Strbuf *buf, const Eolian_Error *err) { if (eolian_error_is_extern(err)) return; - char *fn = strdup(eolian_error_name_get(err)); + char *fn = strdup(eolian_error_c_name_get(err)); for (char *p = strchr(fn, '.'); p; p = strchr(p, '.')) *p = '_'; eina_str_tolower(&fn); eina_strbuf_append_printf(buf, "EWAPI Eina_Error %s_get(void)\n{\n", fn); free(fn); const char *msg = eolian_error_message_get(err); eina_strbuf_append(buf, " static Eina_Error err = EINA_ERROR_NO_ERROR;\n"); eina_strbuf_append(buf, " if (err == EINA_ERROR_NO_ERROR)\n"); eina_strbuf_append(buf, " err = eina_error_msg_static_register(\""); for (const char *p = msg; *p; ++p) switch (*p) { case '\\': case '\'': case '\"': { eina_strbuf_append_char(buf, '\\'); eina_strbuf_append_char(buf, *p); continue; } case '\n': { eina_strbuf_append_char(buf, '\\'); eina_strbuf_append_char(buf, 'n'); continue; } case '\t': { eina_strbuf_append_char(buf, '\\'); eina_strbuf_append_char(buf, 't'); continue; } default: { if (isprint(*p)) eina_strbuf_append_char(buf, *p); else eina_strbuf_append_printf(buf, "\\x%2X", (unsigned int)*p); continue; } } eina_strbuf_append(buf, "\");\n"); eina_strbuf_append(buf, " return err;\n}\n\n"); } void eo_gen_types_source_gen(Eina_Iterator *itr, Eina_Strbuf *buf) { const Eolian_Object *decl; EINA_ITERATOR_FOREACH(itr, decl) { Eolian_Object_Type dt = eolian_object_type_get(decl); if (dt == EOLIAN_OBJECT_ERROR) _source_gen_error(buf, (const Eolian_Error *)decl); } eina_iterator_free(itr); } Eina_Strbuf *eo_gen_class_typedef_gen(const Eolian_State *eos, const char *eof) { const Eolian_Class *cl = eolian_state_class_by_file_get(eos, eof); if (!cl) return NULL; - char *clfn = eo_gen_c_full_name_get(eolian_class_name_get(cl)); + char *clfn = eo_gen_c_full_name_get(eolian_class_c_name_get(cl)); if (!clfn) return NULL; Eina_Strbuf *ret = eina_strbuf_new(); eina_strbuf_append_printf(ret, "typedef Eo %s;\n", clfn); free(clfn); return ret; }