summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-11-22 16:54:57 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-12-05 10:14:03 +0900
commit5425baa9061753356d450a3c736669341e1b1570 (patch)
treea008cad3e6be4c7d5a2f5e79425ddf27cc6a6a68 /src/bin
parenta597084db7b3a8a4bc7320b68aee7cbb34c6da43 (diff)
cxx: Add support for function pointers
This was tested on the function pointer Efl.Ui.Format_Func_Cb
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/eolian_cxx/eolian_cxx.cc115
1 files changed, 108 insertions, 7 deletions
diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc
index 3fab179cae..b67d0442b9 100644
--- a/src/bin/eolian_cxx/eolian_cxx.cc
+++ b/src/bin/eolian_cxx/eolian_cxx.cc
@@ -25,6 +25,7 @@
25#include "grammar/klass_def.hpp" 25#include "grammar/klass_def.hpp"
26#include "grammar/header.hpp" 26#include "grammar/header.hpp"
27#include "grammar/impl_header.hpp" 27#include "grammar/impl_header.hpp"
28#include "grammar/types_definition.hpp"
28 29
29namespace eolian_cxx { 30namespace eolian_cxx {
30 31
@@ -58,7 +59,8 @@ opts_check(eolian_cxx::options_type const& opts)
58} 59}
59 60
60static bool 61static bool
61generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts) 62generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts,
63 std::string const& cpp_types_header)
62{ 64{
63 std::string header_decl_file_name = opts.out_file.empty() 65 std::string header_decl_file_name = opts.out_file.empty()
64 ? (::eolian_class_file_get(klass) + std::string(".hh")) : opts.out_file; 66 ? (::eolian_class_file_get(klass) + std::string(".hh")) : opts.out_file;
@@ -143,9 +145,9 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
143 } 145 }
144 }; 146 };
145 klass_function(klass); 147 klass_function(klass);
146 148
147 cpp_headers.erase(eolian_class_file_get(klass) + std::string(".hh")); 149 cpp_headers.erase(eolian_class_file_get(klass) + std::string(".hh"));
148 150
149 std::string guard_name; 151 std::string guard_name;
150 as_generator(*(efl::eolian::grammar::string << "_") << efl::eolian::grammar::string << "_EO_HH") 152 as_generator(*(efl::eolian::grammar::string << "_") << efl::eolian::grammar::string << "_EO_HH")
151 .generate(std::back_insert_iterator<std::string>(guard_name) 153 .generate(std::back_insert_iterator<std::string>(guard_name)
@@ -153,12 +155,13 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
153 , efl::eolian::grammar::context_null{}); 155 , efl::eolian::grammar::context_null{});
154 156
155 std::tuple<std::string, std::set<std::string>&, std::set<std::string>& 157 std::tuple<std::string, std::set<std::string>&, std::set<std::string>&
158 , std::string const&
156 , std::vector<efl::eolian::grammar::attributes::klass_def>& 159 , std::vector<efl::eolian::grammar::attributes::klass_def>&
157 , std::vector<efl::eolian::grammar::attributes::klass_def>& 160 , std::vector<efl::eolian::grammar::attributes::klass_def>&
158 , std::vector<efl::eolian::grammar::attributes::klass_def>& 161 , std::vector<efl::eolian::grammar::attributes::klass_def>&
159 , std::vector<efl::eolian::grammar::attributes::klass_def>& 162 , std::vector<efl::eolian::grammar::attributes::klass_def>&
160 > attributes 163 > attributes
161 {guard_name, c_headers, cpp_headers, klasses, forward_klasses, klasses, klasses}; 164 {guard_name, c_headers, cpp_headers, cpp_types_header, klasses, forward_klasses, klasses, klasses};
162 165
163 if(opts.out_file == "-") 166 if(opts.out_file == "-")
164 { 167 {
@@ -205,19 +208,117 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
205 return true; 208 return true;
206} 209}
207 210
211static bool
212types_generate(std::string const& fname, options_type const& opts,
213 std::string& cpp_types_header)
214{
215 using namespace efl::eolian::grammar::attributes;
216
217 std::vector<function_def> functions;
218 Eina_Iterator *itr = eolian_declarations_get_by_file(fname.c_str());
219 /* const */ Eolian_Declaration *decl;
220
221 // Build list of functions with their parameters
222 while(::eina_iterator_next(itr, reinterpret_cast<void**>(&decl)))
223 {
224 Eolian_Declaration_Type dt = eolian_declaration_type_get(decl);
225 if (dt != EOLIAN_DECL_ALIAS)
226 continue;
227
228 const Eolian_Typedecl *tp = eolian_declaration_data_type_get(decl);
229 if (!tp || eolian_typedecl_is_extern(tp))
230 continue;
231
232 if (::eolian_typedecl_type_get(tp) != EOLIAN_TYPEDECL_FUNCTION_POINTER)
233 continue;
234
235 const Eolian_Function *func = eolian_typedecl_function_pointer_get(tp);
236 if (!func) return false;
237
238 Eina_Iterator *param_itr = eolian_function_parameters_get(func);
239 std::vector<parameter_def> params;
240
241 /* const */ Eolian_Function_Parameter *param;
242 while (::eina_iterator_next(param_itr, reinterpret_cast<void **>(&param)))
243 {
244 parameter_direction param_dir;
245 switch (eolian_parameter_direction_get(param))
246 {
247 /* Note: Inverted on purpose, as the direction objects are
248 * passed is inverted (from C to C++ for function pointers).
249 * FIXME: This is probably not right in all cases. */
250 case EOLIAN_IN_PARAM: param_dir = parameter_direction::out; break;
251 case EOLIAN_INOUT_PARAM: param_dir = parameter_direction::inout; break;
252 case EOLIAN_OUT_PARAM: param_dir = parameter_direction::in; break;
253 default: return false;
254 }
255
256 const Eolian_Type *param_type_eolian = eolian_parameter_type_get(param);
257 type_def param_type(param_type_eolian, opts.unit, EOLIAN_C_TYPE_PARAM);
258 std::string param_name = eolian_parameter_name_get(param);
259 std::string param_c_type = eolian_type_c_type_get(param_type_eolian, EOLIAN_C_TYPE_PARAM);
260 parameter_def param_def(param_dir, param_type, param_name, param_c_type);
261 params.push_back(std::move(param_def));
262 }
263 ::eina_iterator_free(param_itr);
264
265 const Eolian_Type *ret_type_eolian = eolian_function_return_type_get(func, EOLIAN_FUNCTION_POINTER);
266
267 type_def ret_type = void_;
268 if (ret_type_eolian)
269 ret_type = type_def(ret_type_eolian, opts.unit, EOLIAN_C_TYPE_RETURN);
270
271 /*
272 // List namespaces. Not used as function_wrapper lives in efl::eolian.
273 std::vector<std::string> namespaces;
274 Eina_Iterator *ns_itr = eolian_typedecl_namespaces_get(tp);
275 char *ns;
276 while (::eina_iterator_next(ns_itr, reinterpret_cast<void**>(&ns)))
277 namespaces.push_back(std::string(ns));
278 ::eina_iterator_free(ns_itr);
279 */
280
281 std::string name = eolian_function_name_get(func);
282 std::string c_name = eolian_typedecl_full_name_get(tp);
283 std::replace(c_name.begin(), c_name.end(), '.', '_');
284 bool beta = eolian_function_is_beta(func);
285
286 function_def def(ret_type, name, params, c_name, beta, false, true);
287 functions.push_back(std::move(def));
288 }
289 ::eina_iterator_free(itr);
290
291 if (functions.empty())
292 return true;
293
294 std::stringstream sink;
295
296 sink.write("\n", 1);
297 if (!efl::eolian::grammar::types_definition
298 .generate(std::ostream_iterator<char>(sink),
299 functions, efl::eolian::grammar::context_null()))
300 return false;
301
302 cpp_types_header = sink.str();
303
304 return true;
305}
306
208static void 307static void
209run(options_type const& opts) 308run(options_type const& opts)
210{ 309{
211 if(!opts.main_header) 310 if(!opts.main_header)
212 { 311 {
213 const Eolian_Class *klass = NULL; 312 const Eolian_Class *klass = nullptr;
214 char* dup = strdup(opts.in_files[0].c_str()); 313 char* dup = strdup(opts.in_files[0].c_str());
215 char* base = basename(dup); 314 char* base = basename(dup);
216 klass = ::eolian_class_get_by_file(NULL, base); 315 std::string cpp_types_header;
316 klass = ::eolian_class_get_by_file(nullptr, base);
217 free(dup); 317 free(dup);
218 if (klass) 318 if (klass)
219 { 319 {
220 if (!generate(klass, opts)) 320 if (!types_generate(base, opts, cpp_types_header) ||
321 !generate(klass, opts, cpp_types_header))
221 { 322 {
222 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) 323 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
223 << "Error generating: " << ::eolian_class_name_get(klass) 324 << "Error generating: " << ::eolian_class_name_get(klass)