summaryrefslogtreecommitdiff
path: root/src/bin/eolian_cxx
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2014-06-30 19:32:52 +0100
committerDaniel Kolesa <d.kolesa@samsung.com>2014-06-30 19:35:06 +0100
commitc05493b480b23cf45d2b8de9fe50070939519abb (patch)
tree372dcb9175b63b6e87e09cb9c570ba58e52983cf /src/bin/eolian_cxx
parentbd41cfe9ea1633a9dd8e2831f6b1ab37d7ddf41d (diff)
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.
Diffstat (limited to 'src/bin/eolian_cxx')
-rw-r--r--src/bin/eolian_cxx/comments.hh29
-rw-r--r--src/bin/eolian_cxx/convert.cc330
-rw-r--r--src/bin/eolian_cxx/convert.hh12
-rw-r--r--src/bin/eolian_cxx/convert_comments.cc (renamed from src/bin/eolian_cxx/comments.cc)39
-rw-r--r--src/bin/eolian_cxx/convert_comments.hh45
-rw-r--r--src/bin/eolian_cxx/eo_read.h62
-rw-r--r--src/bin/eolian_cxx/eolian_cxx.cc322
-rw-r--r--src/bin/eolian_cxx/eolian_wrappers.hh318
-rw-r--r--src/bin/eolian_cxx/safe_strings.hh82
-rw-r--r--src/bin/eolian_cxx/type_lookup.hh37
10 files changed, 813 insertions, 463 deletions
diff --git a/src/bin/eolian_cxx/comments.hh b/src/bin/eolian_cxx/comments.hh
deleted file mode 100644
index c8378bc689..0000000000
--- a/src/bin/eolian_cxx/comments.hh
+++ /dev/null
@@ -1,29 +0,0 @@
1
2#ifndef EOLIAN_CXX_EOLIAN_CONVERT_COMMENTS_HH
3#define EOLIAN_CXX_EOLIAN_CONVERT_COMMENTS_HH
4
5#include <string>
6
7extern "C"
8{
9#include <Eina.h>
10#include <Eolian.h>
11}
12
13#include <Eolian_Cxx.hh>
14
15namespace detail {
16
17std::string eolian_class_comment(const Eolian_Class kls);
18
19std::string eolian_constructor_comment(Eolian_Function constructor);
20
21std::string eolian_function_comment(Eolian_Function function);
22
23std::string eolian_property_getter_comment(Eolian_Function function);
24
25std::string eolian_property_setter_comment(Eolian_Function function);
26
27}
28
29#endif // EOLIAN_CXX_EOLIAN_CONVERT_COMMENTS_HH
diff --git a/src/bin/eolian_cxx/convert.cc b/src/bin/eolian_cxx/convert.cc
index b915ed82b7..0b7b8366da 100644
--- a/src/bin/eolian_cxx/convert.cc
+++ b/src/bin/eolian_cxx/convert.cc
@@ -1,18 +1,26 @@
1
1#include <vector> 2#include <vector>
2#include <algorithm> 3#include <algorithm>
3#include <cassert> 4#include <cassert>
5#include <cstddef>
4 6
5#ifdef HAVE_CONFIG_H 7#ifdef HAVE_CONFIG_H
6# include <config.h> 8# include <config.h>
7#endif 9#endif
8 10
9#include <Eina.h>
10#include <Eina.hh> 11#include <Eina.hh>
11#include <Eolian.h> 12#include <Eolian.h>
12 13
13#include "eo_types.hh" 14#include "eo_types.hh"
15#include "eo_validate.hh"
16
14#include "safe_strings.hh" 17#include "safe_strings.hh"
15#include "comments.hh" 18#include "convert_comments.hh"
19#include "eolian_wrappers.hh"
20
21namespace eolian_cxx {
22
23extern efl::eina::log_domain domain;
16 24
17static std::string 25static std::string
18_dedup_func_name(Eolian_Function func, const std::string &classn) 26_dedup_func_name(Eolian_Function func, const std::string &classn)
@@ -23,145 +31,147 @@ _dedup_func_name(Eolian_Function func, const std::string &classn)
23 return ret; 31 return ret;
24} 32}
25 33
26static std::string
27_resolve_param_type(Eolian_Function_Parameter id, bool is_get)
28{
29 Eolian_Parameter_Dir dir;
30 Eolian_Type typet;
31 const char *type = NULL;
32 bool is_const;
33 std::string res;
34
35 eolian_parameter_information_get(id, &dir, &typet, NULL, NULL);
36 if (typet) type = eolian_type_c_type_get(typet);
37 is_const = eolian_parameter_const_attribute_get(id, is_get);
38 res = safe_str(type);
39 eina_stringshare_del(type);
40 assert(res != "");
41 if (is_const) res = std::string("const ") + res;
42 if (dir == EOLIAN_OUT_PARAM || dir == EOLIAN_INOUT_PARAM) res += "*";
43 return res;
44}
45
46static efl::eolian::parameters_container_type 34static efl::eolian::parameters_container_type
47_get_params(const Eina_List *eolian_params, bool is_get = false) 35convert_eolian_parameters(Eina_List const* parameters,
36 Eolian_Function_Type func_type)
48{ 37{
38 if (parameters == NULL) return {};
39 assert(func_type != EOLIAN_PROPERTY);
40
49 const Eina_List *it; 41 const Eina_List *it;
50 void *curr; 42 void *curr;
51 if (eolian_params == NULL)
52 {
53 return efl::eolian::parameters_container_type();
54 }
55 efl::eolian::parameters_container_type list; 43 efl::eolian::parameters_container_type list;
56 EINA_LIST_FOREACH (eolian_params, it, curr) 44 EINA_LIST_FOREACH (parameters, it, curr)
57 { 45 {
58 Eolian_Function_Parameter id = 46 Eolian_Function_Parameter id =
59 (static_cast<Eolian_Function_Parameter>(curr)); 47 (static_cast<Eolian_Function_Parameter>(curr));
60 list.push_back({ 48 list.push_back
61 _resolve_param_type(id, is_get), 49 ({
62 safe_strshare(eolian_parameter_name_get(id)) 50 parameter_type(id, func_type),
63 }); 51 parameter_name(id)
52 });
64 } 53 }
65 return list; 54 return list;
66} 55}
67 56
68static efl::eolian::functions_container_type 57static efl::eolian::parameters_container_type
69_get_properties(const Eolian_Class klass) 58convert_eolian_parameters(Eolian_Function const& function,
59 getter_t func_type)
70{ 60{
71 efl::eolian::functions_container_type container; 61 return convert_eolian_parameters
62 (::eolian_parameters_list_get(function), func_type.value);
63}
72 64
73 std::string cxx_classname = eolian_class_name_get(klass); 65static efl::eolian::parameters_container_type
74 std::transform(cxx_classname.begin(), cxx_classname.end(), 66convert_eolian_parameters(Eina_List const* parameters,
75 cxx_classname.begin(), ::tolower); 67 getter_t func_type)
68{
69 return convert_eolian_parameters(parameters, func_type.value);
70}
76 71
77 const Eina_List *properties; 72static efl::eolian::parameters_container_type
78 properties = eolian_class_functions_list_get(klass, EOLIAN_PROPERTY); 73convert_eolian_parameters(Eina_List const* parameters,
74 setter_t func_type)
75{
76 return convert_eolian_parameters(parameters, func_type.value);
77}
78
79static efl::eolian::parameters_container_type
80convert_eolian_parameters(Eolian_Function const& function)
81{
82 assert(function_type(function) != EOLIAN_PROPERTY);
83 return convert_eolian_parameters
84 (::eolian_parameters_list_get(function), function_type(function));
85}
79 86
87static efl::eolian::functions_container_type
88convert_eolian_property_to_functions(Eolian_Class const& klass)
89{
90 efl::eolian::functions_container_type container;
91 std::string cxx_classname = safe_lower(class_name(klass));
92 const Eina_List *properties =
93 eolian_class_functions_list_get(klass, EOLIAN_PROPERTY); // XXX
80 const Eina_List *it; 94 const Eina_List *it;
81 void *curr; 95 void *curr;
82 std::string prefix(safe_str(eolian_class_eo_prefix_get(klass))); 96 std::string prefix(class_prefix(klass));
83 EINA_LIST_FOREACH (properties, it, curr) 97 EINA_LIST_FOREACH (properties, it, curr)
84 { 98 {
85 Eolian_Function property = static_cast<Eolian_Function>(curr); 99 Eolian_Function prop_ = static_cast<Eolian_Function>(curr);
86 Eolian_Function_Type type = eolian_function_type_get(property); 100 if (property_is_getter(prop_))
87 std::string name = safe_str(eolian_function_name_get(property));
88 if (type == EOLIAN_PROP_GET || type == EOLIAN_PROPERTY)
89 { 101 {
90 const Eina_List *keys_ = eolian_property_keys_list_get(property); 102 efl::eolian::parameters_container_type params
91 efl::eolian::parameters_container_type params = _get_params 103 = convert_eolian_parameters(prop_, eolian_cxx::getter);
92 (eolian_parameters_list_get(property), true); 104
93 efl::eolian::eo_function getter; 105 efl::eolian::eo_function get_;
94 getter.type = efl::eolian::eo_function::regular_; 106 get_.type = efl::eolian::eo_function::regular_;
95 getter.name = name + "_get"; 107 get_.name = function_name(prop_) + "_get";
96 getter.impl = _dedup_func_name(property, (prefix != "" ? prefix : cxx_classname)) + "_get"; 108 get_.impl = _dedup_func_name(prop_, prefix) + "_get";
97 Eolian_Type tp = eolian_function_return_type_get(property, EOLIAN_PROP_GET);
98 const char *tps = NULL;
99 if (tp) tps = eolian_type_c_type_get(tp);
100 std::string ret = safe_str(tps);
101 if (tps) eina_stringshare_del(tps);
102 if (ret == "") ret = "void";
103 109
104 // if the getter has a single parameter and void return 110 efl::eolian::eolian_type_instance ret =
105 // we translate it to a getter with no parameters that 111 function_return_type(prop_, eolian_cxx::getter);
106 // returns its type. 112
107 if ((ret == "void") && params.size() == 1) 113 // if the getter has a single parameter and a void return
114 // it is transformed into a getter with no parameters
115 // that actually returns what would be the first argument.
116 if (params.size() == 1 && efl::eolian::type_is_void(ret))
108 { 117 {
109 getter.ret = params[0].type; 118 get_.ret = params[0].type;
110 getter.params.clear(); 119 get_.params.clear();
111 } 120 }
112 else // otherwise just create the described getter 121 else // otherwise just create the described getter
113 { 122 {
114 getter.ret = ret; 123 get_.ret = ret;
115 getter.params = params; 124 get_.params = params;
116 std::transform 125 std::transform
117 (params.begin(), params.end(), getter.params.begin(), 126 (params.begin(), params.end(), get_.params.begin(),
118 [](efl::eolian::eo_parameter const& param) 127 [](efl::eolian::eo_parameter const& param)
119 { 128 {
129 efl::eolian::eolian_type getter_param_type =
130 type_to_native(param.type);
131 getter_param_type/*.native*/ += "*"; // XXX implement complex types
120 return efl::eolian::eo_parameter 132 return efl::eolian::eo_parameter
121 { param.type + "*", param.name }; 133 { { getter_param_type }, param.name };
122 }); 134 });
123 } 135 }
124 if (eina_list_count(keys_) > 0) 136 efl::eolian::parameters_container_type keys =
137 convert_eolian_parameters(::eolian_property_keys_list_get(prop_),
138 eolian_cxx::getter);
139 if (!keys.empty())
125 { 140 {
126 efl::eolian::parameters_container_type keys = _get_params(keys_, true); 141 keys.reserve(keys.size() + get_.params.size());
127 keys.reserve(keys.size() + getter.params.size()); 142 keys.insert(keys.end(), get_.params.begin(),
128 keys.insert(keys.end(), getter.params.begin(), getter.params.end()); 143 get_.params.end());
129 getter.params = keys; 144 get_.params = keys;
130 } 145 }
131 getter.comment = detail::eolian_property_getter_comment(property); 146 get_.comment = convert_comments_function(prop_, eolian_cxx::getter);
132 container.push_back(getter); 147 container.push_back(get_);
133 } 148 }
134 if (type == EOLIAN_PROP_SET || type == EOLIAN_PROPERTY) 149 if (property_is_setter(prop_))
135 { 150 {
136 const Eina_List *keys_ = eolian_property_keys_list_get(property); 151 const Eina_List *keys_ = eolian_property_keys_list_get(prop_);
137 const Eina_List *args_ = eolian_parameters_list_get(property); 152 const Eina_List *args_ = eolian_parameters_list_get(prop_);
138 Eina_List *params_ = eina_list_merge(eina_list_clone(keys_), eina_list_clone(args_)); 153 Eina_List *params_ = eina_list_merge(eina_list_clone(keys_), eina_list_clone(args_));
139 efl::eolian::parameters_container_type params = _get_params(params_); 154 efl::eolian::parameters_container_type params =
155 convert_eolian_parameters(params_, eolian_cxx::setter);
140 eina_list_free(params_); 156 eina_list_free(params_);
141 efl::eolian::eo_function setter; 157 efl::eolian::eo_function set_;
142 setter.type = efl::eolian::eo_function::regular_; 158 set_.type = efl::eolian::eo_function::regular_;
143 setter.name = name + "_set"; 159 set_.name = function_name(prop_) + "_set";
144 setter.impl = _dedup_func_name(property, (prefix != "" ? prefix : cxx_classname)) + "_set"; 160 set_.impl = _dedup_func_name(prop_, prefix) + "_set";
145 setter.params = params; 161 set_.params = params;
146 Eolian_Type tp = eolian_function_return_type_get(property, EOLIAN_PROP_SET); 162 set_.ret = function_return_type(prop_, eolian_cxx::setter);
147 const char *tps = NULL; 163 set_.comment = convert_comments_function(prop_, eolian_cxx::setter);
148 if (tp) tps = eolian_type_c_type_get(tp); 164 container.push_back(set_);
149 setter.ret = safe_str(tps);
150 if (tps) eina_stringshare_del(tps);
151 if (setter.ret == "") setter.ret = "void";
152 setter.comment = detail::eolian_property_setter_comment(property);
153 container.push_back(setter);
154 } 165 }
155 } 166 }
156 return container; 167 return container;
157} 168}
158 169
159namespace detail {
160
161void 170void
162convert_eolian_inheritances(efl::eolian::eo_class& cls, const Eolian_Class klass) 171convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klass)
163{ 172{
164 const Eina_List *inheritances = eolian_class_inherits_list_get(klass); 173 const Eina_List *inheritances =
174 ::eolian_class_inherits_list_get(klass);
165 const Eina_List *it; 175 const Eina_List *it;
166 void *curr; 176 void *curr;
167 177
@@ -173,29 +183,31 @@ convert_eolian_inheritances(efl::eolian::eo_class& cls, const Eolian_Class klass
173 } 183 }
174 else 184 else
175 { 185 {
176 std::string parent = 186 const char *ptr = static_cast<const char*>
177 static_cast<const char*>(eina_list_data_get(inheritances)); 187 (eina_list_data_get(inheritances));
178 std::transform(parent.begin(), parent.end(), parent.begin(), ::tolower); 188 std::string parent = class_format_cxx(safe_lower(ptr));
189
179 // "eo_base" is the Eolian name for EO_BASE_CLASS. 190 // "eo_base" is the Eolian name for EO_BASE_CLASS.
180 cls.parent = (parent == "eo_base" || parent == "") ? "efl::eo::base" : parent; 191 cls.parent =
192 (parent == "eo_base" || parent == "eo::base" || parent == "")
193 ? "efl::eo::base"
194 : parent;
181 } 195 }
182
183 inheritances = eina_list_next(inheritances); 196 inheritances = eina_list_next(inheritances);
184 EINA_LIST_FOREACH (inheritances, it, curr) 197 EINA_LIST_FOREACH (inheritances, it, curr)
185 { 198 {
186 std::string extension = static_cast<const char*>(curr); 199 std::string extension = safe_lower(static_cast<const char*>(curr));
187 std::transform 200 cls.extensions.push_back(class_format_cxx(extension));
188 (extension.begin(), extension.end(), extension.begin(), ::tolower);
189 cls.extensions.push_back(extension);
190 } 201 }
191} 202}
192 203
193void 204void
194convert_eolian_implements(efl::eolian::eo_class& cls, const Eolian_Class klass) 205convert_eolian_implements(efl::eolian::eo_class& cls, Eolian_Class const& klass)
195{ 206{
196 const Eina_List *it; 207 const Eina_List *it;
197 std::string prefix(safe_str(eolian_class_eo_prefix_get(klass))); 208 std::string prefix(class_prefix(klass));
198 void *impl_desc_; 209 void *impl_desc_;
210
199 EINA_LIST_FOREACH(eolian_class_implements_list_get(klass), it, impl_desc_) 211 EINA_LIST_FOREACH(eolian_class_implements_list_get(klass), it, impl_desc_)
200 { 212 {
201 Eolian_Implement impl_desc = static_cast<Eolian_Implement>(impl_desc_); 213 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)
207 if (impl_type == EOLIAN_CTOR) 219 if (impl_type == EOLIAN_CTOR)
208 { 220 {
209 efl::eolian::eo_constructor constructor; 221 efl::eolian::eo_constructor constructor;
210 std::string parent = safe_str(eolian_class_full_name_get(impl_class)); 222 std::string parent = safe_lower(eolian_class_full_name_get(impl_class));
211 if(parent == "Eo_Base") parent = "eo"; 223 if (parent == "eo_base" || parent == "eo.base") parent = "eo";
212 else std::transform(parent.begin(), parent.end(), parent.begin(), ::tolower); 224 constructor.name = parent + "_" + function_name(impl_func);
213 constructor.name = parent + "_" + safe_str(eolian_function_name_get(impl_func)); 225 constructor.params = convert_eolian_parameters(impl_func);
214 constructor.params = _get_params 226 constructor.comment = convert_comments_function(impl_func, eolian_cxx::ctor);
215 (eolian_parameters_list_get(impl_func));
216 constructor.comment = detail::eolian_constructor_comment
217 (impl_func);
218 cls.constructors.push_back(constructor); 227 cls.constructors.push_back(constructor);
219 } 228 }
220 } 229 }
221} 230}
222 231
223void 232void
224convert_eolian_constructors(efl::eolian::eo_class& cls, const Eolian_Class klass) 233convert_eolian_constructors(efl::eolian::eo_class& cls, Eolian_Class const& klass)
225{ 234{
226 const Eina_List *it; 235 const Eina_List *it;
227 void *curr; 236 void *curr;
228 std::string prefix(safe_str(eolian_class_eo_prefix_get(klass))); 237 std::string prefix(class_prefix(klass));
229 const Eina_List *constructors = 238 const Eina_List *constructors =
230 eolian_class_functions_list_get(klass, EOLIAN_CTOR); 239 eolian_class_functions_list_get(klass, EOLIAN_CTOR);
231 EINA_LIST_FOREACH (constructors, it, curr) 240 EINA_LIST_FOREACH (constructors, it, curr)
232 { 241 {
233 Eolian_Function eolian_constructor = static_cast<Eolian_Function>(curr); 242 Eolian_Function eo_constructor = static_cast<Eolian_Function>(curr);
234 efl::eolian::eo_constructor constructor; 243 efl::eolian::eo_constructor constructor;
235 constructor.name = _dedup_func_name(eolian_constructor, 244 constructor.name = _dedup_func_name(eo_constructor, prefix);
236 (prefix != "" ? prefix : cls.name)); 245 constructor.params = convert_eolian_parameters(eo_constructor);
237 constructor.params = _get_params 246 constructor.comment = convert_comments_function(eo_constructor, eolian_cxx::ctor);
238 (eolian_parameters_list_get(eolian_constructor));
239 constructor.comment = detail::eolian_constructor_comment
240 (eolian_constructor);
241 cls.constructors.push_back(constructor); 247 cls.constructors.push_back(constructor);
242 } 248 }
243} 249}
244 250
245void 251void
246convert_eolian_functions(efl::eolian::eo_class& cls, const Eolian_Class klass) 252convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass)
247{ 253{
248 const Eina_List *it; 254 const Eina_List *it;
249 void *curr; 255 void *curr;
@@ -254,60 +260,60 @@ convert_eolian_functions(efl::eolian::eo_class& cls, const Eolian_Class klass)
254 { 260 {
255 efl::eolian::eo_function function; 261 efl::eolian::eo_function function;
256 Eolian_Function eolian_function = static_cast<Eolian_Function>(curr); 262 Eolian_Function eolian_function = static_cast<Eolian_Function>(curr);
257 std::string prefix(safe_str(eolian_class_eo_prefix_get(klass))); 263 std::string prefix(class_prefix(klass));
258 // XXX Eolian only provides regular methods so far 264 // XXX Eolian only provides regular methods so far
259 function.type = efl::eolian::eo_function::regular_; 265 function.type = efl::eolian::eo_function::regular_;
260 function.name = safe_str(eolian_function_name_get(eolian_function)); 266 function.name = function_name(eolian_function);
261 function.impl = _dedup_func_name(eolian_function, (prefix != "" ? prefix : cls.name)); 267 function.impl = _dedup_func_name(eolian_function, prefix);
262 Eolian_Type tp = eolian_function_return_type_get(eolian_function, EOLIAN_METHOD); 268 function.ret = function_return_type(eolian_function);
263 const char *tps = NULL; 269 function.params = convert_eolian_parameters(eolian_function);
264 if (tp) tps = eolian_type_c_type_get(tp); 270 function.comment = convert_comments_function(eolian_function, eolian_cxx::method);
265 function.ret = safe_str(tps);
266 if (tps) eina_stringshare_del(tps);
267 if(function.ret == "") function.ret = "void";
268 function.params = _get_params(eolian_parameters_list_get(eolian_function));
269 function.comment = detail::eolian_function_comment(eolian_function);
270 cls.functions.push_back(function); 271 cls.functions.push_back(function);
271 } 272 }
272} 273}
273 274
274void 275void
275convert_eolian_properties(efl::eolian::eo_class& cls, const Eolian_Class klass) 276convert_eolian_properties(efl::eolian::eo_class& cls, Eolian_Class const& klass)
276{ 277{
277 efl::eolian::functions_container_type properties = _get_properties(klass); 278 efl::eolian::functions_container_type properties
278 cls.functions.insert(cls.functions.end(), properties.begin(), properties.end()); 279 = convert_eolian_property_to_functions(klass);
280 cls.functions.insert
281 (cls.functions.end(), properties.begin(), properties.end());
279} 282}
280 283
281} // namespace detail { 284void
285convert_eolian_events(efl::eolian::eo_class& cls, Eolian_Class const& klass)
286{
287 efl::eolian::events_container_type events = event_list(klass);
288 cls.events.reserve(cls.events.size() + events.size());
289 cls.events.insert(cls.events.end(), events.begin(), events.end());
290}
282 291
283efl::eolian::eo_class 292efl::eolian::eo_class
284_cxx_new(const Eolian_Class klass) 293convert_eolian_class_new(Eolian_Class const& klass)
285{ 294{
286 using namespace efl::eolian; 295 efl::eolian::eo_class cls;
287 eo_class cls; 296 cls.type = class_type(klass);
288 Eolian_Class_Type cls_type = ::eolian_class_type_get(klass); 297 cls.name = safe_lower(class_name(klass));
289 if (cls_type == EOLIAN_CLASS_REGULAR) cls.type = eo_class::regular_; 298 cls.name_space = safe_lower(class_namespace_full(klass));
290 else if (cls_type == EOLIAN_CLASS_ABSTRACT) cls.type = eo_class::regular_noninst_; 299 cls.eo_name = class_eo_name(klass);
291 else if (cls_type == EOLIAN_CLASS_MIXIN) cls.type = eo_class::mixin_; 300 cls.comment = convert_comments_class(klass);
292 else if (cls_type == EOLIAN_CLASS_INTERFACE) cls.type = eo_class::interface_;
293 else { assert(false); }
294 cls.name = eolian_class_name_get(klass);
295 cls.eo_name = cls.name + "_CLASS";
296 cls.comment = detail::eolian_class_comment(klass);
297 std::transform(cls.name.begin(), cls.name.end(), cls.name.begin(), ::tolower);
298 std::transform(cls.eo_name.begin(), cls.eo_name.end(), cls.eo_name.begin(), ::toupper);
299 return cls; 301 return cls;
300} 302}
301 303
302efl::eolian::eo_class 304efl::eolian::eo_class
303c_to_cxx(const char *classname) 305convert_eolian_class(const Eolian_Class klass)
304{ 306{
305 Eolian_Class klass = eolian_class_find_by_name(classname); 307 assert(klass != NULL);
306 efl::eolian::eo_class cls(_cxx_new(klass)); 308 efl::eolian::eo_class cls(eolian_cxx::convert_eolian_class_new(klass));
307 detail::convert_eolian_inheritances(cls, klass); 309 eolian_cxx::convert_eolian_inheritances(cls, klass);
308 detail::convert_eolian_implements(cls, klass); 310 eolian_cxx::convert_eolian_implements(cls, klass);
309 detail::convert_eolian_constructors(cls, klass); 311 eolian_cxx::convert_eolian_constructors(cls, klass);
310 detail::convert_eolian_functions(cls, klass); 312 eolian_cxx::convert_eolian_functions(cls, klass);
311 detail::convert_eolian_properties(cls, klass); 313 eolian_cxx::convert_eolian_properties(cls, klass);
314 eolian_cxx::convert_eolian_events(cls, klass);
315 efl::eolian::eo_class_validate(cls);
312 return cls; 316 return cls;
313} 317}
318
319} // namespace eolian_cxx {
diff --git a/src/bin/eolian_cxx/convert.hh b/src/bin/eolian_cxx/convert.hh
index 910d3a5dd8..1f692b4471 100644
--- a/src/bin/eolian_cxx/convert.hh
+++ b/src/bin/eolian_cxx/convert.hh
@@ -4,6 +4,16 @@
4 4
5#include "eo_types.hh" 5#include "eo_types.hh"
6 6
7efl::eolian::eo_class c_to_cxx(const char *classname); 7namespace eolian_cxx
8{
9
10///
11/// @brief Retrieve a efl::eolian::eo_class from an Eolian_Class name.
12/// @param cls The Eolian class.
13/// @return The @p eo_class describing @p classname.
14///
15efl::eolian::eo_class convert_eolian_class(Eolian_Class klass);
16
17}
8 18
9#endif // EOLIAN_CXX_EOLIAN_CONVERT_CLASSES_HH 19#endif // EOLIAN_CXX_EOLIAN_CONVERT_CLASSES_HH
diff --git a/src/bin/eolian_cxx/comments.cc b/src/bin/eolian_cxx/convert_comments.cc
index 32eec8bcda..fae7591bc8 100644
--- a/src/bin/eolian_cxx/comments.cc
+++ b/src/bin/eolian_cxx/convert_comments.cc
@@ -1,7 +1,9 @@
1 1
2#include "comments.hh" 2#include "convert_comments.hh"
3#include "safe_strings.hh" 3#include "safe_strings.hh"
4 4
5namespace eolian_cxx {
6
5static std::string 7static std::string
6_comment_parameter(Eolian_Function_Parameter param) 8_comment_parameter(Eolian_Function_Parameter param)
7{ 9{
@@ -74,41 +76,20 @@ _comment_return(Eolian_Function function,
74 return doc; 76 return doc;
75} 77}
76 78
77namespace detail {
78
79std::string 79std::string
80eolian_class_comment(const Eolian_Class kls) 80convert_comments_class(Eolian_Class const& klass)
81{ 81{
82 return safe_str(eolian_class_description_get(kls)); 82 return safe_str(eolian_class_description_get(klass));
83} 83}
84 84
85std::string 85std::string
86eolian_constructor_comment(Eolian_Function constructor) 86convert_comments_function(Eolian_Function const& function,
87{ 87 Eolian_Function_Type func_type)
88 return _comment_brief_and_params(constructor);
89}
90
91std::string eolian_function_comment(Eolian_Function function)
92{ 88{
93 std::string doc = _comment_brief_and_params(function); 89 std::string doc = _comment_brief_and_params(function);
94 doc += _comment_return(function, EOLIAN_METHOD); 90 if (func_type != eolian_cxx::ctor.value)
95 return doc; 91 doc += _comment_return(function, func_type);
96}
97
98std::string eolian_property_getter_comment(Eolian_Function property)
99{
100 std::string doc = _comment_brief_and_params
101 (property, EOLIAN_COMMENT_GET);
102 doc += _comment_return(property, EOLIAN_PROP_GET);
103 return doc;
104}
105
106std::string eolian_property_setter_comment(Eolian_Function property)
107{
108 std::string doc = _comment_brief_and_params
109 (property, EOLIAN_COMMENT_SET);
110 doc += _comment_return(property, EOLIAN_PROP_SET);
111 return doc; 92 return doc;
112} 93}
113 94
114} // namespace detail 95} // 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
index 0000000000..75d420af58
--- /dev/null
+++ b/src/bin/eolian_cxx/convert_comments.hh
@@ -0,0 +1,45 @@
1
2#ifndef EOLIAN_CXX_CONVERT_COMMENTS_HH
3#define EOLIAN_CXX_CONVERT_COMMENTS_HH
4
5#include <string>
6
7#include <Eolian.h>
8#include <Eolian_Cxx.hh>
9
10#include "eolian_wrappers.hh"
11
12namespace eolian_cxx {
13
14std::string convert_comments_class(Eolian_Class const& kls);
15
16std::string convert_comments_function(Eolian_Function const& function,
17 Eolian_Function_Type func_type);
18
19inline std::string
20convert_comments_function(Eolian_Function const& constructor_, ctor_t func_type_)
21{
22 return convert_comments_function(constructor_, func_type_.value);
23}
24
25inline std::string
26convert_comments_function(Eolian_Function const& function_, method_t func_type_)
27{
28 return convert_comments_function(function_, func_type_.value);
29}
30
31inline std::string
32convert_comments_function(Eolian_Function const& property_, getter_t func_type_)
33{
34 return convert_comments_function(property_, func_type_.value);
35}
36
37inline std::string
38convert_comments_function(Eolian_Function const& property_, setter_t func_type_)
39{
40 return convert_comments_function(property_, func_type_.value);
41}
42
43}
44
45#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
index 57b5214252..0000000000
--- a/src/bin/eolian_cxx/eo_read.h
+++ /dev/null
@@ -1,62 +0,0 @@
1
2#ifndef EOLIAN_CXX_EOLIAN_HELPER_H
3#define EOLIAN_CXX_EOLIAN_HELPER_H
4
5#include <Eina.h>
6#include <Eolian.h>
7#include <assert.h>
8
9#define EO_SUFFIX ".eo"
10
11inline Eina_List*
12_list_dir(const char *dir, const char *suffix, Eina_Bool recurse)
13{
14 Eina_List *files = NULL;
15 Eina_Iterator *ls;
16 Eina_File_Direct_Info *info;
17
18 ls = eina_file_direct_ls(dir);
19 if(ls == NULL) return NULL;
20
21 EINA_ITERATOR_FOREACH (ls, info)
22 {
23 assert(info && info->path);
24 if (info->type == EINA_FILE_DIR && recurse)
25 {
26 files = eina_list_merge
27 (files, _list_dir(info->path, suffix, recurse));
28 }
29 else if (eina_str_has_suffix(&info->path[info->name_start], suffix))
30 {
31 files = eina_list_append(files, strdup(info->path));
32 }
33 }
34 eina_iterator_free(ls);
35 return eina_list_sort
36 (files, eina_list_count(files), EINA_COMPARE_CB(strcoll));
37}
38
39inline Eina_List*
40eolian_read_from_fs(const char *path)
41{
42 if (eina_str_has_suffix(path, EO_SUFFIX))
43 {
44 if(!eolian_eo_file_parse(path))
45 {
46 /* XXX: fprintf? */
47 fprintf(stderr, "Couldn't load input file: %s\n", path);
48 return NULL;
49 }
50 }
51 else
52 {
53 if (!eolian_directory_scan(path))
54 {
55 /* XXX: fprintf? */
56 fprintf(stderr, "Error scanning directory: %s\n", path);
57 }
58 }
59 return eina_list_clone(eolian_class_names_list_get());
60}
61
62#endif /* EOLIAN_CXX_EOLIAN_HELPER_H */
diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc
index 951397708c..40b226be94 100644
--- a/src/bin/eolian_cxx/eolian_cxx.cc
+++ b/src/bin/eolian_cxx/eolian_cxx.cc
@@ -13,42 +13,40 @@
13#include <type_traits> 13#include <type_traits>
14#include <cassert> 14#include <cassert>
15 15
16extern "C"
17{
18#ifdef HAVE_CONFIG_H 16#ifdef HAVE_CONFIG_H
19# include <config.h> 17# include <config.h>
20#endif 18#endif
21
22#include <Eina.h>
23#include <Eolian.h> 19#include <Eolian.h>
24}
25 20
26#include <Eina.hh> 21#include <Eina.hh>
27#include <Eolian_Cxx.hh> 22#include <Eolian_Cxx.hh>
28 23
29#include "eo_read.h"
30#include "convert.hh" 24#include "convert.hh"
25#include "type_lookup.hh"
26
27#include "convert.hh"
28#include "eolian_wrappers.hh"
31#include "safe_strings.hh" 29#include "safe_strings.hh"
32 30
33namespace { 31namespace eolian_cxx {
34 32
35// Program options. 33/// Program options.
36struct options_type 34struct options_type
37{ 35{
38 std::vector<std::string> in_srcs; 36 std::vector<std::string> include_dirs;
37 std::string in_file;
39 std::string out_file; 38 std::string out_file;
40 std::string out_dir; 39 std::string out_dir;
41 std::string classname; 40 std::string classname;
42 std::string name_space;
43 bool recurse; 41 bool recurse;
44 bool generate_all; 42 bool generate_all;
45 43
46 options_type() 44 options_type()
47 : in_srcs() 45 : include_dirs()
48 , out_file("") 46 , in_file()
49 , out_dir("") 47 , out_file()
50 , classname("") 48 , out_dir()
51 , name_space("") 49 , classname()
52 , recurse(false) 50 , recurse(false)
53 , generate_all(false) 51 , generate_all(false)
54 {} 52 {}
@@ -56,112 +54,80 @@ struct options_type
56 54
57efl::eina::log_domain domain("eolian_cxx"); 55efl::eina::log_domain domain("eolian_cxx");
58 56
59} 57static bool
60 58opts_check(eolian_cxx::options_type const& opts)
61static void
62_opt_error(std::string message)
63{
64 EINA_CXX_DOM_LOG_ERR(::domain) << message << std::endl;
65 exit(EXIT_FAILURE);
66}
67
68static void
69_assert_not_dup(std::string option, std::string value)
70{ 59{
71 if (value != "") 60 if (!opts.generate_all && opts.in_file.empty())
72 { 61 {
73 _opt_error("Option -" + option + " already set (" + value + ")"); 62 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
63 << "Nothing to generate?" << std::endl;
74 } 64 }
75} 65 else if (opts.generate_all && !opts.in_file.empty())
76
77// Try to guess classname from input filenames.
78// Precondition: Input sources must be loaded into Eolian Database
79// otherwise we can't infer the classname from the .eo files.
80// Precondition: Input options must have opts.classname == "".
81static std::string
82_guess_classname_from_sources(::options_type& opts)
83{
84 for (auto filename : opts.in_srcs)
85 { 66 {
86 if (Eolian_Class klass = eolian_class_find_by_file(filename.c_str())) 67 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
87 { 68 << "Didn't expect to receive input files (" << opts.in_file
88 return eolian_class_full_name_get(klass); 69 << ") with parameter -a."
89 } 70 << std::endl;
90 } 71 }
91 return ""; 72 else if (opts.generate_all && !opts.out_file.empty())
92} 73 {
93 74 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
94std::pair<std::string, std::string> get_filename_info(std::string path) 75 << "Can't use -a and -o together." << std::endl;
95{ 76 }
96 const size_t last = path.rfind("lib/"); 77 else if (opts.generate_all && opts.include_dirs.empty())
97 if (last != std::string::npos) 78 {
98 { 79 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
99 path.erase(0, last+4); 80 << "Option -a requires at least one include directory (-I)."
100 81 << std::endl;
101 std::string::iterator slash 82 }
102 = std::find(path.begin(), path.end(), '/'); 83 else
103 if(slash != path.end()) 84 {
104 { 85 return true; // valid.
105 std::string namespace_ (path.begin(), slash); 86 }
106 std::string filename (slash+1, path.end()); 87 return false;
107 return {filename, namespace_};
108 }
109 }
110 std::string::reverse_iterator slash
111 = std::find(path.rbegin(), path.rend(), '/');
112 return {std::string(slash.base(), path.end()), std::string()};
113} 88}
114 89
115efl::eolian::eo_generator_options 90efl::eolian::eo_generator_options
116_resolve_includes(std::string const& classname) 91generator_options(const Eolian_Class klass)
117{ 92{
118 efl::eolian::eo_generator_options gen_opts; 93 efl::eolian::eo_generator_options gen_opts;
119 94 gen_opts.c_headers.push_back(class_base_file(klass) + ".h");
120 std::string cls_name = classname;
121 Eolian_Class klass = eolian_class_find_by_name(classname.c_str());
122 std::transform(cls_name.begin(), cls_name.end(), cls_name.begin(), ::tolower);
123
124 std::string eo_file = safe_str(eolian_class_file_get(klass));
125 gen_opts.c_headers.push_back(get_filename_info(eo_file).first + ".h");
126 95
127 void *cur = NULL; 96 void *cur = NULL;
128 const Eina_List *itr, *inheritances = eolian_class_inherits_list_get(klass); 97 const Eina_List *itr, *inheritances = eolian_class_inherits_list_get(klass);
129 EINA_LIST_FOREACH(inheritances, itr, cur) 98 EINA_LIST_FOREACH(inheritances, itr, cur)
130 { 99 {
131 Eolian_Class ext = eolian_class_find_by_name(static_cast<const char*>(cur)); 100 Eolian_Class ext = eolian_class_find_by_name(static_cast<const char*>(cur));
132 std::string eo_parent_file = safe_str(eolian_class_file_get(ext)); 101 std::string eo_parent_file = class_base_file(ext);
133 if (!eo_parent_file.empty()) 102 if (!eo_parent_file.empty())
134 { 103 {
135 std::string filename, namespace_;
136 std::tie(filename, namespace_) = get_filename_info(eo_parent_file);
137 // we have our own eo_base.hh 104 // we have our own eo_base.hh
138 std::string eo_base_eo = "eo_base.eo"; 105 std::string eo_base_eo = "eo_base.eo";
139 if (filename.length() < eo_base_eo.length() || 106 if (eo_parent_file.length() < eo_base_eo.length() ||
140 !std::equal(eo_base_eo.begin(), eo_base_eo.end(), 107 !std::equal(eo_base_eo.begin(), eo_base_eo.end(),
141 filename.end() - eo_base_eo.length())) 108 eo_parent_file.end() - eo_base_eo.length()))
142 { 109 {
143 gen_opts.cxx_headers.push_back(filename + ".hh"); 110 gen_opts.cxx_headers.push_back(eo_parent_file + ".hh");
144 } 111 }
145 } 112 }
146 else 113 else
147 { 114 {
148 EINA_CXX_DOM_LOG_ERR(::domain) 115 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
149 << "Couldn't find source file for class '" << ext << "'"; 116 << "Couldn't find source file for class '" << ext << "'"
117 << std::endl;
150 } 118 }
151 } 119 }
152 return gen_opts; 120 return gen_opts;
153} 121}
154 122
155static void 123static bool
156_generate(const std::string classname, ::options_type const& opts) 124generate(const Eolian_Class klass, eolian_cxx::options_type const& opts)
157{ 125{
158 efl::eolian::eo_class cls = ::c_to_cxx(classname.c_str()); 126 assert(!!klass);
159 cls.name_space = opts.name_space; 127 efl::eolian::eo_class cls = eolian_cxx::convert_eolian_class(klass);
160 efl::eolian::eo_class_validate(cls); 128 efl::eolian::eo_generator_options gen_opts = generator_options(klass);
161 efl::eolian::eo_generator_options gen_opts = _resolve_includes(classname); 129 std::string outname = opts.out_file.empty() ? (class_base_file(klass) + ".hh") : opts.out_file;
162 std::string outname = (opts.out_file == "") ? (cls.name + ".eo.hh") : opts.out_file; 130 if (!opts.out_dir.empty())
163
164 if (opts.out_dir != "")
165 { 131 {
166 outname = opts.out_dir + "/" + outname; 132 outname = opts.out_dir + "/" + outname;
167 } 133 }
@@ -173,105 +139,96 @@ _generate(const std::string classname, ::options_type const& opts)
173 { 139 {
174 std::ofstream outfile; 140 std::ofstream outfile;
175 outfile.open(outname); 141 outfile.open(outname);
176 assert(outfile.good()); 142 if (outfile.good())
177 efl::eolian::generate(outfile, cls, gen_opts); 143 {
178 outfile.close(); 144 efl::eolian::generate(outfile, cls, gen_opts);
145 outfile.close();
146 }
147 else
148 {
149 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
150 << "Can't open output file: " << outname << std::endl;
151 return false;
152 }
179 } 153 }
154 return true;
180} 155}
181 156
182static void 157static void
183_run(options_type const& opts) 158run(options_type const& opts)
184{ 159{
185 if (opts.classname != "") 160 Eolian_Class klass = NULL;
161 if (!opts.classname.empty())
162 klass = class_from_name(opts.classname);
163 else if (!opts.in_file.empty())
164 klass = class_from_file(opts.in_file);
165 if (klass)
186 { 166 {
187 _generate(opts.classname.c_str(), opts); 167 if (!generate(klass, opts))
168 goto err;
188 } 169 }
189 else 170 else
190 { 171 {
191 efl::eina::range_ptr_list<const char* const> 172 auto classes = class_list_all();
192 classes(eolian_class_names_list_get()); 173 for (const Eolian_Class c : classes)
193 for (auto cls : classes)
194 { 174 {
195 if (opts.classname == "" || opts.classname == cls) 175 if (!generate(c, opts))
196 { 176 {
197 _generate(cls, opts); 177 klass = c;
178 goto err;
198 } 179 }
199 } 180 }
200 } 181 }
182 return;
183 err:
184 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
185 << "Error generating: " << class_name(klass)
186 << std::endl;
187 std::abort();
201} 188}
202 189
203static void 190static void
204_print_version() 191database_load(options_type const& opts)
205{ 192{
206 std::cerr 193 for (auto src : opts.include_dirs)
207 << "Eolian C++ Binding Generator (EFL "
208 << PACKAGE_VERSION << ")" << std::endl;
209}
210
211static void
212_validate_options(::options_type const& opts)
213{
214 if (opts.in_srcs.size() == 0)
215 {
216 _opt_error("You must provide at least one input source (-I). "
217 "Either an .eo file or a directory of .eo files.");
218 }
219 else if (opts.out_file != "" && opts.generate_all)
220 { 194 {
221 _opt_error("Options -a and -o can't be used together."); 195 if (!::eolian_directory_scan(src.c_str()))
196 {
197 EINA_CXX_DOM_LOG_WARN(eolian_cxx::domain)
198 << "Couldn't load eolian from '" << src << "'.";
199 }
222 } 200 }
223 else if (!opts.generate_all && opts.classname == "") 201 if (!::eolian_all_eot_files_parse())
224 { 202 {
225 _opt_error("Neither -a nor -c provided. " 203 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
226 "Don't know what to generate."); 204 << "Eolian failed parsing eot files";
205 std::abort();
227 } 206 }
228} 207 if (!opts.in_file.empty())
229
230static void
231_resolve_classname(options_type& opts)
232{
233 if (opts.classname == "")
234 { 208 {
235 std::string cls = _guess_classname_from_sources(opts); 209 if (!::eolian_eo_file_parse(opts.in_file.c_str()))
236 opts.classname = cls; 210 {
211 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
212 << "Failed parsing: " << opts.in_file << ".";
213 std::abort();
214 }
237 } 215 }
238 if (opts.classname == "" && opts.out_file != "") 216 if (!::eolian_all_eo_files_parse())
239 { 217 {
240 EINA_CXX_DOM_LOG_ERR(::domain) 218 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
241 << "Unknown output class for " << opts.out_file 219 << "Eolian failed parsing input files";
242 << " : Missing '-c' option?";
243 std::abort(); 220 std::abort();
244 } 221 }
245} 222}
246 223
247static void 224} // namespace eolian_cxx {
248_scan_directories(options_type const& opts)
249{
250 for (auto src : opts.in_srcs)
251 {
252 if (eina_str_has_suffix(src.c_str(), EO_SUFFIX)) continue;
253 eolian_read_from_fs(src.c_str());
254 }
255}
256
257static void
258_load_eot()
259{
260 eolian_all_eot_files_parse();
261}
262 225
263static void 226static void
264_load_classes(options_type const& opts) 227_print_version()
265{ 228{
266 for (auto src : opts.in_srcs) 229 std::cerr
267 { 230 << "Eolian C++ Binding Generator (EFL "
268 if (!eina_str_has_suffix(src.c_str(), EO_SUFFIX)) continue; 231 << PACKAGE_VERSION << ")" << std::endl;
269 if ( eolian_read_from_fs(src.c_str()) == NULL)
270 {
271 EINA_CXX_DOM_LOG_WARN(::domain)
272 << "Couldn't load eolian file: " << src;
273 }
274 }
275} 232}
276 233
277static void 234static void
@@ -279,7 +236,8 @@ _usage(const char *progname)
279{ 236{
280 std::cerr 237 std::cerr
281 << progname 238 << progname
282 << " [options]" << std::endl 239 << " [options] [file.eo]" << std::endl
240 << " A single input file must be provided (unless -a is specified)." << std::endl
283 << "Options:" << std::endl 241 << "Options:" << std::endl
284 << " -a, --all Generate bindings for all Eo classes." << std::endl 242 << " -a, --all Generate bindings for all Eo classes." << std::endl
285 << " -c, --class <name> The Eo class name to generate code for." << std::endl 243 << " -c, --class <name> The Eo class name to generate code for." << std::endl
@@ -293,10 +251,20 @@ _usage(const char *progname)
293 exit(EXIT_FAILURE); 251 exit(EXIT_FAILURE);
294} 252}
295 253
296static ::options_type 254static void
297_read_options(int argc, char **argv) 255_assert_not_dup(std::string option, std::string value)
298{ 256{
299 ::options_type opts; 257 if (value != "")
258 {
259 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) <<
260 "Option -" + option + " already set (" + value + ")";
261 }
262}
263
264static eolian_cxx::options_type
265opts_get(int argc, char **argv)
266{
267 eolian_cxx::options_type opts;
300 268
301 const struct option long_options[] = 269 const struct option long_options[] =
302 { 270 {
@@ -304,21 +272,20 @@ _read_options(int argc, char **argv)
304 { "out-dir", required_argument, 0, 'D' }, 272 { "out-dir", required_argument, 0, 'D' },
305 { "out-file", required_argument, 0, 'o' }, 273 { "out-file", required_argument, 0, 'o' },
306 { "class", required_argument, 0, 'c' }, 274 { "class", required_argument, 0, 'c' },
307 { "namespace", required_argument, 0, 'n' },
308 { "all", no_argument, 0, 'a' }, 275 { "all", no_argument, 0, 'a' },
309 { "recurse", no_argument, 0, 'r' }, 276 { "recurse", no_argument, 0, 'r' },
310 { "version", no_argument, 0, 'v' }, 277 { "version", no_argument, 0, 'v' },
311 { "help", no_argument, 0, 'h' }, 278 { "help", no_argument, 0, 'h' },
312 { 0, 0, 0, 0 } 279 { 0, 0, 0, 0 }
313 }; 280 };
314 const char* options = "I:D:o:c:n:arvh"; 281 const char* options = "I:D:o:c:arvh";
315 282
316 int c, idx; 283 int c, idx;
317 while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1) 284 while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1)
318 { 285 {
319 if (c == 'I') 286 if (c == 'I')
320 { 287 {
321 opts.in_srcs.push_back(optarg); 288 opts.include_dirs.push_back(optarg);
322 } 289 }
323 else if (c == 'D') 290 else if (c == 'D')
324 { 291 {
@@ -335,11 +302,6 @@ _read_options(int argc, char **argv)
335 _assert_not_dup("c", opts.classname); 302 _assert_not_dup("c", opts.classname);
336 opts.classname = optarg; 303 opts.classname = optarg;
337 } 304 }
338 else if (c == 'n')
339 {
340 _assert_not_dup("n", opts.name_space);
341 opts.name_space = optarg;
342 }
343 else if (c == 'a') 305 else if (c == 'a')
344 { 306 {
345 opts.generate_all = true; 307 opts.generate_all = true;
@@ -358,6 +320,17 @@ _read_options(int argc, char **argv)
358 if (argc == 2) exit(EXIT_SUCCESS); 320 if (argc == 2) exit(EXIT_SUCCESS);
359 } 321 }
360 } 322 }
323 if (optind == argc-1)
324 {
325 opts.in_file = argv[optind];
326 }
327
328 if (!eolian_cxx::opts_check(opts))
329 {
330 _usage(argv[0]);
331 std::abort();
332 }
333
361 return opts; 334 return opts;
362} 335}
363 336
@@ -365,15 +338,8 @@ int main(int argc, char **argv)
365{ 338{
366 efl::eina::eina_init eina_init; 339 efl::eina::eina_init eina_init;
367 efl::eolian::eolian_init eolian_init; 340 efl::eolian::eolian_init eolian_init;
368#if DEBUG 341 eolian_cxx::options_type opts = opts_get(argc, argv);
369 domain.set_level(efl::eina::log_level::debug); 342 eolian_cxx::database_load(opts);
370#endif 343 eolian_cxx::run(opts);
371 options_type opts = _read_options(argc, argv);
372 _scan_directories(opts);
373 _load_eot();
374 _load_classes(opts);
375 _resolve_classname(opts);
376 _validate_options(opts);
377 _run(opts);
378 return 0; 344 return 0;
379} 345}
diff --git a/src/bin/eolian_cxx/eolian_wrappers.hh b/src/bin/eolian_cxx/eolian_wrappers.hh
new file mode 100644
index 0000000000..e29716c83e
--- /dev/null
+++ b/src/bin/eolian_cxx/eolian_wrappers.hh
@@ -0,0 +1,318 @@
1#ifndef EOLIAN_CXX_EOLIAN_WRAPPERS_HH
2#define EOLIAN_CXX_EOLIAN_WRAPPERS_HH
3
4#include <cassert>
5
6#include <Eolian.h>
7
8#include "eo_types.hh"
9#include "safe_strings.hh"
10#include "type_lookup.hh"
11
12namespace eolian_cxx
13{
14
15struct property_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROPERTY; };
16property_t const property = {};
17
18struct setter_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROP_SET; };
19setter_t const setter = {};
20
21struct getter_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_PROP_GET; };
22getter_t const getter = {};
23
24struct method_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_METHOD; };
25method_t const method = {};
26
27struct ctor_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_CTOR; };
28ctor_t const ctor = {};
29
30inline Eolian_Class
31class_from_file(std::string const& file)
32{
33 return ::eolian_class_find_by_file(file.c_str());
34}
35
36inline std::string
37class_file(Eolian_Class const& klass)
38{
39 return safe_str(::eolian_class_file_get(klass));
40}
41
42inline std::string
43class_base_file(Eolian_Class const& klass)
44{
45 return path_base(safe_str(::eolian_class_file_get(klass)));
46}
47
48inline std::string
49class_name(Eolian_Class const& klass)
50{
51 return safe_str(::eolian_class_name_get(klass));
52}
53
54inline std::string
55class_full_name(Eolian_Class const& klass)
56{
57 return safe_str(::eolian_class_full_name_get(klass));
58}
59
60inline Eolian_Class
61class_from_name(std::string const& classname)
62{
63 return ::eolian_class_find_by_name(classname.c_str());
64}
65
66inline std::string
67class_eo_name(Eolian_Class const& klass)
68{
69 std::string s = class_full_name(klass) + "_CLASS";
70 std::transform(s.begin(), s.end(), s.begin(),
71 [](int c)
72 {
73 return c == '.' ? '_' : c ;
74 });
75 return safe_upper(s);
76}
77
78inline std::string
79class_format_cxx(std::string const& fullname)
80{
81 std::string s = fullname;
82 auto found = s.find(".");
83 while (found != std::string::npos)
84 {
85 s.replace(found, 1, "::");
86 found = s.find(".");
87 }
88 return s;
89}
90
91inline std::string
92class_prefix(Eolian_Class const& klass)
93{
94 std::string prefix = safe_lower(::eolian_class_eo_prefix_get(klass));
95 if (prefix.empty())
96 prefix = safe_lower(class_name(klass));
97 assert(!prefix.empty());
98 return prefix;
99}
100
101inline efl::eolian::eo_class::eo_class_type
102class_type(Eolian_Class const& klass)
103{
104 assert(klass != NULL);
105 efl::eolian::eo_class::eo_class_type type;
106 Eolian_Class_Type cls_type = ::eolian_class_type_get(klass);
107
108 if (cls_type == EOLIAN_CLASS_REGULAR)
109 type = efl::eolian::eo_class::regular_;
110 else if (cls_type == EOLIAN_CLASS_ABSTRACT)
111 type = efl::eolian::eo_class::regular_noninst_;
112 else if (cls_type == EOLIAN_CLASS_MIXIN)
113 type = efl::eolian::eo_class::mixin_;
114 else if (cls_type == EOLIAN_CLASS_INTERFACE)
115 type = efl::eolian::eo_class::interface_;
116 else assert(false);
117
118 return type;
119}
120
121inline std::string
122class_namespace_full(Eolian_Class const& klass)
123{
124 std::string s;
125 const Eina_List* list =
126 ::eolian_class_namespaces_list_get(klass), *itr;
127 void* name;
128 EINA_LIST_FOREACH(list, itr, name)
129 {
130 s += static_cast<const char*>(name);
131 s += "::";
132 }
133 if (s.size() >= 2)
134 s = s.substr(0, s.size()-2);
135 return s;
136}
137
138inline efl::eina::range_ptr_list<const Eolian_Class>
139class_list_all()
140{
141 return ::eolian_class_names_list_get();
142}
143
144inline std::string
145function_name(Eolian_Function const& function)
146{
147 return safe_str(::eolian_function_name_get(function));
148}
149
150inline Eolian_Function_Type
151function_type(Eolian_Function const& function)
152{
153 return ::eolian_function_type_get(function);
154}
155
156inline efl::eolian::eolian_type_instance
157function_return_type(Eolian_Function const& function, Eolian_Function_Type func_type = method_t::value)
158{
159 return type_lookup
160 (::eolian_function_return_type_get(function, func_type));
161}
162
163inline efl::eolian::eolian_type_instance
164function_return_type(Eolian_Function const& function, setter_t func_type)
165{
166 return function_return_type(function, func_type.value);
167}
168
169inline efl::eolian::eolian_type_instance
170function_return_type(Eolian_Function const& function, getter_t func_type)
171{
172 return function_return_type(function, func_type.value);
173}
174
175inline efl::eolian::eolian_type_instance
176function_return_type(Eolian_Function const& function, method_t func_type)
177{
178 return function_return_type(function, func_type.value);
179}
180
181inline efl::eolian::eolian_type_instance
182function_return_type(Eolian_Function const& function, ctor_t func_type)
183{
184 return function_return_type(function, func_type.value);
185}
186
187inline bool
188property_is_getter(Eolian_Function_Type func_type)
189{
190 return func_type == property_t::value || func_type == getter_t::value;
191}
192
193inline bool
194property_is_getter(Eolian_Function const& function)
195{
196 return property_is_getter(function_type(function));
197}
198
199inline bool
200property_is_setter(Eolian_Function_Type func_type)
201{
202 return func_type == property_t::value || func_type == setter_t::value;
203}
204
205inline bool
206property_is_setter(Eolian_Function const& function)
207{
208 return property_is_setter(function_type(function));
209}
210
211inline std::string
212parameter_name(Eolian_Function_Parameter const& parameter)
213{
214 return safe_strshare(::eolian_parameter_name_get(parameter));
215}
216
217inline bool
218parameter_is_out(Eolian_Function_Parameter const& parameter)
219{
220 Eolian_Parameter_Dir direction;
221 ::eolian_parameter_information_get(parameter, &direction, NULL, NULL, NULL);
222 return direction == EOLIAN_OUT_PARAM || direction == EOLIAN_INOUT_PARAM;
223}
224
225inline bool
226parameter_is_const(Eolian_Function_Parameter const& parameter,
227 Eolian_Function_Type func_type)
228{
229 return ::eolian_parameter_const_attribute_get
230 (parameter, property_is_getter(func_type));
231}
232
233inline bool
234parameter_is_const(Eolian_Function_Parameter const& parameter,
235 getter_t func_type)
236{
237 return ::eolian_parameter_const_attribute_get
238 (parameter, property_is_getter(func_type.value));
239}
240
241inline bool
242parameter_is_const(Eolian_Function_Parameter const& parameter,
243 setter_t func_type)
244{
245 return ::eolian_parameter_const_attribute_get
246 (parameter, property_is_getter(func_type.value));
247}
248
249inline bool
250parameter_is_const(Eolian_Function_Parameter const& parameter,
251 Eolian_Function const& function)
252{
253 assert(function_type(function) != EOLIAN_PROPERTY);
254 return ::eolian_parameter_const_attribute_get
255 (parameter, property_is_getter(function));
256}
257
258inline efl::eolian::eolian_type_instance
259parameter_type(Eolian_Function_Parameter const& parameter,
260 Eolian_Function_Type func_type = method_t::value)
261{
262 efl::eolian::eolian_type_instance type
263 (type_lookup(::eolian_parameter_type_get(parameter)));
264 assert(!type.empty());
265 // XXX implement complex types.
266 if (parameter_is_out(parameter))
267 type = { type_to_native(type) + "*" };
268 if (parameter_is_const(parameter, func_type))
269 type.insert(0, "const ");
270 return type;
271}
272
273inline efl::eolian::eolian_type_instance
274parameter_type(Eolian_Function_Parameter const& parameter, getter_t func_type)
275{
276 return parameter_type(parameter, func_type.value);
277}
278
279inline efl::eolian::eolian_type_instance
280parameter_type(Eolian_Function_Parameter const& parameter, setter_t func_type)
281{
282 return parameter_type(parameter, func_type.value);
283}
284
285inline efl::eolian::eo_event
286event_create(Eolian_Class const& klass, const Eolian_Event event_)
287{
288 efl::eolian::eo_event event;
289 const char *name, *type, *comment;
290 if(::eolian_class_event_information_get(event_, &name, &type, &comment))
291 {
292 std::string name_ = safe_str(name);
293 std::transform(name_.begin(), name_.end(), name_.begin(),
294 [](int c) { return c != ',' ? c : '_'; });
295 event.name = normalize_spaces(name_);
296 event.eo_name = safe_upper(class_name(klass) + "_EVENT_" + event.name);
297 event.comment = safe_str(comment);
298 }
299 return event;
300}
301
302inline efl::eolian::events_container_type
303event_list(Eolian_Class const& klass)
304{
305 efl::eolian::events_container_type events;
306 const Eina_List* list = eolian_class_events_list_get(klass);
307 unsigned int length = eina_list_count(list);
308 for (unsigned int i = 0; i < length; ++i)
309 {
310 Eolian_Event e = static_cast<Eolian_Event>(eina_list_nth(list, i));
311 events.push_back(event_create(klass, e));
312 }
313 return events;
314}
315
316}
317
318#endif // EOLIAN_CXX_EOLIAN_WRAPPERS_HH
diff --git a/src/bin/eolian_cxx/safe_strings.hh b/src/bin/eolian_cxx/safe_strings.hh
index 61f7f9b58f..b45a4ff32d 100644
--- a/src/bin/eolian_cxx/safe_strings.hh
+++ b/src/bin/eolian_cxx/safe_strings.hh
@@ -3,20 +3,26 @@
3#define EOLIAN_CXX_BIN_SAFE_STRINGS_HH 3#define EOLIAN_CXX_BIN_SAFE_STRINGS_HH
4 4
5#include <string> 5#include <string>
6#include <algorithm>
7#include <cstddef>
8#include <cctype>
9#include <iterator>
6 10
7extern "C" 11extern "C"
8{ 12{
9#include <Eina.h> 13#include <Eina.h>
10} 14}
11 15
12/// @brief Safely convert an const char* to std::string. 16/// @brief Safely convert const char* to std::string.
17///
13inline std::string 18inline std::string
14safe_str(const char* str) 19safe_str(const char* str)
15{ 20{
16 return (str != NULL) ? str : ""; 21 return (str != NULL) ? str : "";
17} 22}
18 23
19/// @brief Safely convert an Eina_Stringshare to std::string. 24/// @brief Safely convert Eina_Stringshare to std::string.
25///
20inline std::string 26inline std::string
21safe_strshare(Eina_Stringshare* strsh) 27safe_strshare(Eina_Stringshare* strsh)
22{ 28{
@@ -25,4 +31,76 @@ safe_strshare(Eina_Stringshare* strsh)
25 return ret; 31 return ret;
26} 32}
27 33
34/// @brief Get a lower-case copy of string.
35///
36inline std::string
37safe_lower(std::string const& s)
38{
39 std::string res;
40 res.resize(s.size());
41 std::transform(s.begin(), s.end(), res.begin(), ::tolower);
42 return res;
43}
44
45/// @brief Get a lower-case copy of string.
46///
47inline std::string
48safe_lower(const char *s)
49{
50 return safe_lower(safe_str(s));
51}
52
53/// @brief Get a upper-case copy of string.
54///
55inline std::string
56safe_upper(std::string const& s)
57{
58 std::string res;
59 res.resize(s.size());
60 std::transform(s.begin(), s.end(), res.begin(), ::toupper);
61 return res;
62}
63
64/// @brief Get a upper-case copy of string.
65///
66inline std::string
67safe_upper(const char* s)
68{
69 return safe_upper(safe_str(s));
70}
71
72/// @brief Trim both ends of the string and replaces any
73/// subsequence of contiguous spaces with a single space.
74///
75inline std::string
76normalize_spaces(std::string const& s)
77{
78 std::ostringstream os;
79 bool prev_is_space = true;
80 std::remove_copy_if
81 (s.begin(), s.end(),
82 std::ostream_iterator<char>(os),
83 [&prev_is_space] (char c)
84 {
85 bool r = ::isspace(c);
86 if (r && prev_is_space)
87 return true;
88 prev_is_space = r;
89 return false;
90 });
91 std::string r = os.str();
92 if (!r.empty() && ::isspace(r.back()))
93 r.erase(r.end()-1, r.end());
94 return r;
95}
96
97inline std::string
98path_base(std::string path)
99{
100 std::string::reverse_iterator
101 slash = std::find(path.rbegin(), path.rend(), '/');
102 return std::string(slash.base(), path.end());
103}
104
105
28#endif // EOLIAN_CXX_BIN_SAFE_STRINGS_HH 106#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
index 0000000000..a85be2dfac
--- /dev/null
+++ b/src/bin/eolian_cxx/type_lookup.hh
@@ -0,0 +1,37 @@
1
2#ifndef EOLIAN_CXX_TYPE_LOOKUP_HH
3#define EOLIAN_CXX_TYPE_LOOKUP_HH
4
5#include <iostream>
6#include <algorithm>
7#include <string>
8#include <vector>
9#include <cctype>
10#include <iterator>
11#include <cassert>
12#include <cstddef>
13
14#include <Eolian.h>
15#include <Eina.hh>
16
17#include "eo_types.hh"
18#include "safe_strings.hh"
19
20namespace eolian_cxx {
21
22inline std::string
23type_lookup(Eolian_Type type)
24{
25 if (type == NULL)
26 return "void";
27 // XXX add complex types implementation.
28 const char *tps = eolian_type_c_type_get(type);
29 std::string ret = normalize_spaces(safe_str(tps));
30 ::eina_stringshare_del(tps);
31 return ret;
32}
33
34
35} // namespace eolian_cxx {
36
37#endif // EOLIAN_CXX_TYPE_LOOKUP_HH