summaryrefslogtreecommitdiff
path: root/src/bin/eolian_cxx
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2017-01-18 22:25:02 -0200
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2017-01-18 22:47:04 -0200
commita1f2db255b22052050baf0c04bb72146b22a6e99 (patch)
tree8499c057a7a0054f75fe3ab4719b2cc3659949d5 /src/bin/eolian_cxx
parent7f148feea8275d4ae3a366e5aead8170498089a6 (diff)
cxx: Modify how to generate C++ headers and allow cyclic dependencies
Allow cyclic dependencies in generated C++ headers by changing order of includes and creating forward declarations.
Diffstat (limited to 'src/bin/eolian_cxx')
-rw-r--r--src/bin/eolian_cxx/eolian_cxx.cc129
1 files changed, 95 insertions, 34 deletions
diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc
index 24a9dd62a1..18978a3fe9 100644
--- a/src/bin/eolian_cxx/eolian_cxx.cc
+++ b/src/bin/eolian_cxx/eolian_cxx.cc
@@ -32,8 +32,11 @@ namespace eolian_cxx {
32struct options_type 32struct options_type
33{ 33{
34 std::vector<std::string> include_dirs; 34 std::vector<std::string> include_dirs;
35 std::string in_file; 35 std::vector<std::string> in_files;
36 std::string out_file; 36 std::string out_file;
37 bool main_header;
38
39 options_type() : main_header(false) {}
37}; 40};
38 41
39efl::eina::log_domain domain("eolian_cxx"); 42efl::eina::log_domain domain("eolian_cxx");
@@ -41,7 +44,7 @@ efl::eina::log_domain domain("eolian_cxx");
41static bool 44static bool
42opts_check(eolian_cxx::options_type const& opts) 45opts_check(eolian_cxx::options_type const& opts)
43{ 46{
44 if (opts.in_file.empty()) 47 if (opts.in_files.empty())
45 { 48 {
46 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) 49 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
47 << "Nothing to generate?" << std::endl; 50 << "Nothing to generate?" << std::endl;
@@ -68,6 +71,7 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
68 71
69 efl::eolian::grammar::attributes::klass_def klass_def(klass); 72 efl::eolian::grammar::attributes::klass_def klass_def(klass);
70 std::vector<efl::eolian::grammar::attributes::klass_def> klasses{klass_def}; 73 std::vector<efl::eolian::grammar::attributes::klass_def> klasses{klass_def};
74 std::vector<efl::eolian::grammar::attributes::klass_def> forward_klasses{klass_def};
71 75
72 std::set<std::string> c_headers; 76 std::set<std::string> c_headers;
73 std::set<std::string> cpp_headers; 77 std::set<std::string> cpp_headers;
@@ -82,6 +86,9 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
82 assert(klass); 86 assert(klass);
83 c_headers.insert(eolian_class_file_get(klass) + std::string(".h")); 87 c_headers.insert(eolian_class_file_get(klass) + std::string(".h"));
84 cpp_headers.insert(eolian_class_file_get(klass) + std::string(".hh")); 88 cpp_headers.insert(eolian_class_file_get(klass) + std::string(".hh"));
89 efl::eolian::grammar::attributes::klass_def cls{klass};
90 if(std::find(forward_klasses.begin(), forward_klasses.end(), cls) == forward_klasses.end())
91 forward_klasses.push_back(cls);
85 }; 92 };
86 auto complex_function 93 auto complex_function
87 = [&] (efl::eolian::grammar::attributes::complex_type_def const& complex) 94 = [&] (efl::eolian::grammar::attributes::complex_type_def const& complex)
@@ -112,6 +119,9 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
112 Eolian_Class const* inherit = ::eolian_class_get_by_name(&*inherit_iterator); 119 Eolian_Class const* inherit = ::eolian_class_get_by_name(&*inherit_iterator);
113 c_headers.insert(eolian_class_file_get(inherit) + std::string(".h")); 120 c_headers.insert(eolian_class_file_get(inherit) + std::string(".h"));
114 cpp_headers.insert(eolian_class_file_get(inherit) + std::string(".hh")); 121 cpp_headers.insert(eolian_class_file_get(inherit) + std::string(".hh"));
122 efl::eolian::grammar::attributes::klass_def klass{inherit};
123 if(std::find(forward_klasses.begin(), forward_klasses.end(), klass) == forward_klasses.end())
124 forward_klasses.push_back(klass);
115 125
116 klass_function(inherit); 126 klass_function(inherit);
117 } 127 }
@@ -147,7 +157,7 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
147 , std::vector<efl::eolian::grammar::attributes::klass_def>& 157 , std::vector<efl::eolian::grammar::attributes::klass_def>&
148 , std::vector<efl::eolian::grammar::attributes::klass_def>& 158 , std::vector<efl::eolian::grammar::attributes::klass_def>&
149 > attributes 159 > attributes
150 {guard_name, c_headers, cpp_headers, klasses, klasses, klasses, klasses}; 160 {guard_name, c_headers, cpp_headers, klasses, forward_klasses, klasses, klasses};
151 161
152 if(opts.out_file == "-") 162 if(opts.out_file == "-")
153 { 163 {
@@ -182,15 +192,11 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
182 return false; 192 return false;
183 } 193 }
184 194
185#if 1
186 efl::eolian::grammar::class_header.generate 195 efl::eolian::grammar::class_header.generate
187 (std::ostream_iterator<char>(header_decl), attributes, efl::eolian::grammar::context_null()); 196 (std::ostream_iterator<char>(header_decl), attributes, efl::eolian::grammar::context_null());
188 197
189 efl::eolian::grammar::impl_header.generate 198 efl::eolian::grammar::impl_header.generate
190 (std::ostream_iterator<char>(header_impl), klasses, efl::eolian::grammar::context_null()); 199 (std::ostream_iterator<char>(header_impl), klasses, efl::eolian::grammar::context_null());
191#else
192 efl::eolian::generate(header_decl, header_impl, cls, gen_opts);
193#endif
194 200
195 header_impl.close(); 201 header_impl.close();
196 header_decl.close(); 202 header_decl.close();
@@ -201,26 +207,75 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
201static void 207static void
202run(options_type const& opts) 208run(options_type const& opts)
203{ 209{
204 const Eolian_Class *klass = NULL; 210 if(!opts.main_header)
205 char* dup = strdup(opts.in_file.c_str());
206 char* base = basename(dup);
207 klass = ::eolian_class_get_by_file(base);
208 free(dup);
209 if (klass)
210 { 211 {
211 if (!generate(klass, opts)) 212 const Eolian_Class *klass = NULL;
212 goto err; 213 char* dup = strdup(opts.in_files[0].c_str());
214 char* base = basename(dup);
215 klass = ::eolian_class_get_by_file(base);
216 free(dup);
217 if (klass)
218 {
219 if (!generate(klass, opts))
220 {
221 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
222 << "Error generating: " << ::eolian_class_name_get(klass)
223 << std::endl;
224 assert(false && "error generating class");
225 }
226 }
227 else
228 {
229 std::abort();
230 }
213 } 231 }
214 else 232 else
215 { 233 {
216 std::abort(); 234 std::set<std::string> headers;
217 } 235 std::set<std::string> eo_files;
218 return; 236
219 err: 237 for(auto&& name : opts.in_files)
220 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) 238 {
221 << "Error generating: " << ::eolian_class_name_get(klass) 239 bool b = ::eolian_file_parse(name.c_str());
222 << std::endl; 240 if(!b)
223 assert(false && "error generating class"); 241 {
242 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
243 << "Failed parsing: " << name << ".";
244 }
245 char* dup = strdup(name.c_str());
246 char* base = basename(dup);
247 Eolian_Class const* klass = ::eolian_class_get_by_file(base);
248 free(dup);
249 if (klass)
250 {
251 std::string filename = eolian_class_file_get(klass);
252 headers.insert(filename + std::string(".hh"));
253 eo_files.insert(filename);
254 }
255 }
256
257 using efl::eolian::grammar::header_include_directive;
258 using efl::eolian::grammar::implementation_include_directive;
259
260 auto main_header_grammar =
261 *header_include_directive // sequence<string>
262 << *implementation_include_directive // sequence<string>
263 ;
264
265 std::tuple<std::set<std::string>&, std::set<std::string>&> attributes{headers, eo_files};
266
267 std::ofstream main_header;
268 main_header.open(opts.out_file);
269 if (!main_header.good())
270 {
271 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
272 << "Can't open output file: " << opts.out_file << std::endl;
273 return;
274 }
275
276 main_header_grammar.generate(std::ostream_iterator<char>(main_header)
277 , attributes, efl::eolian::grammar::context_null());
278 }
224} 279}
225 280
226static void 281static void
@@ -240,16 +295,16 @@ database_load(options_type const& opts)
240 << "Eolian failed parsing eot files"; 295 << "Eolian failed parsing eot files";
241 assert(false && "Error parsing eot files"); 296 assert(false && "Error parsing eot files");
242 } 297 }
243 if (opts.in_file.empty()) 298 if (opts.in_files.empty())
244 { 299 {
245 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) 300 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
246 << "No input file."; 301 << "No input file.";
247 assert(false && "Error parsing input file"); 302 assert(false && "Error parsing input file");
248 } 303 }
249 if (!::eolian_file_parse(opts.in_file.c_str())) 304 if (!opts.main_header && !::eolian_file_parse(opts.in_files[0].c_str()))
250 { 305 {
251 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) 306 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
252 << "Failed parsing: " << opts.in_file << "."; 307 << "Failed parsing: " << opts.in_files[0] << ".";
253 assert(false && "Error parsing input file"); 308 assert(false && "Error parsing input file");
254 } 309 }
255 if (!::eolian_database_validate()) 310 if (!::eolian_database_validate())
@@ -307,13 +362,14 @@ opts_get(int argc, char **argv)
307 362
308 const struct option long_options[] = 363 const struct option long_options[] =
309 { 364 {
310 { "in", required_argument, 0, 'I' }, 365 { "in", required_argument, 0, 'I' },
311 { "out-file", required_argument, 0, 'o' }, 366 { "out-file", required_argument, 0, 'o' },
312 { "version", no_argument, 0, 'v' }, 367 { "version", no_argument, 0, 'v' },
313 { "help", no_argument, 0, 'h' }, 368 { "help", no_argument, 0, 'h' },
314 { 0, 0, 0, 0 } 369 { "main-header", no_argument, 0, 'm' },
370 { 0, 0, 0, 0 }
315 }; 371 };
316 const char* options = "I:D:o:c:arvh"; 372 const char* options = "I:D:o:c::marvh";
317 373
318 int c, idx; 374 int c, idx;
319 while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1) 375 while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1)
@@ -331,15 +387,20 @@ opts_get(int argc, char **argv)
331 { 387 {
332 _usage(argv[0]); 388 _usage(argv[0]);
333 } 389 }
390 else if(c == 'm')
391 {
392 opts.main_header = true;
393 }
334 else if (c == 'v') 394 else if (c == 'v')
335 { 395 {
336 _print_version(); 396 _print_version();
337 if (argc == 2) exit(EXIT_SUCCESS); 397 if (argc == 2) exit(EXIT_SUCCESS);
338 } 398 }
339 } 399 }
340 if (optind == argc-1) 400 if (optind != argc)
341 { 401 {
342 opts.in_file = argv[optind]; 402 for(int i = optind; i != argc; ++i)
403 opts.in_files.push_back(argv[i]);
343 } 404 }
344 405
345 if (!eolian_cxx::opts_check(opts)) 406 if (!eolian_cxx::opts_check(opts))