eolian-cxx: Added namespaces and more (see below)
authorDaniel Kolesa <d.kolesa@samsung.com>
Mon, 30 Jun 2014 18:32:52 +0000 (19:32 +0100)
committerDaniel Kolesa <d.kolesa@samsung.com>
Mon, 30 Jun 2014 18:35:06 +0000 (19:35 +0100)
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.

23 files changed:
src/Makefile_Edje_Cxx.am
src/Makefile_Eolian_Cxx.am
src/Makefile_Eolian_Cxx_Helper.am
src/bin/eolian_cxx/comments.hh [deleted file]
src/bin/eolian_cxx/convert.cc
src/bin/eolian_cxx/convert.hh
src/bin/eolian_cxx/convert_comments.cc [moved from src/bin/eolian_cxx/comments.cc with 71% similarity]
src/bin/eolian_cxx/convert_comments.hh [new file with mode: 0644]
src/bin/eolian_cxx/eo_read.h [deleted file]
src/bin/eolian_cxx/eolian_cxx.cc
src/bin/eolian_cxx/eolian_wrappers.hh [new file with mode: 0644]
src/bin/eolian_cxx/safe_strings.hh
src/bin/eolian_cxx/type_lookup.hh [new file with mode: 0644]
src/examples/eolian_cxx/Makefile.am
src/examples/eolian_cxx/eolian_cxx_inherit_01.cc
src/lib/eolian_cxx/Eolian_Cxx.hh
src/lib/eolian_cxx/eo_generate.hh
src/lib/eolian_cxx/eo_types.hh
src/lib/eolian_cxx/eo_validate.hh
src/lib/eolian_cxx/grammar/comment.hh
src/lib/eolian_cxx/grammar/eo_class_events_generator.hh [moved from src/lib/eolian_cxx/grammar/eo_class_events.generator.hh with 100% similarity]
src/lib/eolian_cxx/grammar/eo_header_generator.hh
src/lib/eolian_cxx/grammar/tab.hh

index e57a866..b41bb29 100644 (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@ \
index 6ed05b1..367245a 100644 (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
 
index 09840f7..cb54cc4 100644 (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)
diff --git a/src/bin/eolian_cxx/comments.hh b/src/bin/eolian_cxx/comments.hh
deleted file mode 100644 (file)
index c8378bc..0000000
+++ /dev/null
@@ -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
index b915ed8..0b7b836 100644 (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::functions_container_type
-_get_properties(const Eolian_Class klass)
+static efl::eolian::parameters_container_type
+convert_eolian_parameters(Eolian_Function const& function,
+                          getter_t func_type)
 {
-   efl::eolian::functions_container_type container;
+   return convert_eolian_parameters
+     (::eolian_parameters_list_get(function), func_type.value);
+}
 
-   std::string cxx_classname = eolian_class_name_get(klass);
-   std::transform(cxx_classname.begin(), cxx_classname.end(),
-                  cxx_classname.begin(), ::tolower);
+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);
+}
 
-   const Eina_List *properties;
-   properties = eolian_class_functions_list_get(klass, EOLIAN_PROPERTY);
+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
+convert_eolian_property_to_functions(Eolian_Class const& klass)
+{
+   efl::eolian::functions_container_type container;
+   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);
+
+             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";
 
-             // 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::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);
+        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 == "") ? "efl::eo::base" : parent;
+        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 {
index 910d3a5..1f692b4 100644 (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
similarity index 71%
rename from src/bin/eolian_cxx/comments.cc
rename to src/bin/eolian_cxx/convert_comments.cc
index 32eec8b..fae7591 100644 (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);
-   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);
+   if (func_type != eolian_cxx::ctor.value)
+     doc += _comment_return(function, func_type);
    return doc;
 }
 
-} // namespace detail
+} // namespace eolian_cxx
diff --git a/src/bin/eolian_cxx/convert_comments.hh b/src/bin/eolian_cxx/convert_comments.hh
new file mode 100644 (file)
index 0000000..75d420a
--- /dev/null
@@ -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
diff --git a/src/bin/eolian_cxx/eo_read.h b/src/bin/eolian_cxx/eo_read.h
deleted file mode 100644 (file)
index 57b5214..0000000
+++ /dev/null
@@ -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 */
index 9513977..40b226b 100644 (file)
 #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)
-{
-   EINA_CXX_DOM_LOG_ERR(::domain) << message << std::endl;
-   exit(EXIT_FAILURE);
-}
-
-static void
-_assert_not_dup(std::string option, std::string value)
+static bool
+opts_check(eolian_cxx::options_type const& opts)
 {
-   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,105 +139,96 @@ _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
-_print_version()
+database_load(options_type const& opts)
 {
-   std::cerr
-     << "Eolian C++ Binding Generator (EFL "
-     << 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)
+   for (auto src : opts.include_dirs)
      {
-        _opt_error("Options -a and -o can't be used together.");
+        if (!::eolian_directory_scan(src.c_str()))
+          {
+             EINA_CXX_DOM_LOG_WARN(eolian_cxx::domain)
+               << "Couldn't load eolian from '" << src << "'.";
+          }
      }
-   else if (!opts.generate_all && opts.classname == "")
+   if (!::eolian_all_eot_files_parse())
      {
-        _opt_error("Neither -a nor -c provided. "
-                   "Don't know what to generate.");
+        EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
+          << "Eolian failed parsing eot files";
+        std::abort();
      }
-}
-
-static void
-_resolve_classname(options_type& opts)
-{
-   if (opts.classname == "")
+   if (!opts.in_file.empty())
      {
-        std::string cls = _guess_classname_from_sources(opts);
-        opts.classname = cls;
+        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 (opts.classname == "" && opts.out_file != "")
+   if (!::eolian_all_eo_files_parse())
      {
-        EINA_CXX_DOM_LOG_ERR(::domain)
-          << "Unknown output class for " << opts.out_file
-          << " : Missing '-c' option?";
+        EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
+          << "Eolian failed parsing input files";
         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();
-}
+} // namespace eolian_cxx {
 
 static void
-_load_classes(options_type const& opts)
+_print_version()
 {
-   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;
-          }
-     }
+   std::cerr
+     << "Eolian C++ Binding Generator (EFL "
+     << PACKAGE_VERSION << ")" << std::endl;
 }
 
 static void
@@ -279,7 +236,8 @@ _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;
 }
diff --git a/src/bin/eolian_cxx/eolian_wrappers.hh b/src/bin/eolian_cxx/eolian_wrappers.hh
new file mode 100644 (file)
index 0000000..e29716c
--- /dev/null
@@ -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
index 61f7f9b..b45a4ff 100644 (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
diff --git a/src/bin/eolian_cxx/type_lookup.hh b/src/bin/eolian_cxx/type_lookup.hh
new file mode 100644 (file)
index 0000000..a85be2d
--- /dev/null
@@ -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
index 09b770a..f1f678a 100644 (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 \
index 763e0c3..b3fe196 100644 (file)
@@ -64,7 +64,5 @@ main()
 
    assert(obj1.colour_get() == obj2.colour_get());
 
-   // ColourableFoo obj3(10, 0xc0ffee);
-
    return 0;
 }
index c4fe643..dfa7482 100644 (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 {
index 6cbbb30..a509201 100644 (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 {
index 1d04fd0..4fba083 100644 (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
index ab28c2f..0095cd5 100644 (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
-eo_class_validate(const eo_class& cls)
+_validate(T val, const eo_class& cls)
 {
-   assert(_isvalid(cls.name));
+   if(!_is_valid(val))
+     {
+        static_cast<void>(cls);
+#ifndef NDEBUG
+   std::abort();
+#endif
+     }
+}
 
+inline void
+eo_class_validate(const eo_class& cls)
+{
+   // 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 {
index f9853fb..92cc03f 100644 (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"
 
index 875777c..f1a0fd8 100644 (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);
index 5cd31ba..e775bff 100644 (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