eolian-cxx: Added namespaces and more (see below)

Implemented namespaces
Added eolian_wrappers.hh with C++ code wrapping Eolain API
Changed eolian_cxx program options. Now they're eolian_gen's
Added functions to safe_str.hh (safe_lower, safe_upper, normalize_spaces, path_base)
Added a mocked version of type_lookup.hh in advance. The full
version will come as soon as complex-types are added.

Made apply again by Daniel Kolesa, original implementation by Savio Sena.
This commit is contained in:
Daniel Kolesa 2014-06-30 19:32:52 +01:00
parent bd41cfe9ea
commit c05493b480
23 changed files with 927 additions and 569 deletions

View File

@ -27,6 +27,7 @@ TESTS += tests/edje_cxx/cxx_compile_test
tests_edje_cxx_cxx_compile_test_SOURCES = tests/edje_cxx/cxx_compile_test.cc
tests_edje_cxx_cxx_compile_test_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-I$(top_builddir)/src/lib/evas/canvas/ \
-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/edje_cxx\" \
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/edje_cxx\" \
@CHECK_CFLAGS@ @ECORE_CXX_CFLAGS@ @EINA_CXX_CFLAGS@ @EDJE_CXX_CFLAGS@ @EO_CXX_CFLAGS@ \

View File

@ -16,7 +16,7 @@ installed_eoliancxxgrammarheadersdir = $(includedir)/eolian-cxx-@VMAJ@/grammar/
dist_installed_eoliancxxgrammarheaders_DATA = \
lib/eolian_cxx/grammar/comment.hh \
lib/eolian_cxx/grammar/eo_class_constructors_generator.hh \
lib/eolian_cxx/grammar/eo_class_events.generator.hh \
lib/eolian_cxx/grammar/eo_class_events_generator.hh \
lib/eolian_cxx/grammar/eo_class_functions_generator.hh \
lib/eolian_cxx/grammar/eo_class_generator.hh \
lib/eolian_cxx/grammar/eo_header_generator.hh \
@ -26,15 +26,14 @@ lib/eolian_cxx/grammar/tab.hh
### Binary
bin_PROGRAMS += bin/eolian_cxx/eolian_cxx
bin_eolian_cxx_eolian_cxx_SOURCES = \
bin/eolian_cxx/comments.cc \
bin/eolian_cxx/comments.hh \
bin/eolian_cxx/convert_comments.cc \
bin/eolian_cxx/convert_comments.hh \
bin/eolian_cxx/convert.cc \
bin/eolian_cxx/convert.hh \
bin/eolian_cxx/eo_read.h \
bin/eolian_cxx/eolian_wrappers.hh \
bin/eolian_cxx/safe_strings.hh \
bin/eolian_cxx/eolian_cxx.cc

View File

@ -13,6 +13,6 @@ am__v_EOLCXX_0 = @echo " EOLCXX " $@;
SUFFIXES += .eo.hh
%.eo.hh: %.eo $(_EOLIAN_CXX_DEP)
$(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -I $< -o $@
$(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -o $@ $<
CLEANFILES += $(BUILT_SOURCES)

View File

@ -1,29 +0,0 @@
#ifndef EOLIAN_CXX_EOLIAN_CONVERT_COMMENTS_HH
#define EOLIAN_CXX_EOLIAN_CONVERT_COMMENTS_HH
#include <string>
extern "C"
{
#include <Eina.h>
#include <Eolian.h>
}
#include <Eolian_Cxx.hh>
namespace detail {
std::string eolian_class_comment(const Eolian_Class kls);
std::string eolian_constructor_comment(Eolian_Function constructor);
std::string eolian_function_comment(Eolian_Function function);
std::string eolian_property_getter_comment(Eolian_Function function);
std::string eolian_property_setter_comment(Eolian_Function function);
}
#endif // EOLIAN_CXX_EOLIAN_CONVERT_COMMENTS_HH

View File

@ -1,18 +1,26 @@
#include <vector>
#include <algorithm>
#include <cassert>
#include <cstddef>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eina.h>
#include <Eina.hh>
#include <Eolian.h>
#include "eo_types.hh"
#include "eo_validate.hh"
#include "safe_strings.hh"
#include "comments.hh"
#include "convert_comments.hh"
#include "eolian_wrappers.hh"
namespace eolian_cxx {
extern efl::eina::log_domain domain;
static std::string
_dedup_func_name(Eolian_Function func, const std::string &classn)
@ -23,145 +31,147 @@ _dedup_func_name(Eolian_Function func, const std::string &classn)
return ret;
}
static std::string
_resolve_param_type(Eolian_Function_Parameter id, bool is_get)
{
Eolian_Parameter_Dir dir;
Eolian_Type typet;
const char *type = NULL;
bool is_const;
std::string res;
eolian_parameter_information_get(id, &dir, &typet, NULL, NULL);
if (typet) type = eolian_type_c_type_get(typet);
is_const = eolian_parameter_const_attribute_get(id, is_get);
res = safe_str(type);
eina_stringshare_del(type);
assert(res != "");
if (is_const) res = std::string("const ") + res;
if (dir == EOLIAN_OUT_PARAM || dir == EOLIAN_INOUT_PARAM) res += "*";
return res;
}
static efl::eolian::parameters_container_type
_get_params(const Eina_List *eolian_params, bool is_get = false)
convert_eolian_parameters(Eina_List const* parameters,
Eolian_Function_Type func_type)
{
if (parameters == NULL) return {};
assert(func_type != EOLIAN_PROPERTY);
const Eina_List *it;
void *curr;
if (eolian_params == NULL)
{
return efl::eolian::parameters_container_type();
}
efl::eolian::parameters_container_type list;
EINA_LIST_FOREACH (eolian_params, it, curr)
EINA_LIST_FOREACH (parameters, it, curr)
{
Eolian_Function_Parameter id =
(static_cast<Eolian_Function_Parameter>(curr));
list.push_back({
_resolve_param_type(id, is_get),
safe_strshare(eolian_parameter_name_get(id))
});
list.push_back
({
parameter_type(id, func_type),
parameter_name(id)
});
}
return list;
}
static efl::eolian::parameters_container_type
convert_eolian_parameters(Eolian_Function const& function,
getter_t func_type)
{
return convert_eolian_parameters
(::eolian_parameters_list_get(function), func_type.value);
}
static efl::eolian::parameters_container_type
convert_eolian_parameters(Eina_List const* parameters,
getter_t func_type)
{
return convert_eolian_parameters(parameters, func_type.value);
}
static efl::eolian::parameters_container_type
convert_eolian_parameters(Eina_List const* parameters,
setter_t func_type)
{
return convert_eolian_parameters(parameters, func_type.value);
}
static efl::eolian::parameters_container_type
convert_eolian_parameters(Eolian_Function const& function)
{
assert(function_type(function) != EOLIAN_PROPERTY);
return convert_eolian_parameters
(::eolian_parameters_list_get(function), function_type(function));
}
static efl::eolian::functions_container_type
_get_properties(const Eolian_Class klass)
convert_eolian_property_to_functions(Eolian_Class const& klass)
{
efl::eolian::functions_container_type container;
std::string cxx_classname = eolian_class_name_get(klass);
std::transform(cxx_classname.begin(), cxx_classname.end(),
cxx_classname.begin(), ::tolower);
const Eina_List *properties;
properties = eolian_class_functions_list_get(klass, EOLIAN_PROPERTY);
std::string cxx_classname = safe_lower(class_name(klass));
const Eina_List *properties =
eolian_class_functions_list_get(klass, EOLIAN_PROPERTY); // XXX
const Eina_List *it;
void *curr;
std::string prefix(safe_str(eolian_class_eo_prefix_get(klass)));
std::string prefix(class_prefix(klass));
EINA_LIST_FOREACH (properties, it, curr)
{
Eolian_Function property = static_cast<Eolian_Function>(curr);
Eolian_Function_Type type = eolian_function_type_get(property);
std::string name = safe_str(eolian_function_name_get(property));
if (type == EOLIAN_PROP_GET || type == EOLIAN_PROPERTY)
Eolian_Function prop_ = static_cast<Eolian_Function>(curr);
if (property_is_getter(prop_))
{
const Eina_List *keys_ = eolian_property_keys_list_get(property);
efl::eolian::parameters_container_type params = _get_params
(eolian_parameters_list_get(property), true);
efl::eolian::eo_function getter;
getter.type = efl::eolian::eo_function::regular_;
getter.name = name + "_get";
getter.impl = _dedup_func_name(property, (prefix != "" ? prefix : cxx_classname)) + "_get";
Eolian_Type tp = eolian_function_return_type_get(property, EOLIAN_PROP_GET);
const char *tps = NULL;
if (tp) tps = eolian_type_c_type_get(tp);
std::string ret = safe_str(tps);
if (tps) eina_stringshare_del(tps);
if (ret == "") ret = "void";
efl::eolian::parameters_container_type params
= convert_eolian_parameters(prop_, eolian_cxx::getter);
// if the getter has a single parameter and void return
// we translate it to a getter with no parameters that
// returns its type.
if ((ret == "void") && params.size() == 1)
efl::eolian::eo_function get_;
get_.type = efl::eolian::eo_function::regular_;
get_.name = function_name(prop_) + "_get";
get_.impl = _dedup_func_name(prop_, prefix) + "_get";
efl::eolian::eolian_type_instance ret =
function_return_type(prop_, eolian_cxx::getter);
// if the getter has a single parameter and a void return
// it is transformed into a getter with no parameters
// that actually returns what would be the first argument.
if (params.size() == 1 && efl::eolian::type_is_void(ret))
{
getter.ret = params[0].type;
getter.params.clear();
get_.ret = params[0].type;
get_.params.clear();
}
else // otherwise just create the described getter
{
getter.ret = ret;
getter.params = params;
get_.ret = ret;
get_.params = params;
std::transform
(params.begin(), params.end(), getter.params.begin(),
(params.begin(), params.end(), get_.params.begin(),
[](efl::eolian::eo_parameter const& param)
{
efl::eolian::eolian_type getter_param_type =
type_to_native(param.type);
getter_param_type/*.native*/ += "*"; // XXX implement complex types
return efl::eolian::eo_parameter
{ param.type + "*", param.name };
{ { getter_param_type }, param.name };
});
}
if (eina_list_count(keys_) > 0)
efl::eolian::parameters_container_type keys =
convert_eolian_parameters(::eolian_property_keys_list_get(prop_),
eolian_cxx::getter);
if (!keys.empty())
{
efl::eolian::parameters_container_type keys = _get_params(keys_, true);
keys.reserve(keys.size() + getter.params.size());
keys.insert(keys.end(), getter.params.begin(), getter.params.end());
getter.params = keys;
keys.reserve(keys.size() + get_.params.size());
keys.insert(keys.end(), get_.params.begin(),
get_.params.end());
get_.params = keys;
}
getter.comment = detail::eolian_property_getter_comment(property);
container.push_back(getter);
get_.comment = convert_comments_function(prop_, eolian_cxx::getter);
container.push_back(get_);
}
if (type == EOLIAN_PROP_SET || type == EOLIAN_PROPERTY)
if (property_is_setter(prop_))
{
const Eina_List *keys_ = eolian_property_keys_list_get(property);
const Eina_List *args_ = eolian_parameters_list_get(property);
const Eina_List *keys_ = eolian_property_keys_list_get(prop_);
const Eina_List *args_ = eolian_parameters_list_get(prop_);
Eina_List *params_ = eina_list_merge(eina_list_clone(keys_), eina_list_clone(args_));
efl::eolian::parameters_container_type params = _get_params(params_);
efl::eolian::parameters_container_type params =
convert_eolian_parameters(params_, eolian_cxx::setter);
eina_list_free(params_);
efl::eolian::eo_function setter;
setter.type = efl::eolian::eo_function::regular_;
setter.name = name + "_set";
setter.impl = _dedup_func_name(property, (prefix != "" ? prefix : cxx_classname)) + "_set";
setter.params = params;
Eolian_Type tp = eolian_function_return_type_get(property, EOLIAN_PROP_SET);
const char *tps = NULL;
if (tp) tps = eolian_type_c_type_get(tp);
setter.ret = safe_str(tps);
if (tps) eina_stringshare_del(tps);
if (setter.ret == "") setter.ret = "void";
setter.comment = detail::eolian_property_setter_comment(property);
container.push_back(setter);
efl::eolian::eo_function set_;
set_.type = efl::eolian::eo_function::regular_;
set_.name = function_name(prop_) + "_set";
set_.impl = _dedup_func_name(prop_, prefix) + "_set";
set_.params = params;
set_.ret = function_return_type(prop_, eolian_cxx::setter);
set_.comment = convert_comments_function(prop_, eolian_cxx::setter);
container.push_back(set_);
}
}
return container;
}
namespace detail {
void
convert_eolian_inheritances(efl::eolian::eo_class& cls, const Eolian_Class klass)
convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
const Eina_List *inheritances = eolian_class_inherits_list_get(klass);
const Eina_List *inheritances =
::eolian_class_inherits_list_get(klass);
const Eina_List *it;
void *curr;
@ -173,29 +183,31 @@ convert_eolian_inheritances(efl::eolian::eo_class& cls, const Eolian_Class klass
}
else
{
std::string parent =
static_cast<const char*>(eina_list_data_get(inheritances));
std::transform(parent.begin(), parent.end(), parent.begin(), ::tolower);
// "eo_base" is the Eolian name for EO_BASE_CLASS.
cls.parent = (parent == "eo_base" || parent == "") ? "efl::eo::base" : parent;
}
const char *ptr = static_cast<const char*>
(eina_list_data_get(inheritances));
std::string parent = class_format_cxx(safe_lower(ptr));
// "eo_base" is the Eolian name for EO_BASE_CLASS.
cls.parent =
(parent == "eo_base" || parent == "eo::base" || parent == "")
? "efl::eo::base"
: parent;
}
inheritances = eina_list_next(inheritances);
EINA_LIST_FOREACH (inheritances, it, curr)
{
std::string extension = static_cast<const char*>(curr);
std::transform
(extension.begin(), extension.end(), extension.begin(), ::tolower);
cls.extensions.push_back(extension);
std::string extension = safe_lower(static_cast<const char*>(curr));
cls.extensions.push_back(class_format_cxx(extension));
}
}
void
convert_eolian_implements(efl::eolian::eo_class& cls, const Eolian_Class klass)
convert_eolian_implements(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
const Eina_List *it;
std::string prefix(safe_str(eolian_class_eo_prefix_get(klass)));
std::string prefix(class_prefix(klass));
void *impl_desc_;
EINA_LIST_FOREACH(eolian_class_implements_list_get(klass), it, impl_desc_)
{
Eolian_Implement impl_desc = static_cast<Eolian_Implement>(impl_desc_);
@ -207,43 +219,37 @@ convert_eolian_implements(efl::eolian::eo_class& cls, const Eolian_Class klass)
if (impl_type == EOLIAN_CTOR)
{
efl::eolian::eo_constructor constructor;
std::string parent = safe_str(eolian_class_full_name_get(impl_class));
if(parent == "Eo_Base") parent = "eo";
else std::transform(parent.begin(), parent.end(), parent.begin(), ::tolower);
constructor.name = parent + "_" + safe_str(eolian_function_name_get(impl_func));
constructor.params = _get_params
(eolian_parameters_list_get(impl_func));
constructor.comment = detail::eolian_constructor_comment
(impl_func);
std::string parent = safe_lower(eolian_class_full_name_get(impl_class));
if (parent == "eo_base" || parent == "eo.base") parent = "eo";
constructor.name = parent + "_" + function_name(impl_func);
constructor.params = convert_eolian_parameters(impl_func);
constructor.comment = convert_comments_function(impl_func, eolian_cxx::ctor);
cls.constructors.push_back(constructor);
}
}
}
void
convert_eolian_constructors(efl::eolian::eo_class& cls, const Eolian_Class klass)
convert_eolian_constructors(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
const Eina_List *it;
void *curr;
std::string prefix(safe_str(eolian_class_eo_prefix_get(klass)));
std::string prefix(class_prefix(klass));
const Eina_List *constructors =
eolian_class_functions_list_get(klass, EOLIAN_CTOR);
EINA_LIST_FOREACH (constructors, it, curr)
{
Eolian_Function eolian_constructor = static_cast<Eolian_Function>(curr);
Eolian_Function eo_constructor = static_cast<Eolian_Function>(curr);
efl::eolian::eo_constructor constructor;
constructor.name = _dedup_func_name(eolian_constructor,
(prefix != "" ? prefix : cls.name));
constructor.params = _get_params
(eolian_parameters_list_get(eolian_constructor));
constructor.comment = detail::eolian_constructor_comment
(eolian_constructor);
constructor.name = _dedup_func_name(eo_constructor, prefix);
constructor.params = convert_eolian_parameters(eo_constructor);
constructor.comment = convert_comments_function(eo_constructor, eolian_cxx::ctor);
cls.constructors.push_back(constructor);
}
}
void
convert_eolian_functions(efl::eolian::eo_class& cls, const Eolian_Class klass)
convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
const Eina_List *it;
void *curr;
@ -254,60 +260,60 @@ convert_eolian_functions(efl::eolian::eo_class& cls, const Eolian_Class klass)
{
efl::eolian::eo_function function;
Eolian_Function eolian_function = static_cast<Eolian_Function>(curr);
std::string prefix(safe_str(eolian_class_eo_prefix_get(klass)));
std::string prefix(class_prefix(klass));
// XXX Eolian only provides regular methods so far
function.type = efl::eolian::eo_function::regular_;
function.name = safe_str(eolian_function_name_get(eolian_function));
function.impl = _dedup_func_name(eolian_function, (prefix != "" ? prefix : cls.name));
Eolian_Type tp = eolian_function_return_type_get(eolian_function, EOLIAN_METHOD);
const char *tps = NULL;
if (tp) tps = eolian_type_c_type_get(tp);
function.ret = safe_str(tps);
if (tps) eina_stringshare_del(tps);
if(function.ret == "") function.ret = "void";
function.params = _get_params(eolian_parameters_list_get(eolian_function));
function.comment = detail::eolian_function_comment(eolian_function);
function.name = function_name(eolian_function);
function.impl = _dedup_func_name(eolian_function, prefix);
function.ret = function_return_type(eolian_function);
function.params = convert_eolian_parameters(eolian_function);
function.comment = convert_comments_function(eolian_function, eolian_cxx::method);
cls.functions.push_back(function);
}
}
void
convert_eolian_properties(efl::eolian::eo_class& cls, const Eolian_Class klass)
convert_eolian_properties(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
efl::eolian::functions_container_type properties = _get_properties(klass);
cls.functions.insert(cls.functions.end(), properties.begin(), properties.end());
efl::eolian::functions_container_type properties
= convert_eolian_property_to_functions(klass);
cls.functions.insert
(cls.functions.end(), properties.begin(), properties.end());
}
} // namespace detail {
void
convert_eolian_events(efl::eolian::eo_class& cls, Eolian_Class const& klass)
{
efl::eolian::events_container_type events = event_list(klass);
cls.events.reserve(cls.events.size() + events.size());
cls.events.insert(cls.events.end(), events.begin(), events.end());
}
efl::eolian::eo_class
_cxx_new(const Eolian_Class klass)
convert_eolian_class_new(Eolian_Class const& klass)
{
using namespace efl::eolian;
eo_class cls;
Eolian_Class_Type cls_type = ::eolian_class_type_get(klass);
if (cls_type == EOLIAN_CLASS_REGULAR) cls.type = eo_class::regular_;
else if (cls_type == EOLIAN_CLASS_ABSTRACT) cls.type = eo_class::regular_noninst_;
else if (cls_type == EOLIAN_CLASS_MIXIN) cls.type = eo_class::mixin_;
else if (cls_type == EOLIAN_CLASS_INTERFACE) cls.type = eo_class::interface_;
else { assert(false); }
cls.name = eolian_class_name_get(klass);
cls.eo_name = cls.name + "_CLASS";
cls.comment = detail::eolian_class_comment(klass);
std::transform(cls.name.begin(), cls.name.end(), cls.name.begin(), ::tolower);
std::transform(cls.eo_name.begin(), cls.eo_name.end(), cls.eo_name.begin(), ::toupper);
efl::eolian::eo_class cls;
cls.type = class_type(klass);
cls.name = safe_lower(class_name(klass));
cls.name_space = safe_lower(class_namespace_full(klass));
cls.eo_name = class_eo_name(klass);
cls.comment = convert_comments_class(klass);
return cls;
}
efl::eolian::eo_class
c_to_cxx(const char *classname)
convert_eolian_class(const Eolian_Class klass)
{
Eolian_Class klass = eolian_class_find_by_name(classname);
efl::eolian::eo_class cls(_cxx_new(klass));
detail::convert_eolian_inheritances(cls, klass);
detail::convert_eolian_implements(cls, klass);
detail::convert_eolian_constructors(cls, klass);
detail::convert_eolian_functions(cls, klass);
detail::convert_eolian_properties(cls, klass);
assert(klass != NULL);
efl::eolian::eo_class cls(eolian_cxx::convert_eolian_class_new(klass));
eolian_cxx::convert_eolian_inheritances(cls, klass);
eolian_cxx::convert_eolian_implements(cls, klass);
eolian_cxx::convert_eolian_constructors(cls, klass);
eolian_cxx::convert_eolian_functions(cls, klass);
eolian_cxx::convert_eolian_properties(cls, klass);
eolian_cxx::convert_eolian_events(cls, klass);
efl::eolian::eo_class_validate(cls);
return cls;
}
} // namespace eolian_cxx {

View File

@ -4,6 +4,16 @@
#include "eo_types.hh"
efl::eolian::eo_class c_to_cxx(const char *classname);
namespace eolian_cxx
{
///
/// @brief Retrieve a efl::eolian::eo_class from an Eolian_Class name.
/// @param cls The Eolian class.
/// @return The @p eo_class describing @p classname.
///
efl::eolian::eo_class convert_eolian_class(Eolian_Class klass);
}
#endif // EOLIAN_CXX_EOLIAN_CONVERT_CLASSES_HH

View File

@ -1,7 +1,9 @@
#include "comments.hh"
#include "convert_comments.hh"
#include "safe_strings.hh"
namespace eolian_cxx {
static std::string
_comment_parameter(Eolian_Function_Parameter param)
{
@ -74,41 +76,20 @@ _comment_return(Eolian_Function function,
return doc;
}
namespace detail {
std::string
eolian_class_comment(const Eolian_Class kls)
convert_comments_class(Eolian_Class const& klass)
{
return safe_str(eolian_class_description_get(kls));
return safe_str(eolian_class_description_get(klass));
}
std::string
eolian_constructor_comment(Eolian_Function constructor)
{
return _comment_brief_and_params(constructor);
}
std::string eolian_function_comment(Eolian_Function function)
convert_comments_function(Eolian_Function const& function,
Eolian_Function_Type func_type)
{
std::string doc = _comment_brief_and_params(function);
doc += _comment_return(function, EOLIAN_METHOD);
if (func_type != eolian_cxx::ctor.value)
doc += _comment_return(function, func_type);
return doc;
}
std::string eolian_property_getter_comment(Eolian_Function property)
{
std::string doc = _comment_brief_and_params
(property, EOLIAN_COMMENT_GET);
doc += _comment_return(property, EOLIAN_PROP_GET);
return doc;
}
std::string eolian_property_setter_comment(Eolian_Function property)
{
std::string doc = _comment_brief_and_params
(property, EOLIAN_COMMENT_SET);
doc += _comment_return(property, EOLIAN_PROP_SET);
return doc;
}
} // namespace detail
} // namespace eolian_cxx

View File

@ -0,0 +1,45 @@
#ifndef EOLIAN_CXX_CONVERT_COMMENTS_HH
#define EOLIAN_CXX_CONVERT_COMMENTS_HH
#include <string>
#include <Eolian.h>
#include <Eolian_Cxx.hh>
#include "eolian_wrappers.hh"
namespace eolian_cxx {
std::string convert_comments_class(Eolian_Class const& kls);
std::string convert_comments_function(Eolian_Function const& function,
Eolian_Function_Type func_type);
inline std::string
convert_comments_function(Eolian_Function const& constructor_, ctor_t func_type_)
{
return convert_comments_function(constructor_, func_type_.value);
}
inline std::string
convert_comments_function(Eolian_Function const& function_, method_t func_type_)
{
return convert_comments_function(function_, func_type_.value);
}
inline std::string
convert_comments_function(Eolian_Function const& property_, getter_t func_type_)
{
return convert_comments_function(property_, func_type_.value);
}
inline std::string
convert_comments_function(Eolian_Function const& property_, setter_t func_type_)
{
return convert_comments_function(property_, func_type_.value);
}
}
#endif // EOLIAN_CXX_CONVERT_COMMENTS_HH

View File

@ -1,62 +0,0 @@
#ifndef EOLIAN_CXX_EOLIAN_HELPER_H
#define EOLIAN_CXX_EOLIAN_HELPER_H
#include <Eina.h>
#include <Eolian.h>
#include <assert.h>
#define EO_SUFFIX ".eo"
inline Eina_List*
_list_dir(const char *dir, const char *suffix, Eina_Bool recurse)
{
Eina_List *files = NULL;
Eina_Iterator *ls;
Eina_File_Direct_Info *info;
ls = eina_file_direct_ls(dir);
if(ls == NULL) return NULL;
EINA_ITERATOR_FOREACH (ls, info)
{
assert(info && info->path);
if (info->type == EINA_FILE_DIR && recurse)
{
files = eina_list_merge
(files, _list_dir(info->path, suffix, recurse));
}
else if (eina_str_has_suffix(&info->path[info->name_start], suffix))
{
files = eina_list_append(files, strdup(info->path));
}
}
eina_iterator_free(ls);
return eina_list_sort
(files, eina_list_count(files), EINA_COMPARE_CB(strcoll));
}
inline Eina_List*
eolian_read_from_fs(const char *path)
{
if (eina_str_has_suffix(path, EO_SUFFIX))
{
if(!eolian_eo_file_parse(path))
{
/* XXX: fprintf? */
fprintf(stderr, "Couldn't load input file: %s\n", path);
return NULL;
}
}
else
{
if (!eolian_directory_scan(path))
{
/* XXX: fprintf? */
fprintf(stderr, "Error scanning directory: %s\n", path);
}
}
return eina_list_clone(eolian_class_names_list_get());
}
#endif /* EOLIAN_CXX_EOLIAN_HELPER_H */

View File

@ -13,42 +13,40 @@
#include <type_traits>
#include <cassert>
extern "C"
{
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eina.h>
#include <Eolian.h>
}
#include <Eina.hh>
#include <Eolian_Cxx.hh>
#include "eo_read.h"
#include "convert.hh"
#include "type_lookup.hh"
#include "convert.hh"
#include "eolian_wrappers.hh"
#include "safe_strings.hh"
namespace {
namespace eolian_cxx {
// Program options.
/// Program options.
struct options_type
{
std::vector<std::string> in_srcs;
std::vector<std::string> include_dirs;
std::string in_file;
std::string out_file;
std::string out_dir;
std::string classname;
std::string name_space;
bool recurse;
bool generate_all;
options_type()
: in_srcs()
, out_file("")
, out_dir("")
, classname("")
, name_space("")
: include_dirs()
, in_file()
, out_file()
, out_dir()
, classname()
, recurse(false)
, generate_all(false)
{}
@ -56,112 +54,80 @@ struct options_type
efl::eina::log_domain domain("eolian_cxx");
}
static void
_opt_error(std::string message)
static bool
opts_check(eolian_cxx::options_type const& opts)
{
EINA_CXX_DOM_LOG_ERR(::domain) << message << std::endl;
exit(EXIT_FAILURE);
}
static void
_assert_not_dup(std::string option, std::string value)
{
if (value != "")
if (!opts.generate_all && opts.in_file.empty())
{
_opt_error("Option -" + option + " already set (" + value + ")");
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Nothing to generate?" << std::endl;
}
}
// Try to guess classname from input filenames.
// Precondition: Input sources must be loaded into Eolian Database
// otherwise we can't infer the classname from the .eo files.
// Precondition: Input options must have opts.classname == "".
static std::string
_guess_classname_from_sources(::options_type& opts)
{
for (auto filename : opts.in_srcs)
else if (opts.generate_all && !opts.in_file.empty())
{
if (Eolian_Class klass = eolian_class_find_by_file(filename.c_str()))
{
return eolian_class_full_name_get(klass);
}
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Didn't expect to receive input files (" << opts.in_file
<< ") with parameter -a."
<< std::endl;
}
return "";
}
std::pair<std::string, std::string> get_filename_info(std::string path)
{
const size_t last = path.rfind("lib/");
if (last != std::string::npos)
{
path.erase(0, last+4);
std::string::iterator slash
= std::find(path.begin(), path.end(), '/');
if(slash != path.end())
{
std::string namespace_ (path.begin(), slash);
std::string filename (slash+1, path.end());
return {filename, namespace_};
}
}
std::string::reverse_iterator slash
= std::find(path.rbegin(), path.rend(), '/');
return {std::string(slash.base(), path.end()), std::string()};
else if (opts.generate_all && !opts.out_file.empty())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Can't use -a and -o together." << std::endl;
}
else if (opts.generate_all && opts.include_dirs.empty())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Option -a requires at least one include directory (-I)."
<< std::endl;
}
else
{
return true; // valid.
}
return false;
}
efl::eolian::eo_generator_options
_resolve_includes(std::string const& classname)
generator_options(const Eolian_Class klass)
{
efl::eolian::eo_generator_options gen_opts;
std::string cls_name = classname;
Eolian_Class klass = eolian_class_find_by_name(classname.c_str());
std::transform(cls_name.begin(), cls_name.end(), cls_name.begin(), ::tolower);
std::string eo_file = safe_str(eolian_class_file_get(klass));
gen_opts.c_headers.push_back(get_filename_info(eo_file).first + ".h");
gen_opts.c_headers.push_back(class_base_file(klass) + ".h");
void *cur = NULL;
const Eina_List *itr, *inheritances = eolian_class_inherits_list_get(klass);
EINA_LIST_FOREACH(inheritances, itr, cur)
{
Eolian_Class ext = eolian_class_find_by_name(static_cast<const char*>(cur));
std::string eo_parent_file = safe_str(eolian_class_file_get(ext));
std::string eo_parent_file = class_base_file(ext);
if (!eo_parent_file.empty())
{
std::string filename, namespace_;
std::tie(filename, namespace_) = get_filename_info(eo_parent_file);
// we have our own eo_base.hh
std::string eo_base_eo = "eo_base.eo";
if (filename.length() < eo_base_eo.length() ||
if (eo_parent_file.length() < eo_base_eo.length() ||
!std::equal(eo_base_eo.begin(), eo_base_eo.end(),
filename.end() - eo_base_eo.length()))
eo_parent_file.end() - eo_base_eo.length()))
{
gen_opts.cxx_headers.push_back(filename + ".hh");
gen_opts.cxx_headers.push_back(eo_parent_file + ".hh");
}
}
else
{
EINA_CXX_DOM_LOG_ERR(::domain)
<< "Couldn't find source file for class '" << ext << "'";
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Couldn't find source file for class '" << ext << "'"
<< std::endl;
}
}
return gen_opts;
}
static void
_generate(const std::string classname, ::options_type const& opts)
static bool
generate(const Eolian_Class klass, eolian_cxx::options_type const& opts)
{
efl::eolian::eo_class cls = ::c_to_cxx(classname.c_str());
cls.name_space = opts.name_space;
efl::eolian::eo_class_validate(cls);
efl::eolian::eo_generator_options gen_opts = _resolve_includes(classname);
std::string outname = (opts.out_file == "") ? (cls.name + ".eo.hh") : opts.out_file;
if (opts.out_dir != "")
assert(!!klass);
efl::eolian::eo_class cls = eolian_cxx::convert_eolian_class(klass);
efl::eolian::eo_generator_options gen_opts = generator_options(klass);
std::string outname = opts.out_file.empty() ? (class_base_file(klass) + ".hh") : opts.out_file;
if (!opts.out_dir.empty())
{
outname = opts.out_dir + "/" + outname;
}
@ -173,33 +139,90 @@ _generate(const std::string classname, ::options_type const& opts)
{
std::ofstream outfile;
outfile.open(outname);
assert(outfile.good());
efl::eolian::generate(outfile, cls, gen_opts);
outfile.close();
if (outfile.good())
{
efl::eolian::generate(outfile, cls, gen_opts);
outfile.close();
}
else
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Can't open output file: " << outname << std::endl;
return false;
}
}
return true;
}
static void
_run(options_type const& opts)
run(options_type const& opts)
{
if (opts.classname != "")
Eolian_Class klass = NULL;
if (!opts.classname.empty())
klass = class_from_name(opts.classname);
else if (!opts.in_file.empty())
klass = class_from_file(opts.in_file);
if (klass)
{
_generate(opts.classname.c_str(), opts);
if (!generate(klass, opts))
goto err;
}
else
{
efl::eina::range_ptr_list<const char* const>
classes(eolian_class_names_list_get());
for (auto cls : classes)
auto classes = class_list_all();
for (const Eolian_Class c : classes)
{
if (opts.classname == "" || opts.classname == cls)
if (!generate(c, opts))
{
_generate(cls, opts);
klass = c;
goto err;
}
}
}
return;
err:
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Error generating: " << class_name(klass)
<< std::endl;
std::abort();
}
static void
database_load(options_type const& opts)
{
for (auto src : opts.include_dirs)
{
if (!::eolian_directory_scan(src.c_str()))
{
EINA_CXX_DOM_LOG_WARN(eolian_cxx::domain)
<< "Couldn't load eolian from '" << src << "'.";
}
}
if (!::eolian_all_eot_files_parse())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Eolian failed parsing eot files";
std::abort();
}
if (!opts.in_file.empty())
{
if (!::eolian_eo_file_parse(opts.in_file.c_str()))
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Failed parsing: " << opts.in_file << ".";
std::abort();
}
}
if (!::eolian_all_eo_files_parse())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Eolian failed parsing input files";
std::abort();
}
}
} // namespace eolian_cxx {
static void
_print_version()
{
@ -208,78 +231,13 @@ _print_version()
<< PACKAGE_VERSION << ")" << std::endl;
}
static void
_validate_options(::options_type const& opts)
{
if (opts.in_srcs.size() == 0)
{
_opt_error("You must provide at least one input source (-I). "
"Either an .eo file or a directory of .eo files.");
}
else if (opts.out_file != "" && opts.generate_all)
{
_opt_error("Options -a and -o can't be used together.");
}
else if (!opts.generate_all && opts.classname == "")
{
_opt_error("Neither -a nor -c provided. "
"Don't know what to generate.");
}
}
static void
_resolve_classname(options_type& opts)
{
if (opts.classname == "")
{
std::string cls = _guess_classname_from_sources(opts);
opts.classname = cls;
}
if (opts.classname == "" && opts.out_file != "")
{
EINA_CXX_DOM_LOG_ERR(::domain)
<< "Unknown output class for " << opts.out_file
<< " : Missing '-c' option?";
std::abort();
}
}
static void
_scan_directories(options_type const& opts)
{
for (auto src : opts.in_srcs)
{
if (eina_str_has_suffix(src.c_str(), EO_SUFFIX)) continue;
eolian_read_from_fs(src.c_str());
}
}
static void
_load_eot()
{
eolian_all_eot_files_parse();
}
static void
_load_classes(options_type const& opts)
{
for (auto src : opts.in_srcs)
{
if (!eina_str_has_suffix(src.c_str(), EO_SUFFIX)) continue;
if ( eolian_read_from_fs(src.c_str()) == NULL)
{
EINA_CXX_DOM_LOG_WARN(::domain)
<< "Couldn't load eolian file: " << src;
}
}
}
static void
_usage(const char *progname)
{
std::cerr
<< progname
<< " [options]" << std::endl
<< " [options] [file.eo]" << std::endl
<< " A single input file must be provided (unless -a is specified)." << std::endl
<< "Options:" << std::endl
<< " -a, --all Generate bindings for all Eo classes." << std::endl
<< " -c, --class <name> The Eo class name to generate code for." << std::endl
@ -293,10 +251,20 @@ _usage(const char *progname)
exit(EXIT_FAILURE);
}
static ::options_type
_read_options(int argc, char **argv)
static void
_assert_not_dup(std::string option, std::string value)
{
::options_type opts;
if (value != "")
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) <<
"Option -" + option + " already set (" + value + ")";
}
}
static eolian_cxx::options_type
opts_get(int argc, char **argv)
{
eolian_cxx::options_type opts;
const struct option long_options[] =
{
@ -304,21 +272,20 @@ _read_options(int argc, char **argv)
{ "out-dir", required_argument, 0, 'D' },
{ "out-file", required_argument, 0, 'o' },
{ "class", required_argument, 0, 'c' },
{ "namespace", required_argument, 0, 'n' },
{ "all", no_argument, 0, 'a' },
{ "recurse", no_argument, 0, 'r' },
{ "version", no_argument, 0, 'v' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
const char* options = "I:D:o:c:n:arvh";
const char* options = "I:D:o:c:arvh";
int c, idx;
while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1)
{
if (c == 'I')
{
opts.in_srcs.push_back(optarg);
opts.include_dirs.push_back(optarg);
}
else if (c == 'D')
{
@ -335,11 +302,6 @@ _read_options(int argc, char **argv)
_assert_not_dup("c", opts.classname);
opts.classname = optarg;
}
else if (c == 'n')
{
_assert_not_dup("n", opts.name_space);
opts.name_space = optarg;
}
else if (c == 'a')
{
opts.generate_all = true;
@ -358,6 +320,17 @@ _read_options(int argc, char **argv)
if (argc == 2) exit(EXIT_SUCCESS);
}
}
if (optind == argc-1)
{
opts.in_file = argv[optind];
}
if (!eolian_cxx::opts_check(opts))
{
_usage(argv[0]);
std::abort();
}
return opts;
}
@ -365,15 +338,8 @@ int main(int argc, char **argv)
{
efl::eina::eina_init eina_init;
efl::eolian::eolian_init eolian_init;
#if DEBUG
domain.set_level(efl::eina::log_level::debug);
#endif
options_type opts = _read_options(argc, argv);
_scan_directories(opts);
_load_eot();
_load_classes(opts);
_resolve_classname(opts);
_validate_options(opts);
_run(opts);
eolian_cxx::options_type opts = opts_get(argc, argv);
eolian_cxx::database_load(opts);
eolian_cxx::run(opts);
return 0;
}

View File

@ -0,0 +1,318 @@
#ifndef EOLIAN_CXX_EOLIAN_WRAPPERS_HH
#define EOLIAN_CXX_EOLIAN_WRAPPERS_HH
#include <cassert>
#include <Eolian.h>
#include "eo_types.hh"
#include "safe_strings.hh"
#include "type_lookup.hh"
namespace eolian_cxx
{
struct property_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROPERTY; };
property_t const property = {};
struct setter_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROP_SET; };
setter_t const setter = {};
struct getter_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROP_GET; };
getter_t const getter = {};
struct method_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_METHOD; };
method_t const method = {};
struct ctor_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_CTOR; };
ctor_t const ctor = {};
inline Eolian_Class
class_from_file(std::string const& file)
{
return ::eolian_class_find_by_file(file.c_str());
}
inline std::string
class_file(Eolian_Class const& klass)
{
return safe_str(::eolian_class_file_get(klass));
}
inline std::string
class_base_file(Eolian_Class const& klass)
{
return path_base(safe_str(::eolian_class_file_get(klass)));
}
inline std::string
class_name(Eolian_Class const& klass)
{
return safe_str(::eolian_class_name_get(klass));
}
inline std::string
class_full_name(Eolian_Class const& klass)
{
return safe_str(::eolian_class_full_name_get(klass));
}
inline Eolian_Class
class_from_name(std::string const& classname)
{
return ::eolian_class_find_by_name(classname.c_str());
}
inline std::string
class_eo_name(Eolian_Class const& klass)
{
std::string s = class_full_name(klass) + "_CLASS";
std::transform(s.begin(), s.end(), s.begin(),
[](int c)
{
return c == '.' ? '_' : c ;
});
return safe_upper(s);
}
inline std::string
class_format_cxx(std::string const& fullname)
{
std::string s = fullname;
auto found = s.find(".");
while (found != std::string::npos)
{
s.replace(found, 1, "::");
found = s.find(".");
}
return s;
}
inline std::string
class_prefix(Eolian_Class const& klass)
{
std::string prefix = safe_lower(::eolian_class_eo_prefix_get(klass));
if (prefix.empty())
prefix = safe_lower(class_name(klass));
assert(!prefix.empty());
return prefix;
}
inline efl::eolian::eo_class::eo_class_type
class_type(Eolian_Class const& klass)
{
assert(klass != NULL);
efl::eolian::eo_class::eo_class_type type;
Eolian_Class_Type cls_type = ::eolian_class_type_get(klass);
if (cls_type == EOLIAN_CLASS_REGULAR)
type = efl::eolian::eo_class::regular_;
else if (cls_type == EOLIAN_CLASS_ABSTRACT)
type = efl::eolian::eo_class::regular_noninst_;
else if (cls_type == EOLIAN_CLASS_MIXIN)
type = efl::eolian::eo_class::mixin_;
else if (cls_type == EOLIAN_CLASS_INTERFACE)
type = efl::eolian::eo_class::interface_;
else assert(false);
return type;
}
inline std::string
class_namespace_full(Eolian_Class const& klass)
{
std::string s;
const Eina_List* list =
::eolian_class_namespaces_list_get(klass), *itr;
void* name;
EINA_LIST_FOREACH(list, itr, name)
{
s += static_cast<const char*>(name);
s += "::";
}
if (s.size() >= 2)
s = s.substr(0, s.size()-2);
return s;
}
inline efl::eina::range_ptr_list<const Eolian_Class>
class_list_all()
{
return ::eolian_class_names_list_get();
}
inline std::string
function_name(Eolian_Function const& function)
{
return safe_str(::eolian_function_name_get(function));
}
inline Eolian_Function_Type
function_type(Eolian_Function const& function)
{
return ::eolian_function_type_get(function);
}
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& function, Eolian_Function_Type func_type = method_t::value)
{
return type_lookup
(::eolian_function_return_type_get(function, func_type));
}
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& function, setter_t func_type)
{
return function_return_type(function, func_type.value);
}
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& function, getter_t func_type)
{
return function_return_type(function, func_type.value);
}
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& function, method_t func_type)
{
return function_return_type(function, func_type.value);
}
inline efl::eolian::eolian_type_instance
function_return_type(Eolian_Function const& function, ctor_t func_type)
{
return function_return_type(function, func_type.value);
}
inline bool
property_is_getter(Eolian_Function_Type func_type)
{
return func_type == property_t::value || func_type == getter_t::value;
}
inline bool
property_is_getter(Eolian_Function const& function)
{
return property_is_getter(function_type(function));
}
inline bool
property_is_setter(Eolian_Function_Type func_type)
{
return func_type == property_t::value || func_type == setter_t::value;
}
inline bool
property_is_setter(Eolian_Function const& function)
{
return property_is_setter(function_type(function));
}
inline std::string
parameter_name(Eolian_Function_Parameter const& parameter)
{
return safe_strshare(::eolian_parameter_name_get(parameter));
}
inline bool
parameter_is_out(Eolian_Function_Parameter const& parameter)
{
Eolian_Parameter_Dir direction;
::eolian_parameter_information_get(parameter, &direction, NULL, NULL, NULL);
return direction == EOLIAN_OUT_PARAM || direction == EOLIAN_INOUT_PARAM;
}
inline bool
parameter_is_const(Eolian_Function_Parameter const& parameter,
Eolian_Function_Type func_type)
{
return ::eolian_parameter_const_attribute_get
(parameter, property_is_getter(func_type));
}
inline bool
parameter_is_const(Eolian_Function_Parameter const& parameter,
getter_t func_type)
{
return ::eolian_parameter_const_attribute_get
(parameter, property_is_getter(func_type.value));
}
inline bool
parameter_is_const(Eolian_Function_Parameter const& parameter,
setter_t func_type)
{
return ::eolian_parameter_const_attribute_get
(parameter, property_is_getter(func_type.value));
}
inline bool
parameter_is_const(Eolian_Function_Parameter const& parameter,
Eolian_Function const& function)
{
assert(function_type(function) != EOLIAN_PROPERTY);
return ::eolian_parameter_const_attribute_get
(parameter, property_is_getter(function));
}
inline efl::eolian::eolian_type_instance
parameter_type(Eolian_Function_Parameter const& parameter,
Eolian_Function_Type func_type = method_t::value)
{
efl::eolian::eolian_type_instance type
(type_lookup(::eolian_parameter_type_get(parameter)));
assert(!type.empty());
// XXX implement complex types.
if (parameter_is_out(parameter))
type = { type_to_native(type) + "*" };
if (parameter_is_const(parameter, func_type))
type.insert(0, "const ");
return type;
}
inline efl::eolian::eolian_type_instance
parameter_type(Eolian_Function_Parameter const& parameter, getter_t func_type)
{
return parameter_type(parameter, func_type.value);
}
inline efl::eolian::eolian_type_instance
parameter_type(Eolian_Function_Parameter const& parameter, setter_t func_type)
{
return parameter_type(parameter, func_type.value);
}
inline efl::eolian::eo_event
event_create(Eolian_Class const& klass, const Eolian_Event event_)
{
efl::eolian::eo_event event;
const char *name, *type, *comment;
if(::eolian_class_event_information_get(event_, &name, &type, &comment))
{
std::string name_ = safe_str(name);
std::transform(name_.begin(), name_.end(), name_.begin(),
[](int c) { return c != ',' ? c : '_'; });
event.name = normalize_spaces(name_);
event.eo_name = safe_upper(class_name(klass) + "_EVENT_" + event.name);
event.comment = safe_str(comment);
}
return event;
}
inline efl::eolian::events_container_type
event_list(Eolian_Class const& klass)
{
efl::eolian::events_container_type events;
const Eina_List* list = eolian_class_events_list_get(klass);
unsigned int length = eina_list_count(list);
for (unsigned int i = 0; i < length; ++i)
{
Eolian_Event e = static_cast<Eolian_Event>(eina_list_nth(list, i));
events.push_back(event_create(klass, e));
}
return events;
}
}
#endif // EOLIAN_CXX_EOLIAN_WRAPPERS_HH

View File

@ -3,20 +3,26 @@
#define EOLIAN_CXX_BIN_SAFE_STRINGS_HH
#include <string>
#include <algorithm>
#include <cstddef>
#include <cctype>
#include <iterator>
extern "C"
{
#include <Eina.h>
}
/// @brief Safely convert an const char* to std::string.
/// @brief Safely convert const char* to std::string.
///
inline std::string
safe_str(const char* str)
{
return (str != NULL) ? str : "";
}
/// @brief Safely convert an Eina_Stringshare to std::string.
/// @brief Safely convert Eina_Stringshare to std::string.
///
inline std::string
safe_strshare(Eina_Stringshare* strsh)
{
@ -25,4 +31,76 @@ safe_strshare(Eina_Stringshare* strsh)
return ret;
}
/// @brief Get a lower-case copy of string.
///
inline std::string
safe_lower(std::string const& s)
{
std::string res;
res.resize(s.size());
std::transform(s.begin(), s.end(), res.begin(), ::tolower);
return res;
}
/// @brief Get a lower-case copy of string.
///
inline std::string
safe_lower(const char *s)
{
return safe_lower(safe_str(s));
}
/// @brief Get a upper-case copy of string.
///
inline std::string
safe_upper(std::string const& s)
{
std::string res;
res.resize(s.size());
std::transform(s.begin(), s.end(), res.begin(), ::toupper);
return res;
}
/// @brief Get a upper-case copy of string.
///
inline std::string
safe_upper(const char* s)
{
return safe_upper(safe_str(s));
}
/// @brief Trim both ends of the string and replaces any
/// subsequence of contiguous spaces with a single space.
///
inline std::string
normalize_spaces(std::string const& s)
{
std::ostringstream os;
bool prev_is_space = true;
std::remove_copy_if
(s.begin(), s.end(),
std::ostream_iterator<char>(os),
[&prev_is_space] (char c)
{
bool r = ::isspace(c);
if (r && prev_is_space)
return true;
prev_is_space = r;
return false;
});
std::string r = os.str();
if (!r.empty() && ::isspace(r.back()))
r.erase(r.end()-1, r.end());
return r;
}
inline std::string
path_base(std::string path)
{
std::string::reverse_iterator
slash = std::find(path.rbegin(), path.rend(), '/');
return std::string(slash.base(), path.end());
}
#endif // EOLIAN_CXX_BIN_SAFE_STRINGS_HH

View File

@ -0,0 +1,37 @@
#ifndef EOLIAN_CXX_TYPE_LOOKUP_HH
#define EOLIAN_CXX_TYPE_LOOKUP_HH
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cctype>
#include <iterator>
#include <cassert>
#include <cstddef>
#include <Eolian.h>
#include <Eina.hh>
#include "eo_types.hh"
#include "safe_strings.hh"
namespace eolian_cxx {
inline std::string
type_lookup(Eolian_Type type)
{
if (type == NULL)
return "void";
// XXX add complex types implementation.
const char *tps = eolian_type_c_type_get(type);
std::string ret = normalize_spaces(safe_str(tps));
::eina_stringshare_del(tps);
return ret;
}
} // namespace eolian_cxx {
#endif // EOLIAN_CXX_TYPE_LOOKUP_HH

View File

@ -99,7 +99,7 @@ eolian_cxx_inherit_01_SOURCES = \
eolian_cxx_inherit_01.$(OBJEXT): $(GENERATED)
%.eo.hh: %.eo
$(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -I$< -o $@
$(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -I${abs_srcdir} -o $@ $<
%.eo.c: %.eo
$(AM_V_EOL)$(EOLIAN_GEN) --eo --legacy $(EOLIAN_FLAGS) --gc -o $@ $<
@ -114,7 +114,7 @@ clean-local:
install-examples:
mkdir -p $(datadir)/eolian_cxx/examples
$(install_sh_DATA) -c $(SRCS) $(DATA_FILES) $(datadir)/eolian_cxx/examples
cd $(abs_srcdir) && $(install_sh_DATA) -c $(SRCS) $(DATA_FILES) $(datadir)/eolian_cxx/examples
uninstall-local:
for f in $(SRCS) $(DATA_FILES); do \

View File

@ -64,7 +64,5 @@ main()
assert(obj1.colour_get() == obj2.colour_get());
// ColourableFoo obj3(10, 0xc0ffee);
return 0;
}

View File

@ -4,10 +4,10 @@
extern "C"
{
#include <Eolian.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eolian.h>
}
namespace efl { namespace eolian {

View File

@ -2,9 +2,9 @@
#ifndef EOLIAN_CXX_EO_GENERATE_HH
#define EOLIAN_CXX_EO_GENERATE_HH
#include "eo_types.hh"
#include <iosfwd>
#include "eo_types.hh"
#include "grammar/eo_header_generator.hh"
namespace efl { namespace eolian {

View File

@ -2,8 +2,10 @@
#ifndef EOLIAN_CXX_EO_TYPES_HH
#define EOLIAN_CXX_EO_TYPES_HH
#include <algorithm>
#include <string>
#include <vector>
#include <cassert>
namespace efl { namespace eolian {
@ -13,6 +15,7 @@ struct eo_function;
struct eo_event;
typedef std::vector<std::string> extensions_container_type;
typedef std::vector<std::string> includes_container_type;
typedef std::vector<eo_constructor> constructors_container_type;
typedef std::vector<eo_function> functions_container_type;
typedef std::vector<eo_parameter> parameters_container_type;
@ -20,8 +23,8 @@ typedef std::vector<eo_event> events_container_type;
struct eo_generator_options
{
std::vector<std::string> cxx_headers;
std::vector<std::string> c_headers;
includes_container_type cxx_headers;
includes_container_type c_headers;
};
struct eo_class
@ -73,17 +76,40 @@ struct eo_function
inline bool
function_is_void(eo_function const& func)
{
return func.ret == "void" || func.ret == "";
return func.ret.empty() || func.ret.compare("void") == 0;
}
inline bool
function_is_static(eo_function const& func)
{
return func.type == eo_function::class_;
}
struct eo_event
{
std::string name;
parameters_container_type params;
bool is_hot;
std::string eo_name;
std::string comment;
};
// XXX mocked implementation. waiting for complex types...
typedef std::string eolian_type_instance;
typedef std::string eolian_type;
inline bool
type_is_void(eolian_type_instance const& type)
{
return type.empty() || type.compare("void") == 0;
}
} }
namespace eolian_cxx {
inline efl::eolian::eolian_type
type_to_native(efl::eolian::eolian_type const& type)
{
return type;
}
}
#endif // EFL_EOLIAN_CXX_EO_TYPES_HH

View File

@ -2,70 +2,73 @@
#ifndef EOLIAN_CXX_EO_CLASS_VALIDATE_HH
#define EOLIAN_CXX_EO_CLASS_VALIDATE_HH
#include <iostream> // XXX
#include <algorithm>
#include <string>
#include <cassert>
#ifdef DEBUG
#include <iostream>
#endif
#include <cstdlib>
#include "eo_types.hh"
namespace efl { namespace eolian {
inline bool
_isvalid(const std::string& name)
_is_valid(std::string const& value)
{
return name.size() > 0 and isalpha(name[0]);
return !value.empty() and isalpha(value[0]);
}
template <typename T>
inline void
_validate(T val, const eo_class& cls)
{
if(!_is_valid(val))
{
static_cast<void>(cls);
#ifndef NDEBUG
std::abort();
#endif
}
}
inline void
eo_class_validate(const eo_class& cls)
{
assert(_isvalid(cls.name));
// class name and type
_validate(cls.name, cls);
assert(cls.type != eo_class::regular_ ||
cls.type != eo_class::regular_noninst_ ||
cls.type != eo_class::interface_ ||
cls.type != eo_class::mixin_);
{
constructors_container_type::const_iterator it,
first = cls.constructors.begin(),
last = cls.constructors.end();
for (it = first; it != last; ++it)
{
parameters_container_type::const_iterator
param = (*it).params.begin(),
last_param = (*it).params.end();
assert(_isvalid((*it).name));
for (; param != last_param; ++param)
{
assert(_isvalid((*param).name));
assert(_isvalid((*param).type));
}
}
}
{
functions_container_type::const_iterator it,
first = cls.functions.begin(),
last = cls.functions.end();
for (it = first; it != last; ++it)
{
assert(_isvalid((*it).name));
assert(_isvalid((*it).impl));
assert(_isvalid((*it).ret));
parameters_container_type::const_iterator
param = (*it).params.begin(),
last_param = (*it).params.end();
for (; param != last_param; ++param)
{
assert(_isvalid((*param).name));
assert(_isvalid((*param).type));
}
}
}
// constructors
for (auto it = cls.constructors.cbegin(), last = cls.constructors.cend();
it != last; ++it)
{
_validate((*it).name, cls);
// parameters
for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
it_p != last_p; ++it_p)
{
_validate((*it_p).name, cls);
_validate((*it_p).type, cls);
}
}
// functions
for (auto it = cls.functions.begin(), last = cls.functions.end();
it != last; ++it)
{
_validate((*it).name, cls);
_validate((*it).impl, cls);
_validate((*it).ret, cls);
// parameters
for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
it_p != last_p; ++it_p)
{
_validate((*it_p).name, cls);
_validate((*it_p).type, cls);
}
}
}
} } // namespace efl { namespace eolian {

View File

@ -2,9 +2,10 @@
#ifndef EOLIAN_CXX_STD_COMMENT_HH
#define EOLIAN_CXX_STD_COMMENT_HH
#include <string>
#include <sstream>
#include <iosfwd>
#include <ostream>
#include <sstream>
#include "tab.hh"

View File

@ -2,10 +2,12 @@
#ifndef EOLIAN_CXX_STD_EO_HEADER_GENERATOR_HH
#define EOLIAN_CXX_STD_EO_HEADER_GENERATOR_HH
#include <set>
#include <algorithm>
#include <string>
#include <ostream>
#include <iosfwd>
#include <ctype.h>
#include <cctype>
#include "eo_types.hh"
#include "tab.hh"
@ -84,10 +86,11 @@ namespace_tail(std::ostream& out, eo_class const& cls)
}
inline void
include_headers(std::ostream& out, eo_generator_options const& opts)
include_headers(std::ostream& out,
eo_class const& cls EINA_UNUSED,
eo_generator_options const& opts)
{
out << "#include <Eo.h>" << endl
<< "#include <Eo.hh>" << endl << endl
out << "#include <Eo.hh>" << endl << endl
<< "extern \"C\"" << endl
<< "{" << endl;
for (auto c_header : opts.c_headers)
@ -99,14 +102,13 @@ include_headers(std::ostream& out, eo_generator_options const& opts)
{
out << "#include \"" << cxx_header << "\"" << endl;
}
out << endl;
}
inline void
eo_header_generator(std::ostream& out, eo_class const& cls, eo_generator_options const& opts)
{
onceguard_head(out, cls);
include_headers(out, opts);
include_headers(out, cls, opts);
namespace_head(out, cls);
eo_class_generator(out, cls);
namespace_tail(out, cls);

View File

@ -2,9 +2,8 @@
#ifndef EOLIAN_CXX_STD_TAB_HH
#define EOLIAN_CXX_STD_TAB_HH
#include <iosfwd>
#include <ostream>
#include <sstream>
#include <iosfwd>
namespace efl { namespace eolian { namespace grammar {
@ -26,27 +25,6 @@ operator<<(std::ostream& out, efl::eolian::grammar::tab tab)
return out;
}
struct tabify
{
int _n;
std::string _text;
tabify(int n, std::string const& text)
: _n(n), _text(text)
{}
};
inline std::ostream&
operator<<(std::ostream& out, efl::eolian::grammar::tabify const& x)
{
std::string line, tab(tabsize*x._n, ' ');
std::istringstream ss(x._text);
while (std::getline(ss, line))
{
out << tab << line << endl;
}
return out;
}
} } }
#endif // EOLIAN_CXX_STD_TAB_HH