efl/src/bin/eolian_cxx/eolian_cxx.cc

547 lines
18 KiB
C++
Raw Normal View History

/*
* Copyright 2019 by its authors. See AUTHORS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <libgen.h>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <iosfwd>
#include <type_traits>
#include <cassert>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eolian.h>
#include <Eina.hh>
#include <Eolian_Cxx.hh>
#include "grammar/klass_def.hpp"
#include "grammar/header.hpp"
#include "grammar/impl_header.hpp"
#include "grammar/types_definition.hpp"
namespace eolian_cxx {
/// Program options.
struct options_type
{
std::vector<std::string> include_dirs;
std::vector<std::string> in_files;
mutable Eolian_State* state;
mutable Eolian_Unit const* unit;
std::string out_file;
bool main_header;
options_type() : main_header(false) {}
};
static efl::eina::log_domain domain("eolian_cxx");
static bool
opts_check(eolian_cxx::options_type const& opts)
{
if (opts.in_files.empty())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Nothing to generate?" << std::endl;
}
else
{
return true; // valid.
}
return false;
}
static bool
generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts,
std::string const& cpp_types_header)
{
std::string header_decl_file_name = opts.out_file.empty()
? (::eolian_object_file_get((const Eolian_Object *)klass) + std::string(".hh")) : opts.out_file;
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
std::string header_impl_file_name = header_decl_file_name;
std::size_t dot_pos = header_impl_file_name.rfind(".hh");
if (dot_pos != std::string::npos)
header_impl_file_name.insert(dot_pos, ".impl");
else
header_impl_file_name.insert(header_impl_file_name.size(), ".impl");
efl::eolian::grammar::attributes::klass_def klass_def(klass, opts.unit);
std::vector<efl::eolian::grammar::attributes::klass_def> klasses{klass_def};
std::set<efl::eolian::grammar::attributes::klass_def> forward_klasses{};
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
std::set<std::string> c_headers;
std::set<std::string> cpp_headers;
c_headers.insert(eolian_object_file_get((const Eolian_Object *)klass) + std::string(".h"));
std::function<void(efl::eolian::grammar::attributes::type_def const&)>
variant_function;
auto klass_name_function
= [&] (efl::eolian::grammar::attributes::klass_name const& name)
{
Eolian_Class const* klass2 = get_klass(name, opts.unit);
assert(klass2);
c_headers.insert(eolian_object_file_get((const Eolian_Object *)klass2) + std::string(".h"));
cpp_headers.insert(eolian_object_file_get((const Eolian_Object *)klass2) + std::string(".hh"));
efl::eolian::grammar::attributes::klass_def cls{klass2, opts.unit};
forward_klasses.insert(cls);
};
auto complex_function
= [&] (efl::eolian::grammar::attributes::complex_type_def const& complex)
{
for(auto&& t : complex.subtypes)
{
variant_function(t);
}
};
variant_function = [&] (efl::eolian::grammar::attributes::type_def const& type)
{
if(efl::eolian::grammar::attributes::klass_name const*
2016-08-15 10:47:00 -07:00
name = efl::eina::get<efl::eolian::grammar::attributes::klass_name>
(&type.original_type))
klass_name_function(*name);
else if(efl::eolian::grammar::attributes::complex_type_def const*
2016-08-15 10:47:00 -07:00
complex = efl::eina::get<efl::eolian::grammar::attributes::complex_type_def>
(&type.original_type))
complex_function(*complex);
};
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
std::function<void(Eolian_Class const*)> klass_function
= [&] (Eolian_Class const* klass2)
{
if(::eolian_class_parent_get(klass2))
{
Eolian_Class const* inherit = ::eolian_class_parent_get(klass2);
c_headers.insert(eolian_object_file_get((const Eolian_Object *)inherit) + std::string(".h"));
cpp_headers.insert(eolian_object_file_get((const Eolian_Object *)inherit) + std::string(".hh"));
efl::eolian::grammar::attributes::klass_def klass3{inherit, opts.unit};
forward_klasses.insert(klass3);
klass_function(inherit);
}
for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( ::eolian_class_extensions_get(klass2))
, inherit_last; inherit_iterator != inherit_last; ++inherit_iterator)
{
Eolian_Class const* inherit = &*inherit_iterator;
c_headers.insert(eolian_object_file_get((const Eolian_Object *)inherit) + std::string(".h"));
cpp_headers.insert(eolian_object_file_get((const Eolian_Object *)inherit) + std::string(".hh"));
efl::eolian::grammar::attributes::klass_def klass3{inherit, opts.unit};
forward_klasses.insert(klass3);
klass_function(inherit);
}
efl::eolian::grammar::attributes::klass_def klass2_def(klass2, opts.unit);
for(auto&& f : klass2_def.functions)
{
variant_function(f.return_type);
for(auto&& p : f.parameters)
{
variant_function(p.type);
}
}
for(auto&& e : klass2_def.events)
{
if(e.type)
variant_function(*e.type);
}
};
klass_function(klass);
for(efl::eina::iterator<Eolian_Part const> parts_itr ( ::eolian_class_parts_get(klass))
, parts_last; parts_itr != parts_last; ++parts_itr)
{
Eolian_Class const* eolian_part_klass = ::eolian_part_class_get(&*parts_itr);
efl::eolian::grammar::attributes::klass_def part_klass(eolian_part_klass, opts.unit);
forward_klasses.insert(part_klass);
}
cpp_headers.erase(eolian_object_file_get((const Eolian_Object *)klass) + std::string(".hh"));
std::string guard_name;
as_generator(*(efl::eolian::grammar::string << "_") << efl::eolian::grammar::string << "_EO_HH")
.generate(std::back_insert_iterator<std::string>(guard_name)
, std::make_tuple(klass_def.namespaces, klass_def.eolian_name)
, efl::eolian::grammar::context_null{});
std::tuple<std::string, std::set<std::string>&, std::set<std::string>&
, std::vector<efl::eolian::grammar::attributes::klass_def>&
, std::set<efl::eolian::grammar::attributes::klass_def> const&
, std::string const&
, std::vector<efl::eolian::grammar::attributes::klass_def>&
, std::vector<efl::eolian::grammar::attributes::klass_def>&
> attributes
{guard_name, c_headers, cpp_headers, klasses, forward_klasses, cpp_types_header, klasses, klasses};
if(opts.out_file == "-")
{
std::ostream_iterator<char> iterator(std::cout);
efl::eolian::grammar::class_header.generate(iterator, attributes, efl::eolian::grammar::context_null());
std::endl(std::cout);
efl::eolian::grammar::impl_header.generate(iterator, klasses, efl::eolian::grammar::context_null());
std::endl(std::cout);
std::flush(std::cout);
std::flush(std::cerr);
}
else
{
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
std::ofstream header_decl;
header_decl.open(header_decl_file_name);
if (!header_decl.good())
{
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Can't open output file: " << header_decl_file_name << std::endl;
return false;
}
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
std::ofstream header_impl;
header_impl.open(header_impl_file_name);
if (!header_impl.good())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
<< "Can't open output file: " << header_impl_file_name << std::endl;
return false;
}
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
efl::eolian::grammar::class_header.generate
(std::ostream_iterator<char>(header_decl), attributes, efl::eolian::grammar::context_null());
efl::eolian::grammar::impl_header.generate
(std::ostream_iterator<char>(header_impl), klasses, efl::eolian::grammar::context_null());
eolian_cxx: Add protected methods and events to C++ wrappers and fixes Using eina::string_view in eolian generated interfaces (instead of std::string) to allow lightweight passing of both C strings and C++ std::string. Also, No longer using eina::optional in generated headers for types that already implements the concept of null state (like Eo wrappers and eina_accessor). Also fix allocating callback objects require by class methods (i.e. static) in static vectors so the memory will be freed when the programs exit. Added a new test case for testing callbacks on class methods. Moved method definitions and supplementary code from generated C++ wrappers to auxiliary header file (.eo.impl.hh) generated together with the main ".eo.hh" file. Updated Makefiles to list such files in the compilation and cleanup processes. Updated .gitignore to include these new generated files. Made general adjustments on the documentation of generated C++ wrappers Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in order to make some adjustments for better documentation in the C++ generated headers. Excluding generation of documentation for classes in the "eo_cxx" namespace (the namespace for "abstract" eolian C++ wrappers). Now generating the documentation for the events too. Hiding some auxiliary code from being documented. Some aesthetic adjustments for generated white space. Generate documentation for the main constructor of C++ wrappers and added auxiliary grammars to list parameters names.
2015-01-12 06:00:59 -08:00
header_impl.close();
header_decl.close();
}
return true;
}
static bool
types_generate(std::string const& fname, options_type const& opts,
std::string& cpp_types_header)
{
using namespace efl::eolian::grammar::attributes;
std::vector<function_def> functions;
Eina_Iterator *itr = eolian_state_objects_by_file_get(opts.state, fname.c_str());
/* const */ Eolian_Object *decl;
// Build list of functions with their parameters
while(::eina_iterator_next(itr, reinterpret_cast<void**>(&decl)))
{
Eolian_Object_Type dt = eolian_object_type_get(decl);
if (dt != EOLIAN_OBJECT_TYPEDECL)
continue;
2018-03-08 15:40:53 -08:00
const Eolian_Typedecl *tp = (const Eolian_Typedecl *)decl;
if (eolian_typedecl_is_extern(tp))
continue;
if (::eolian_typedecl_type_get(tp) != EOLIAN_TYPEDECL_FUNCTION_POINTER)
continue;
const Eolian_Function *func = eolian_typedecl_function_pointer_get(tp);
if (!func) return false;
function_def def(func, EOLIAN_FUNCTION_POINTER, tp, opts.unit);
2018-03-12 08:28:28 -07:00
def.c_name = eolian_typedecl_name_get(tp);
std::replace(def.c_name.begin(), def.c_name.end(), '.', '_');
functions.push_back(std::move(def));
}
::eina_iterator_free(itr);
if (functions.empty())
return true;
std::stringstream sink;
sink.write("\n", 1);
if (!efl::eolian::grammar::types_definition
.generate(std::ostream_iterator<char>(sink),
functions, efl::eolian::grammar::context_null()))
return false;
cpp_types_header = sink.str();
return true;
}
static void
run(options_type const& opts)
{
if(!opts.main_header)
{
const Eolian_Class *klass = nullptr;
char* dup = strdup(opts.in_files[0].c_str());
std::string base (basename(dup));
std::string cpp_types_header;
opts.unit = (Eolian_Unit*)opts.state;
klass = ::eolian_state_class_by_file_get(opts.state, base.c_str());
free(dup);
if (klass)
{
if (!types_generate(base, opts, cpp_types_header) ||
!generate(klass, opts, cpp_types_header))
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
2018-03-12 08:03:37 -07:00
<< "Error generating: " << ::eolian_class_short_name_get(klass)
<< std::endl;
assert(false && "error generating class");
}
}
else
{
if (!types_generate(base, opts, cpp_types_header))
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Error generating: " << ::eolian_class_short_name_get(klass)
<< std::endl;
assert(false && "error generating class");
}
else
{
std::ofstream header_decl;
header_decl.open(opts.out_file);
if (!header_decl.good())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Can't open output file: " << opts.out_file << std::endl;
assert(false && "error opening file");
}
std::copy (cpp_types_header.begin(), cpp_types_header.end()
, std::ostream_iterator<char>(header_decl));
}
}
}
else
{
std::set<std::string> headers;
std::set<std::string> eo_files;
for(auto&& name : opts.in_files)
{
Eolian_Unit const* unit = ::eolian_state_file_path_parse(opts.state, name.c_str());
if(!unit)
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Failed parsing: " << name << ".";
}
else
{
if(!opts.unit)
opts.unit = unit;
}
char* dup = strdup(name.c_str());
std::string base(basename(dup));
Eolian_Class const* klass = ::eolian_state_class_by_file_get(opts.state, base.c_str());
free(dup);
if (klass)
{
std::string filename = eolian_object_file_get((const Eolian_Object *)klass);
headers.insert(filename + std::string(".hh"));
eo_files.insert(filename);
}
else
{
headers.insert (base + std::string(".hh"));
}
}
using efl::eolian::grammar::header_include_directive;
using efl::eolian::grammar::implementation_include_directive;
auto main_header_grammar =
*header_include_directive // sequence<string>
<< *implementation_include_directive // sequence<string>
;
std::tuple<std::set<std::string>&, std::set<std::string>&> attributes{headers, eo_files};
std::ofstream main_header;
main_header.open(opts.out_file);
if (!main_header.good())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Can't open output file: " << opts.out_file << std::endl;
return;
}
main_header_grammar.generate(std::ostream_iterator<char>(main_header)
, attributes, efl::eolian::grammar::context_null());
}
}
static void
database_load(options_type const& opts)
{
for (auto src : opts.include_dirs)
{
if (!::eolian_state_directory_add(opts.state, src.c_str()))
{
EINA_CXX_DOM_LOG_WARN(eolian_cxx::domain)
<< "Couldn't load eolian from '" << src << "'.";
}
}
if (!::eolian_state_all_eot_files_parse(opts.state))
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Eolian failed parsing eot files";
assert(false && "Error parsing eot files");
}
if (opts.in_files.empty())
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "No input file.";
assert(false && "Error parsing input file");
}
if (!opts.main_header && !::eolian_state_file_path_parse(opts.state, opts.in_files[0].c_str()))
{
EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
<< "Failed parsing: " << opts.in_files[0] << ".";
assert(false && "Error parsing input file");
}
}
} // namespace eolian_cxx {
static void
_print_version()
{
std::cerr
<< "Eolian C++ Binding Generator (EFL "
<< PACKAGE_VERSION << ")" << std::endl;
}
static void
_usage(const char *progname)
{
std::cerr
<< progname
<< " [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
<< " -D, --out-dir <dir> Output directory where generated code will be written." << std::endl
<< " -I, --in <file/dir> The source containing the .eo descriptions." << std::endl
<< " -o, --out-file <file> The output file name. [default: <classname>.eo.hh]" << std::endl
<< " -n, --namespace <ns> Wrap generated code in a namespace. [Eg: efl::ecore::file]" << std::endl
<< " -r, --recurse Recurse input directories loading .eo files." << std::endl
<< " -v, --version Print the version." << std::endl
<< " -h, --help Print this help." << std::endl;
exit(EXIT_FAILURE);
}
static void
_assert_not_dup(std::string option, std::string value)
{
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[] =
{
{ "in", required_argument, nullptr, 'I' },
{ "out-file", required_argument, nullptr, 'o' },
{ "version", no_argument, nullptr, 'v' },
{ "help", no_argument, nullptr, 'h' },
{ "main-header", no_argument, nullptr, 'm' },
{ nullptr, 0, nullptr, 0 }
};
const char* options = "I:D:o:c::marvh";
int c, idx;
while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1)
{
if (c == 'I')
{
opts.include_dirs.push_back(optarg);
}
else if (c == 'o')
{
_assert_not_dup("o", opts.out_file);
opts.out_file = optarg;
}
else if (c == 'h')
{
_usage(argv[0]);
}
else if(c == 'm')
{
opts.main_header = true;
}
else if (c == 'v')
{
_print_version();
if (argc == 2) exit(EXIT_SUCCESS);
}
}
if (optind != argc)
{
for(int i = optind; i != argc; ++i)
opts.in_files.push_back(argv[i]);
}
if (!eolian_cxx::opts_check(opts))
{
_usage(argv[0]);
assert(false && "Wrong options passed in command-line");
}
return opts;
}
int main(int argc, char **argv)
{
try
{
efl::eina::eina_init eina_init;
efl::eolian::eolian_init eolian_init;
efl::eolian::eolian_state eolian_state;
eolian_cxx::options_type opts = opts_get(argc, argv);
opts.state = eolian_state.value;
eolian_cxx::database_load(opts);
eolian_cxx::run(opts);
}
catch(std::exception const& e)
{
std::cerr << "EOLCXX: Eolian C++ failed generation for the following reason: " << e.what() << std::endl;
std::cout << "EOLCXX: Eolian C++ failed generation for the following reason: " << e.what() << std::endl;
return -1;
}
return 0;
}