#ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include "Eolian.h" #include "impl_generator.h" #include "common_funcs.h" static _eolian_class_vars class_env; static Eina_Bool _params_generate(const Eolian_Function *foo, Eolian_Function_Type ftype, Eina_Bool var_as_ret, Eina_Strbuf *params, Eina_Strbuf *short_params) { Eina_Iterator *itr; Eolian_Function_Parameter *param; Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET); eina_strbuf_reset(params); eina_strbuf_reset(short_params); itr = eolian_property_keys_get(foo, ftype); EINA_ITERATOR_FOREACH(itr, param) { const Eolian_Type *ptypet = eolian_parameter_type_get(param); const char *pname = eolian_parameter_name_get(param); const char *ptype = eolian_type_c_type_get(ptypet); Eina_Bool had_star = !!strchr(ptype, '*'); if (eina_strbuf_length_get(params)) { eina_strbuf_append(params, ", "); eina_strbuf_append(short_params, ", "); } eina_strbuf_append_printf(params, "%s%s%s", ptype, had_star?"":" ", pname); eina_strbuf_append_printf(short_params, "%s", pname); eina_stringshare_del(ptype); } eina_iterator_free(itr); if (!var_as_ret) { itr = is_prop ? eolian_property_values_get(foo, ftype) : eolian_function_parameters_get(foo); EINA_ITERATOR_FOREACH(itr, param) { const Eolian_Type *ptypet = eolian_parameter_type_get(param); const char *pname = eolian_parameter_name_get(param); const char *ptype = eolian_type_c_type_get(ptypet); Eolian_Parameter_Dir pdir = eolian_parameter_direction_get(param); const char *add_star = _get_add_star(ftype, pdir); Eina_Bool had_star = !!strchr(ptype, '*'); if (eina_strbuf_length_get(params)) { eina_strbuf_append(params, ", "); eina_strbuf_append(short_params, ", "); } eina_strbuf_append_printf(params, "%s%s%s%s", ptype, had_star?"":" ", add_star, pname); eina_strbuf_append_printf(short_params, "%s", pname); eina_stringshare_del(ptype); } eina_iterator_free(itr); } return EINA_TRUE; } static Eina_Bool _function_exists(const char* func_name, Eina_Strbuf *buffer) { const char *ptr = eina_strbuf_string_get(buffer); int func_len = strlen(func_name); while ((ptr = strstr(ptr, func_name)) != NULL) { switch (*(ptr - 1)) { case '\n': case ' ': { switch (*(ptr + func_len)) { case ' ': case '(': return EINA_TRUE; } } } ptr++; /* so strstr doesn't fall again on func_name */ } return EINA_FALSE; } /* Check if the type is used in the file, not if it is a typedef... */ static Eina_Bool _type_exists(const char* type_name, Eina_Strbuf *buffer) { const char *ptr = eina_strbuf_string_get(buffer); int type_len = strlen(type_name); while ((ptr = strstr(ptr, type_name)) != NULL) { switch (*(ptr - 1)) { case '\n': case ' ': case ',': { switch (*(ptr + type_len)) { case '\n': case ' ': case ',': case ';': return EINA_TRUE; } } } ptr++; /* so strstr doesn't fall again on type_name */ } return EINA_FALSE; } static Eina_Bool _prototype_generate(const Eolian_Function *foo, Eolian_Function_Type ftype, Eina_Strbuf *data_type_buf, Eolian_Implement *impl_desc, Eina_Strbuf *buffer) { Eina_Bool var_as_ret = EINA_FALSE; Eina_Strbuf *params = NULL, *short_params = NULL, *super_invok = NULL; char func_name[PATH_MAX]; char impl_name[PATH_MAX]; const char *fname; size_t flen; _eolian_class_vars impl_env; if (!impl_desc && eolian_function_is_virtual_pure(foo, ftype)) return EINA_TRUE; super_invok = eina_strbuf_new(); if (impl_desc) { _class_env_create(eolian_implement_class_get(impl_desc), NULL, &impl_env); char *tmp = impl_name; sprintf(impl_name, "%s_%s", class_env.full_classname, impl_env.full_classname); eina_str_tolower(&tmp); } sprintf(func_name, "_%s_%s%s", impl_desc?impl_name:class_env.lower_classname, eolian_function_name_get(foo), ftype == EOLIAN_PROP_GET?"_get": (ftype == EOLIAN_PROP_SET?"_set":"")); if (_function_exists(func_name, buffer)) goto end; printf("Generation of function %s\n", func_name); const Eolian_Type *rettypet = eolian_function_return_type_get(foo, ftype); if (ftype == EOLIAN_PROP_GET && !rettypet) { Eina_Iterator *itr = eolian_property_values_get(foo, ftype); void *data, *data2; /* We want to check if there is only one parameter */ if (eina_iterator_next(itr, &data) && !eina_iterator_next(itr, &data2)) { Eolian_Function_Parameter *param = data; rettypet = eolian_parameter_type_get(param); var_as_ret = EINA_TRUE; } eina_iterator_free(itr); } params = eina_strbuf_new(); short_params = eina_strbuf_new(); _params_generate(foo, ftype, var_as_ret, params, short_params); if (eina_strbuf_length_get(params)) eina_strbuf_prepend_printf(params, ", "); if (eina_strbuf_length_get(short_params)) eina_strbuf_prepend_printf(short_params, ", "); fname = eolian_function_name_get(foo); if (fname) { flen = strlen(fname); if (flen >= strlen("destructor")) { if (impl_desc && (!strcmp(fname + flen - strlen("destructor"), "destructor"))) { eina_strbuf_append_printf (super_invok, " %s_%s(efl_super(obj, %s_%s)%s);\n", impl_env.lower_eo_prefix, eolian_function_name_get(foo), class_env.upper_eo_prefix, class_env.upper_classtype, eina_strbuf_string_get(short_params)); } } } const char *rettype = NULL; if (rettypet) rettype = eolian_type_c_type_get(rettypet); eina_strbuf_append_printf(buffer, "EOLIAN static %s\n%s(%sEo *obj, %s *pd%s%s)\n{\n%s\n}\n\n", !rettype?"void":rettype, func_name, eolian_function_object_is_const(foo)?"const ":"", !eina_strbuf_length_get(data_type_buf) ? "void" : eina_strbuf_string_get(data_type_buf), !eina_strbuf_length_get(data_type_buf) ? " EINA_UNUSED" : "", eina_strbuf_string_get(params), eina_strbuf_string_get(super_invok) ); if (rettype) eina_stringshare_del(rettype); end: eina_strbuf_free(short_params); eina_strbuf_free(params); eina_strbuf_free(super_invok); return EINA_TRUE; } Eina_Bool impl_source_generate(const Eolian_Class *class, Eina_Strbuf *buffer) { Eina_Bool ret = EINA_FALSE; Eina_Strbuf *data_type_buf = eina_strbuf_new(); Eina_Iterator *itr; const Eolian_Function *foo; Eina_Strbuf *begin = eina_strbuf_new(); char core_incl[PATH_MAX]; _class_env_create(class, NULL, &class_env); if (!_type_exists("EFL_BETA_API_SUPPORT", buffer)) { printf("Generation of EFL_BETA_API_SUPPORT\n"); eina_strbuf_append_printf(begin, "#define EFL_BETA_API_SUPPORT\n"); } if (!_type_exists("", buffer)) { printf("Generation of #include and \"%s.eo.h\"\n", class_env.lower_classname); eina_strbuf_append_printf(begin, "#include \n#include \"%s.eo.h\"\n\n", class_env.lower_classname); } /* Little calculation of the prefix of the data */ const char *data_type = eolian_class_data_type_get(class); if (data_type) { if (strcmp(data_type, "null")) eina_strbuf_append_printf(data_type_buf, "%s", data_type); } else eina_strbuf_append_printf(data_type_buf, "%s_Data", class_env.full_classname); /* Definition of the structure */ const char *data_type_str = eina_strbuf_string_get(data_type_buf); if (!_type_exists(data_type_str, buffer) && 0 != eina_strbuf_length_get(data_type_buf)) { printf("Generation of type %s\n", data_type_str); eina_strbuf_append_printf(begin, "typedef struct\n{\n\n} %s;\n\n", data_type_str); } if (eina_strbuf_length_get(begin)) eina_strbuf_prepend_printf(buffer, "%s", eina_strbuf_string_get(begin)); eina_strbuf_free(begin); itr = eolian_class_implements_get(class); if (itr) { Eolian_Implement *impl_desc; const char *names[] = { "", "getter ", "setter " }; EINA_ITERATOR_FOREACH(itr, impl_desc) { Eolian_Function_Type ftype; Eolian_Implement *idesc = (eolian_implement_class_get(impl_desc) == class) ? NULL : impl_desc; if (!(foo = eolian_implement_function_get(impl_desc, &ftype))) { const char *name = names[eolian_implement_is_prop_get(impl_desc) | (eolian_implement_is_prop_set(impl_desc) << 1)]; fprintf(stderr, "eolian: failed to generate implementation of '%s%s' - missing from class\n", name, eolian_implement_full_name_get(impl_desc)); goto end; } switch (ftype) { case EOLIAN_PROP_SET: case EOLIAN_PROP_GET: _prototype_generate(foo, ftype, data_type_buf, idesc, buffer); break; case EOLIAN_PROPERTY: _prototype_generate(foo, EOLIAN_PROP_SET, data_type_buf, idesc, buffer); _prototype_generate(foo, EOLIAN_PROP_GET, data_type_buf, idesc, buffer); break; default: _prototype_generate(foo, eolian_function_type_get(foo), data_type_buf, idesc, buffer); break; } } eina_iterator_free(itr); } if (eolian_class_ctor_enable_get(class)) { char func_name[100]; sprintf(func_name, "_%s_class_constructor", class_env.lower_classname); if (!_function_exists(func_name, buffer)) { printf("Generation of function %s\n", func_name); eina_strbuf_append_printf(buffer, "EOLIAN static void\n_%s_class_constructor(Efl_Class *klass)\n{\n\n}\n\n", class_env.lower_classname); } } if (eolian_class_dtor_enable_get(class)) { char func_name[100]; sprintf(func_name, "_%s_class_destructor", class_env.lower_classname); if (!_function_exists(func_name, buffer)) { printf("Generation of function %s\n", func_name); eina_strbuf_append_printf(buffer, "EOLIAN static void\n_%s_class_destructor(Efl_Class *klass)\n{\n\n}\n\n", class_env.lower_classname); } } printf("Removal of all inline instances of #include \"%s.eo.c\"\n", class_env.lower_classname); snprintf(core_incl, sizeof(core_incl), "\n#include \"%s.eo.c\"\n", class_env.lower_classname); eina_strbuf_replace_all(buffer, core_incl, "\n"); snprintf(core_incl, sizeof(core_incl), "\"%s.eo.c\"", class_env.lower_classname); printf("Generation of #include \"%s.eo.c\"\n", class_env.lower_classname); eina_strbuf_append_printf(buffer, "#include \"%s.eo.c\"\n", class_env.lower_classname); ret = EINA_TRUE; end: eina_strbuf_free(data_type_buf); return ret; }