Merging 'devs/q66/eolian_experimental'

This gets in several changes - such as new eolian API for deduplication
of names, support for eot files and processing of classes and typedefs
in sequence.
This commit is contained in:
Daniel Kolesa 2014-06-30 17:40:09 +01:00
commit 8d6e47107b
15 changed files with 568 additions and 400 deletions

View File

@ -57,6 +57,7 @@ getopt.parse {
for i, v in ipairs(opts["I"] or {}) do
lualian.include_dir(v)
end
lualian.load_eot_files()
for i, fname in ipairs(args) do
gen_file(opts, i, fname)
end

View File

@ -122,20 +122,6 @@ local typeconv = function(tps, expr, isin)
return build_calln(tps, expr, false)
end
local dedup_name = function(classn, funcn)
local suffix = classn:match(".+_(.+)" ) or classn
local prefix = funcn:match("([^_]+)_.+") or funcn
if prefix == suffix then
if classn == suffix then
return funcn
else
return classn:match("(.+_).+") .. funcn
end
else
return classn .. "_" .. funcn
end
end
local Node = util.Object:clone {
generate = function(self, s)
end,
@ -184,7 +170,7 @@ local Method = Node:clone {
local allocs = {}
proto.allocs = allocs
proto.full_name = dedup_name(self.parent_node.prefix, proto.name)
proto.full_name = meth:full_c_name_get(self.parent_node.prefix)
local dirs = eolian.parameter_dir
@ -280,7 +266,7 @@ local Property = Method:clone {
local allocs = {}
proto.allocs = allocs
proto.full_name = dedup_name(self.parent_node.prefix, proto.name)
proto.full_name = prop:full_c_name_get(self.parent_node.prefix)
.. proto.suffix
local dirs = eolian.parameter_dir
@ -691,6 +677,10 @@ M.include_dir = function(dir)
end
end
M.load_eot_files = function()
return eolian.all_eot_files_parse()
end
M.generate = function(fname, modname, libname, fstream)
if not eolian.eo_file_parse(fname) then
error("Failed parsing file: " .. fname)

View File

@ -50,7 +50,8 @@ _class_env_create(const Eolian_Class class, const char *over_classname, _eolian_
void
_class_func_env_create(const Eolian_Class class, const char *funcname, Eolian_Function_Type ftype, _eolian_class_func_vars *env)
{
char *p, *ret;
char *p;
const char *ret;
const char *suffix = "";
const char *legacy = NULL;
Eolian_Function funcid = eolian_class_function_find_by_name(class, funcname, ftype);
@ -72,15 +73,15 @@ _class_func_env_create(const Eolian_Class class, const char *funcname, Eolian_Fu
p = strncpy(env->upper_func, funcname, PATH_MAX - 1);
eina_str_toupper(&p);
ret = _func_name_dedup(tmp_env.upper_eo_prefix, funcname);
ret = eolian_function_full_c_name_get(funcid, tmp_env.upper_eo_prefix);
sprintf(p = env->upper_eo_func, "%s%s", ret, suffix);
eina_str_toupper(&p);
free(ret);
eina_stringshare_del(ret);
ret = _func_name_dedup(tmp_env.lower_eo_prefix, funcname);
ret = eolian_function_full_c_name_get(funcid, tmp_env.lower_eo_prefix);
sprintf(p = env->lower_eo_func, "%s%s", ret, suffix);
eina_str_tolower(&p);
free(ret);
eina_stringshare_del(ret);
env->legacy_func[0] = '\0';
if (legacy && !strcmp(legacy, "null")) goto end;
@ -164,36 +165,3 @@ _source_desc_get(const char *str)
eina_strbuf_free(part);
return ret;
}
char *
_func_name_dedup(const char *classn, const char *funcn)
{
const char *last_p = strrchr(classn, '_');
const char *func_p = strchr(funcn, '_');
Eina_Strbuf *buf = eina_strbuf_new();
int len;
char *ret;
if (!last_p) last_p = classn;
else last_p++;
if (!func_p) len = strlen(funcn);
else len = func_p - funcn;
if ((int)strlen(last_p) != len || strncmp(last_p, funcn, len))
{
eina_strbuf_append(buf, classn);
eina_strbuf_append_char(buf, '_');
eina_strbuf_append(buf, funcn);
ret = eina_strbuf_string_steal(buf);
eina_strbuf_free(buf);
return ret;
}
if (last_p != classn)
eina_strbuf_append_n(buf, classn, last_p - classn); /* includes _ */
eina_strbuf_append(buf, funcn);
ret = eina_strbuf_string_steal(buf);
eina_strbuf_free(buf);
return ret;
}

View File

@ -66,6 +66,4 @@ void _class_env_create(const Eolian_Class class, const char *over_classname, _eo
void _class_func_env_create(const Eolian_Class class, const char *funcname, Eolian_Function_Type ftype EINA_UNUSED, _eolian_class_func_vars *env);
char *_func_name_dedup(const char *classn, const char *funcn);
#endif

View File

@ -597,8 +597,8 @@ eo_source_end_generate(const Eolian_Class class, Eina_Strbuf *buf)
Eolian_Function_Type ftype;
Eolian_Function fnid = NULL;
const char *funcname = NULL;
const char *ret;
char *tp = implname;
char *ret;
if (eolian_implement_information_get(impl_desc, &impl_class, &fnid, &ftype))
{
@ -616,7 +616,7 @@ eo_source_end_generate(const Eolian_Class class, Eina_Strbuf *buf)
goto end;
}
ret = _func_name_dedup(impl_env.lower_eo_prefix, funcname);
ret = eolian_function_full_c_name_get(fnid, impl_env.lower_eo_prefix);
switch (ftype)
{
case EOLIAN_PROP_SET: case EOLIAN_PROP_GET: case EOLIAN_PROPERTY:
@ -640,7 +640,7 @@ eo_source_end_generate(const Eolian_Class class, Eina_Strbuf *buf)
eo_bind_func_generate(class, fnid, ftype, str_bodyf, &impl_env);
break;
}
free(ret);
eina_stringshare_del(ret);
}
//Constructors

View File

@ -321,6 +321,8 @@ int main(int argc, char **argv)
goto end;
}
eolian_all_eot_files_parse();
const char *filename;
EINA_LIST_FOREACH(files4gen, itr, filename)
{

View File

@ -15,31 +15,11 @@
#include "comments.hh"
static std::string
_dedup_func_name(const std::string &classn, const std::string &funcn)
_dedup_func_name(Eolian_Function func, const std::string &classn)
{
size_t last_p = classn.rfind('_');
size_t func_p = funcn.find('_');
std::string ret;
size_t len;
if (last_p == std::string::npos) last_p = 0;
else last_p++;
if (func_p == std::string::npos) len = funcn.size();
else len = func_p;
if ((classn.size() - last_p) != len
|| classn.compare(last_p, len, funcn, 0, len))
{
ret += classn;
ret += '_';
ret += funcn;
return ret;
}
if (last_p)
ret += classn.substr(0, last_p);
ret += funcn;
const char *s = eolian_function_full_c_name_get(func, classn.c_str());
std::string ret(s);
eina_stringshare_del(s);
return ret;
}
@ -110,7 +90,7 @@ _get_properties(const Eolian_Class klass)
efl::eolian::eo_function getter;
getter.type = efl::eolian::eo_function::regular_;
getter.name = name + "_get";
getter.impl = _dedup_func_name((prefix != "" ? prefix : cxx_classname), getter.name);
getter.impl = _dedup_func_name(property, (prefix != "" ? prefix : cxx_classname)) + "_get";
std::string ret = safe_str
(eolian_function_return_type_get(property, EOLIAN_PROP_GET));
if (ret == "") ret = "void";
@ -155,7 +135,7 @@ _get_properties(const Eolian_Class klass)
efl::eolian::eo_function setter;
setter.type = efl::eolian::eo_function::regular_;
setter.name = name + "_set";
setter.impl = _dedup_func_name((prefix != "" ? prefix : cxx_classname), setter.name);
setter.impl = _dedup_func_name(property, (prefix != "" ? prefix : cxx_classname)) + "_set";
setter.params = params;
setter.ret = safe_str(eolian_function_return_type_get
(property, EOLIAN_PROP_SET));
@ -243,8 +223,8 @@ convert_eolian_constructors(efl::eolian::eo_class& cls, const Eolian_Class klass
{
Eolian_Function eolian_constructor = static_cast<Eolian_Function>(curr);
efl::eolian::eo_constructor constructor;
constructor.name = _dedup_func_name((prefix != "" ? prefix : cls.name),
safe_str(eolian_function_name_get(eolian_constructor)));
constructor.name = _dedup_func_name(eolian_constructor,
(prefix != "" ? prefix : cls.name));
constructor.params = _get_params
(eolian_parameters_list_get(eolian_constructor));
constructor.comment = detail::eolian_constructor_comment
@ -269,7 +249,7 @@ convert_eolian_functions(efl::eolian::eo_class& cls, const Eolian_Class klass)
// XXX Eolian only provides regular methods so far
function.type = efl::eolian::eo_function::regular_;
function.name = safe_str(eolian_function_name_get(eolian_function));
function.impl = _dedup_func_name((prefix != "" ? prefix : cls.name), function.name);
function.impl = _dedup_func_name(eolian_function, (prefix != "" ? prefix : cls.name));
function.ret = safe_str(eolian_function_return_type_get
(eolian_function, EOLIAN_METHOD));
if(function.ret == "") function.ret = "void";

View File

@ -244,12 +244,29 @@ _resolve_classname(options_type& opts)
}
}
static void
_scan_directories(options_type const& opts)
{
for (auto src : opts.in_srcs)
{
if (eina_str_has_suffix(src.c_str(), EO_SUFFIX)) continue;
eolian_read_from_fs(src.c_str());
}
}
static void
_load_eot()
{
eolian_all_eot_files_parse();
}
static void
_load_classes(options_type const& opts)
{
for (auto src : opts.in_srcs)
{
if (eolian_read_from_fs(src.c_str()) == NULL)
if (!eina_str_has_suffix(src.c_str(), EO_SUFFIX)) continue;
if ( eolian_read_from_fs(src.c_str()) == NULL)
{
EINA_CXX_DOM_LOG_WARN(::domain)
<< "Couldn't load eolian file: " << src;
@ -352,6 +369,8 @@ int main(int argc, char **argv)
domain.set_level(efl::eina::log_level::debug);
#endif
options_type opts = _read_options(argc, argv);
_scan_directories(opts);
_load_eot();
_load_classes(opts);
_resolve_classname(opts);
_validate_options(opts);

View File

@ -47,10 +47,12 @@ ffi.cdef [[
} Eolian_Function_Scope;
Eina_Bool eolian_eo_file_parse(const char *filename);
Eina_Bool eolian_eot_file_parse(const char *filepath);
int eolian_init(void);
int eolian_shutdown(void);
Eina_Bool eolian_directory_scan(const char *dir);
Eina_Bool eolian_all_eo_files_parse();
Eina_Bool eolian_all_eot_files_parse();
Eina_Bool eolian_show(const Eolian_Class *klass);
Eolian_Class *eolian_class_find_by_name(const char *class_name);
Eolian_Class *eolian_class_find_by_file(const char *file_name);
@ -69,6 +71,7 @@ ffi.cdef [[
Eolian_Function_Type eolian_function_type_get(Eolian_Function *function_id);
Eolian_Function_Scope eolian_function_scope_get(Eolian_Function *function_id);
const char *eolian_function_name_get(Eolian_Function *function_id);
const char *eolian_function_full_c_name_get(Eolian_Function function_id, const char *prefix);
Eolian_Function *eolian_class_function_find_by_name(const Eolian_Class *klass, const char *func_name, Eolian_Function_Type f_type);
const char *eolian_function_data_get(Eolian_Function *function_id, const char *key);
Eina_Bool eolian_function_is_virtual_pure(Eolian_Function *function_id, Eolian_Function_Type f_type);
@ -134,6 +137,14 @@ M.eo_file_parse = function(fname)
return eolian.eolian_eo_file_parse(fname) ~= 0
end
M.all_eot_files_parse = function()
return eolian.eolian_all_eot_files_parse() ~= 0
end
M.eot_file_parse = function(fname)
return eolian.eolian_eot_file_parse(fname) ~= 0
end
M.show = function(klass)
return eolian.eolian_show(klass) ~= 0
end
@ -180,6 +191,12 @@ M.Function = ffi.metatype("Eolian_Function", {
return ffi.string(v)
end,
full_c_name_get = function(self)
local v = eolian.eolian_function_full_c_name_get(self)
if v == nil then return nil end
return ffi.string(v)
end,
data_get = function(self, key)
local v = eolian.eolian_function_data_get(self, key)
if v == nil then return nil end

View File

@ -120,11 +120,22 @@ typedef enum
* all the information related to this class.
*
* @param[in] filename Name of the file to parse.
* @see eolian_eot_file_parse
*
* @ingroup Eolian
*/
EAPI Eina_Bool eolian_eo_file_parse(const char *filename);
/*
* @brief Parse a given .eot file and fill the database.
*
* @param[in] filename Name of the file to parse.
* @see eolian_eo_file_parse
*
* @ingroup Eolian
*/
EAPI Eina_Bool eolian_eot_file_parse(const char *filepath);
/*
* @brief Init Eolian.
*
@ -140,7 +151,7 @@ EAPI int eolian_init(void);
EAPI int eolian_shutdown(void);
/*
* @brief Scan the given directory and search for .eo files.
* @brief Scan the given directory and search for .eo and .eot files.
*
* The found files are just open to extract the class name.
*
@ -152,17 +163,31 @@ EAPI int eolian_shutdown(void);
EAPI Eina_Bool eolian_directory_scan(const char *dir);
/*
* @brief Force parsing of all the files located in the directories
* @brief Force parsing of all the .eo files located in the directories
* given in eolian_directory_scan..
*
* @return EINA_TRUE on success, EINA_FALSE otherwise.
*
* @see eolian_directory_scan
* @see eolian_all_eot_files_parse
*
* @ingroup Eolian
*/
EAPI Eina_Bool eolian_all_eo_files_parse();
/*
* @brief Force parsing of all the .eot files located in the directories
* given in eolian_directory_scan..
*
* @return EINA_TRUE on success, EINA_FALSE otherwise.
*
* @see eolian_directory_scan
* @see eolian_all_eo_files_parse
*
* @ingroup Eolian
*/
EAPI Eina_Bool eolian_all_eot_files_parse();
/*
* @brief Show information about a given class.
*
@ -356,6 +381,19 @@ EAPI Eolian_Function_Scope eolian_function_scope_get(Eolian_Function function_id
*/
EAPI const char *eolian_function_name_get(Eolian_Function function_id);
/*
* @brief Returns the full C name of a function (with prefix). It's here
* because the C API names are deduplicated (prefix of function and suffix
* of prefix merge if applicable) and this helps generators not write the
* same code over and over.
*
* @param[in] function_id Id of the function
* @return the function name
*
* @ingroup Eolian
*/
EAPI const char *eolian_function_full_c_name_get(Eolian_Function function_id, const char *prefix);
/*
* @brief Find a function in a class by its name and type
*

View File

@ -275,19 +275,28 @@ eo_lexer_set_input(Eo_Lexer *ls, const char *source)
void
eo_lexer_free(Eo_Lexer *ls)
{
Eo_Class_Def *kls;
Eo_Type_Def *type;
Eo_Node *nd;
if (!ls) return;
if (ls->source) eina_stringshare_del(ls->source);
if (ls->buff ) eina_strbuf_free (ls->buff);
if (ls->handle) eina_file_close (ls->handle);
EINA_LIST_FREE(ls->classes, kls)
eo_definitions_class_def_free(kls);
EINA_LIST_FREE(ls->typedefs, type)
eo_definitions_type_def_free(type);
EINA_LIST_FREE(ls->nodes, nd)
{
switch (nd->type)
{
case NODE_CLASS:
eo_definitions_class_def_free(nd->def_class);
break;
case NODE_TYPEDEF:
eo_definitions_type_def_free(nd->def_type);
break;
default:
break;
}
free(nd);
}
eo_definitions_temps_free(&ls->tmp);

View File

@ -42,6 +42,22 @@ typedef struct _Eo_Token
int kw;
} Eo_Token;
enum Nodes
{
NODE_CLASS = 0,
NODE_TYPEDEF
};
typedef struct _Eo_Node
{
unsigned char type;
union {
void *def;
Eo_Class_Def *def_class;
Eo_Type_Def *def_type;
};
} Eo_Node;
typedef struct _Eo_Lexer
{
int current;
@ -54,8 +70,7 @@ typedef struct _Eo_Lexer
const char *stream_end;
jmp_buf err_jmp;
Eina_List *classes;
Eina_List *typedefs;
Eina_List *nodes;
Eo_Lexer_Temps tmp;
} Eo_Lexer;

View File

@ -103,6 +103,15 @@ pop_strbuf(Eo_Lexer *ls)
ls->tmp.str_bufs = eina_list_remove_list(ls->tmp.str_bufs, ls->tmp.str_bufs);
}
static void
append_node(Eo_Lexer *ls, int type, void *def)
{
Eo_Node *nd = calloc(1, sizeof(Eo_Node));
nd->type = type;
nd->def = def;
ls->nodes = eina_list_append(ls->nodes, nd);
}
static Eina_Strbuf *
parse_name(Eo_Lexer *ls, Eina_Strbuf *buf)
{
@ -850,42 +859,49 @@ parse_class(Eo_Lexer *ls, Eina_Bool allow_ctors, Eolian_Class_Type type)
}
static void
parse_unit(Eo_Lexer *ls)
parse_unit(Eo_Lexer *ls, Eina_Bool eot)
{
switch (ls->t.kw)
{
case KW_abstract:
if (eot) goto def;
parse_class(ls, EINA_TRUE, EOLIAN_CLASS_ABSTRACT);
goto found_class;
case KW_class:
if (eot) goto def;
parse_class(ls, EINA_TRUE, EOLIAN_CLASS_REGULAR);
goto found_class;
case KW_mixin:
if (eot) goto def;
parse_class(ls, EINA_FALSE, EOLIAN_CLASS_MIXIN);
goto found_class;
case KW_interface:
if (eot) goto def;
parse_class(ls, EINA_FALSE, EOLIAN_CLASS_INTERFACE);
goto found_class;
case KW_type:
parse_typedef(ls);
ls->typedefs = eina_list_append(ls->typedefs, ls->tmp.type_def);
ls->tmp.type_def = NULL;
break;
{
parse_typedef(ls);
append_node(ls, NODE_TYPEDEF, ls->tmp.type_def);
ls->tmp.type_def = NULL;
break;
}
def:
default:
eo_lexer_syntax_error(ls, "invalid token");
break;
}
return;
found_class:
ls->classes = eina_list_append(ls->classes, ls->tmp.kls);
append_node(ls, NODE_CLASS, ls->tmp.kls);
ls->tmp.kls = NULL;
}
static void
parse_chunk(Eo_Lexer *ls)
parse_chunk(Eo_Lexer *ls, Eina_Bool eot)
{
while (ls->t.token != TOK_EOF)
parse_unit(ls);
parse_unit(ls, eot);
}
static char *_accessor_type_str[ACCESSOR_TYPE_LAST] = { "setter", "getter" };
@ -908,14 +924,12 @@ _print_type(FILE *f, Eolian_Type tp)
}
}
void
eo_parser_dump(Eo_Lexer *ls)
static void
_dump_class(Eo_Class_Def *kls)
{
const char *s;
Eina_List *k, *l, *m;
Eina_List *l, *m;
Eo_Type_Def *type;
Eo_Class_Def *kls;
Eo_Property_Def *prop;
Eo_Method_Def *meth;
Eo_Param_Def *param;
@ -923,112 +937,129 @@ eo_parser_dump(Eo_Lexer *ls)
Eo_Event_Def *sgn;
Eo_Implement_Def *impl;
EINA_LIST_FOREACH(ls->classes, k, kls)
printf("Class: %s (%s)\n",
kls->name, (kls->comment ? kls->comment : "-"));
printf(" inherits from :");
EINA_LIST_FOREACH(kls->inherits, l, s)
printf(" %s", s);
printf("\n");
printf(" implements:");
EINA_LIST_FOREACH(kls->implements, l, impl)
printf(" %s", impl->meth_name);
printf("\n");
printf(" events:\n");
EINA_LIST_FOREACH(kls->events, l, sgn)
printf(" %s <%s> (%s)\n", sgn->name, sgn->type, sgn->comment);
EINA_LIST_FOREACH(kls->constructors, l, meth)
{
printf("Class: %s (%s)\n",
kls->name, (kls->comment ? kls->comment : "-"));
printf(" inherits from :");
EINA_LIST_FOREACH(kls->inherits, l, s)
printf(" %s", s);
printf("\n");
printf(" implements:");
EINA_LIST_FOREACH(kls->implements, l, impl)
printf(" %s", impl->meth_name);
printf("\n");
printf(" events:\n");
EINA_LIST_FOREACH(kls->events, l, sgn)
printf(" %s <%s> (%s)\n", sgn->name, sgn->type, sgn->comment);
EINA_LIST_FOREACH(kls->constructors, l, meth)
printf(" constructors: %s\n", meth->name);
if (meth->ret)
{
printf(" constructors: %s\n", meth->name);
if (meth->ret)
{
printf(" return: ");
_print_type(stdout, meth->ret->type);
printf(" (%s)\n", meth->ret->comment);
}
printf(" legacy : %s\n", meth->legacy);
EINA_LIST_FOREACH(meth->params, m, param)
{
printf(" param: %s %s : ", _param_way_str[param->way], param->name);
_print_type(stdout, param->type);
printf(" (%s)\n", param->comment);
}
printf(" return: ");
_print_type(stdout, meth->ret->type);
printf(" (%s)\n", meth->ret->comment);
}
EINA_LIST_FOREACH(kls->properties, l, prop)
printf(" legacy : %s\n", meth->legacy);
EINA_LIST_FOREACH(meth->params, m, param)
{
printf(" property: %s\n", prop->name);
EINA_LIST_FOREACH(prop->keys, m, param)
{
printf(" key: %s : ", param->name);
_print_type(stdout, param->type);
printf(" (%s)\n", param->comment);
}
EINA_LIST_FOREACH(prop->values, m, param)
{
printf(" value: %s : ", param->name);
_print_type(stdout, param->type);
printf(" (%s)\n", param->comment);
}
EINA_LIST_FOREACH(prop->accessors, m, accessor)
{
printf(" accessor: ");
if (accessor->ret)
_print_type(stdout, accessor->ret->type);
printf(" : %s (%s)\n", _accessor_type_str[accessor->type], accessor->comment);
printf(" legacy : %s\n", accessor->legacy);
}
}
EINA_LIST_FOREACH(kls->methods, l, meth)
{
printf(" method: %s\n", meth->name);
if (meth->ret)
{
printf(" return: ");
_print_type(stdout, meth->ret->type);
printf(" (%s)\n", meth->ret->comment);
}
printf(" legacy : %s\n", meth->legacy);
printf(" obj_const : %s\n", meth->obj_const?"true":"false");
EINA_LIST_FOREACH(meth->params, m, param)
{
printf(" param: %s %s : ", _param_way_str[param->way], param->name);
_print_type(stdout, param->type);
printf(" (%s)\n", param->comment);
}
printf(" param: %s %s : ", _param_way_str[param->way], param->name);
_print_type(stdout, param->type);
printf(" (%s)\n", param->comment);
}
}
EINA_LIST_FOREACH(ls->typedefs, k, type)
EINA_LIST_FOREACH(kls->properties, l, prop)
{
printf("Typedef: %s ", type->alias);
_print_type(stdout, type->type);
printf("\n");
printf(" property: %s\n", prop->name);
EINA_LIST_FOREACH(prop->keys, m, param)
{
printf(" key: %s : ", param->name);
_print_type(stdout, param->type);
printf(" (%s)\n", param->comment);
}
EINA_LIST_FOREACH(prop->values, m, param)
{
printf(" value: %s : ", param->name);
_print_type(stdout, param->type);
printf(" (%s)\n", param->comment);
}
EINA_LIST_FOREACH(prop->accessors, m, accessor)
{
printf(" accessor: ");
if (accessor->ret)
_print_type(stdout, accessor->ret->type);
printf(" : %s (%s)\n", _accessor_type_str[accessor->type], accessor->comment);
printf(" legacy : %s\n", accessor->legacy);
}
}
EINA_LIST_FOREACH(kls->methods, l, meth)
{
printf(" method: %s\n", meth->name);
if (meth->ret)
{
printf(" return: ");
_print_type(stdout, meth->ret->type);
printf(" (%s)\n", meth->ret->comment);
}
printf(" legacy : %s\n", meth->legacy);
printf(" obj_const : %s\n", meth->obj_const?"true":"false");
EINA_LIST_FOREACH(meth->params, m, param)
{
printf(" param: %s %s : ", _param_way_str[param->way], param->name);
_print_type(stdout, param->type);
printf(" (%s)\n", param->comment);
}
}
}
static void
_dump_type(Eo_Type_Def *type)
{
printf("Typedef: %s ", type->alias);
_print_type(stdout, type->type);
printf("\n");
}
void
eo_parser_dump(Eo_Lexer *ls)
{
Eina_List *k;
Eo_Node *nd;
EINA_LIST_FOREACH(ls->nodes, k, nd)
{
switch (nd->type)
{
case NODE_CLASS:
_dump_class(nd->def_class);
break;
case NODE_TYPEDEF:
_dump_type(nd->def_type);
break;
default:
break;
}
}
}
Eina_Bool
eo_parser_walk(Eo_Lexer *ls)
eo_parser_walk(Eo_Lexer *ls, Eina_Bool eot)
{
if (!setjmp(ls->err_jmp))
{
parse_chunk(ls);
parse_chunk(ls, eot);
return EINA_TRUE;
}
return EINA_FALSE;
}
Eina_Bool
eo_parser_database_fill(const char *filename)
static Eina_Bool
_db_fill_class(Eo_Class_Def *kls, const char *filename)
{
const char *s;
Eina_List *k, *l, *m;
Eina_List *l, *m;
Eo_Class_Def *kls;
Eo_Type_Def *type_def;
Eo_Property_Def *prop;
Eo_Method_Def *meth;
Eo_Param_Def *param;
@ -1036,6 +1067,206 @@ eo_parser_database_fill(const char *filename)
Eo_Event_Def *event;
Eo_Implement_Def *impl;
Eolian_Class class = database_class_add(kls->name, kls->type);
Eina_Bool is_iface = (kls->type == EOLIAN_CLASS_INTERFACE);
database_class_file_set(class, filename);
if (kls->comment) database_class_description_set(class, kls->comment);
EINA_LIST_FOREACH(kls->inherits, l, s)
database_class_inherit_add(class, s);
if (kls->legacy_prefix)
{
database_class_legacy_prefix_set(class, kls->legacy_prefix);
}
if (kls->eo_prefix)
{
database_class_eo_prefix_set(class, kls->eo_prefix);
}
if (kls->data_type)
{
database_class_data_type_set(class, kls->data_type);
}
EINA_LIST_FOREACH(kls->constructors, l, meth)
{
Eolian_Function foo_id = database_function_new(meth->name, EOLIAN_CTOR);
database_class_function_add(class, foo_id);
if (meth->ret) database_function_return_comment_set(foo_id, EOLIAN_METHOD, meth->ret->comment);
database_function_data_set(foo_id, EOLIAN_LEGACY, meth->legacy);
EINA_LIST_FOREACH(meth->params, m, param)
{
database_method_parameter_add(foo_id, (Eolian_Parameter_Dir)param->way, param->type, param->name, param->comment);
param->type = NULL;
}
}
EINA_LIST_FOREACH(kls->properties, l, prop)
{
Eolian_Function foo_id = database_function_new(prop->name, EOLIAN_UNRESOLVED);
database_function_scope_set(foo_id, prop->scope);
EINA_LIST_FOREACH(prop->keys, m, param)
{
Eolian_Function_Parameter p = database_property_key_add(
foo_id, param->type, param->name, param->comment);
database_parameter_nonull_set(p, param->nonull);
param->type = NULL;
}
EINA_LIST_FOREACH(prop->values, m, param)
{
Eolian_Function_Parameter p = database_property_value_add(
foo_id, param->type, param->name, param->comment);
database_parameter_nonull_set(p, param->nonull);
param->type = NULL;
}
EINA_LIST_FOREACH(prop->accessors, m, accessor)
{
database_function_type_set(foo_id, (accessor->type == SETTER?EOLIAN_PROP_SET:EOLIAN_PROP_GET));
Eolian_Function_Type ftype =
accessor->type == SETTER?EOLIAN_PROP_SET:EOLIAN_PROP_GET;
if (accessor->ret && accessor->ret->type)
{
database_function_return_type_set(foo_id, ftype, accessor->ret->type);
database_function_return_comment_set(foo_id,
ftype, accessor->ret->comment);
database_function_return_flag_set_as_warn_unused(foo_id,
ftype, accessor->ret->warn_unused);
database_function_return_dflt_val_set(foo_id,
ftype, accessor->ret->dflt_ret_val);
accessor->ret->type = NULL;
}
if (accessor->legacy)
{
database_function_data_set(foo_id,
(accessor->type == SETTER?EOLIAN_LEGACY_SET:EOLIAN_LEGACY_GET),
accessor->legacy);
}
database_function_description_set(foo_id,
(accessor->type == SETTER?EOLIAN_COMMENT_SET:EOLIAN_COMMENT_GET),
accessor->comment);
Eo_Accessor_Param *acc_param;
Eina_List *m2;
EINA_LIST_FOREACH(accessor->params, m2, acc_param)
{
Eolian_Function_Parameter desc = eolian_function_parameter_get(foo_id, acc_param->name);
if (!desc)
{
printf("Error - %s not known as parameter of property %s\n", acc_param->name, prop->name);
}
else
if (strstr(acc_param->attrs, "const"))
{
database_parameter_const_attribute_set(desc, accessor->type == GETTER, EINA_TRUE);
}
}
if (is_iface)
database_function_set_as_virtual_pure(foo_id, ftype);
}
if (!prop->accessors)
{
database_function_type_set(foo_id, EOLIAN_PROPERTY);
if (is_iface)
database_function_set_as_virtual_pure(foo_id, EOLIAN_UNRESOLVED);
}
database_class_function_add(class, foo_id);
}
EINA_LIST_FOREACH(kls->methods, l, meth)
{
Eolian_Function foo_id = database_function_new(meth->name, EOLIAN_METHOD);
database_function_scope_set(foo_id, meth->scope);
database_class_function_add(class, foo_id);
if (meth->ret)
{
database_function_return_type_set(foo_id, EOLIAN_METHOD, meth->ret->type);
database_function_return_comment_set(foo_id, EOLIAN_METHOD, meth->ret->comment);
database_function_return_flag_set_as_warn_unused(foo_id,
EOLIAN_METHOD, meth->ret->warn_unused);
database_function_return_dflt_val_set(foo_id,
EOLIAN_METHOD, meth->ret->dflt_ret_val);
meth->ret->type = NULL;
}
database_function_description_set(foo_id, EOLIAN_COMMENT, meth->comment);
database_function_data_set(foo_id, EOLIAN_LEGACY, meth->legacy);
database_function_object_set_as_const(foo_id, meth->obj_const);
EINA_LIST_FOREACH(meth->params, m, param)
{
Eolian_Function_Parameter p = database_method_parameter_add(foo_id,
(Eolian_Parameter_Dir)param->way, param->type, param->name, param->comment);
database_parameter_nonull_set(p, param->nonull);
param->type = NULL;
}
if (is_iface)
database_function_set_as_virtual_pure(foo_id, EOLIAN_METHOD);
}
EINA_LIST_FOREACH(kls->implements, l, impl)
{
const char *impl_name = impl->meth_name;
if (!strcmp(impl_name, "class.constructor"))
{
database_class_ctor_enable_set(class, EINA_TRUE);
continue;
}
if (!strcmp(impl_name, "class.destructor"))
{
database_class_dtor_enable_set(class, EINA_TRUE);
continue;
}
if (!strncmp(impl_name, "virtual.", 8))
{
char *virtual_name = strdup(impl_name);
char *func = strchr(virtual_name, '.');
if (func) *func = '\0';
func += 1;
Eolian_Function_Type ftype = EOLIAN_UNRESOLVED;
char *type_as_str = strchr(func, '.');
if (type_as_str)
{
*type_as_str = '\0';
if (!strcmp(type_as_str+1, "set")) ftype = EOLIAN_PROP_SET;
else if (!strcmp(type_as_str+1, "get")) ftype = EOLIAN_PROP_GET;
}
/* Search the function into the existing functions of the current class */
Eolian_Function foo_id = eolian_class_function_find_by_name(
class, func, ftype);
free(virtual_name);
if (!foo_id)
{
ERR("Error - %s not known in class %s", impl_name + 8, eolian_class_name_get(class));
return EINA_FALSE;
}
database_function_set_as_virtual_pure(foo_id, ftype);
continue;
}
Eolian_Implement impl_desc = database_implement_new(impl_name);
database_class_implement_add(class, impl_desc);
}
EINA_LIST_FOREACH(kls->events, l, event)
{
Eolian_Event ev = database_event_new(event->name, event->type, event->comment);
database_class_event_add(class, ev);
}
return EINA_TRUE;
}
static Eina_Bool
_db_fill_type(Eo_Type_Def *type_def)
{
database_type_add(type_def->alias, type_def->type);
type_def->type = NULL;
return EINA_TRUE;
}
Eina_Bool
eo_parser_database_fill(const char *filename, Eina_Bool eot)
{
Eina_List *k;
Eo_Node *nd;
Eina_Bool has_class = EINA_FALSE;
Eo_Lexer *ls = eo_lexer_new(filename);
if (!ls)
{
@ -1046,212 +1277,49 @@ eo_parser_database_fill(const char *filename)
/* read first token */
eo_lexer_get(ls);
if (!eo_parser_walk(ls))
if (!eo_parser_walk(ls, eot))
{
eo_lexer_free(ls);
return EINA_FALSE;
}
if (!ls->classes)
if (eot) goto nodeloop;
EINA_LIST_FOREACH(ls->nodes, k, nd) if (nd->type == NODE_CLASS)
{
has_class = EINA_TRUE;
break;
}
if (!has_class)
{
ERR("No classes for file %s", filename);
eo_lexer_free(ls);
return EINA_FALSE;
}
EINA_LIST_FOREACH(ls->classes, k, kls)
nodeloop:
EINA_LIST_FOREACH(ls->nodes, k, nd)
{
Eolian_Class class = database_class_add(kls->name, kls->type);
Eina_Bool is_iface = (kls->type == EOLIAN_CLASS_INTERFACE);
database_class_file_set(class, filename);
if (kls->comment) database_class_description_set(class, kls->comment);
EINA_LIST_FOREACH(kls->inherits, l, s)
database_class_inherit_add(class, s);
if (kls->legacy_prefix)
switch (nd->type)
{
database_class_legacy_prefix_set(class, kls->legacy_prefix);
case NODE_CLASS:
if (!_db_fill_class(nd->def_class, filename))
goto error;
break;
case NODE_TYPEDEF:
if (!_db_fill_type(nd->def_type))
goto error;
break;
default:
break;
}
if (kls->eo_prefix)
{
database_class_eo_prefix_set(class, kls->eo_prefix);
}
if (kls->data_type)
{
database_class_data_type_set(class, kls->data_type);
}
EINA_LIST_FOREACH(kls->constructors, l, meth)
{
Eolian_Function foo_id = database_function_new(meth->name, EOLIAN_CTOR);
database_class_function_add(class, foo_id);
if (meth->ret) database_function_return_comment_set(foo_id, EOLIAN_METHOD, meth->ret->comment);
database_function_data_set(foo_id, EOLIAN_LEGACY, meth->legacy);
EINA_LIST_FOREACH(meth->params, m, param)
{
database_method_parameter_add(foo_id, (Eolian_Parameter_Dir)param->way, param->type, param->name, param->comment);
param->type = NULL;
}
}
EINA_LIST_FOREACH(kls->properties, l, prop)
{
Eolian_Function foo_id = database_function_new(prop->name, EOLIAN_UNRESOLVED);
database_function_scope_set(foo_id, prop->scope);
EINA_LIST_FOREACH(prop->keys, m, param)
{
Eolian_Function_Parameter p = database_property_key_add(
foo_id, param->type, param->name, param->comment);
database_parameter_nonull_set(p, param->nonull);
param->type = NULL;
}
EINA_LIST_FOREACH(prop->values, m, param)
{
Eolian_Function_Parameter p = database_property_value_add(
foo_id, param->type, param->name, param->comment);
database_parameter_nonull_set(p, param->nonull);
param->type = NULL;
}
EINA_LIST_FOREACH(prop->accessors, m, accessor)
{
database_function_type_set(foo_id, (accessor->type == SETTER?EOLIAN_PROP_SET:EOLIAN_PROP_GET));
Eolian_Function_Type ftype =
accessor->type == SETTER?EOLIAN_PROP_SET:EOLIAN_PROP_GET;
if (accessor->ret && accessor->ret->type)
{
database_function_return_type_set(foo_id, ftype, accessor->ret->type);
database_function_return_comment_set(foo_id,
ftype, accessor->ret->comment);
database_function_return_flag_set_as_warn_unused(foo_id,
ftype, accessor->ret->warn_unused);
database_function_return_dflt_val_set(foo_id,
ftype, accessor->ret->dflt_ret_val);
accessor->ret->type = NULL;
}
if (accessor->legacy)
{
database_function_data_set(foo_id,
(accessor->type == SETTER?EOLIAN_LEGACY_SET:EOLIAN_LEGACY_GET),
accessor->legacy);
}
database_function_description_set(foo_id,
(accessor->type == SETTER?EOLIAN_COMMENT_SET:EOLIAN_COMMENT_GET),
accessor->comment);
Eo_Accessor_Param *acc_param;
Eina_List *m2;
EINA_LIST_FOREACH(accessor->params, m2, acc_param)
{
Eolian_Function_Parameter desc = eolian_function_parameter_get(foo_id, acc_param->name);
if (!desc)
{
printf("Error - %s not known as parameter of property %s\n", acc_param->name, prop->name);
}
else
if (strstr(acc_param->attrs, "const"))
{
database_parameter_const_attribute_set(desc, accessor->type == GETTER, EINA_TRUE);
}
}
if (is_iface)
database_function_set_as_virtual_pure(foo_id, ftype);
}
if (!prop->accessors)
{
database_function_type_set(foo_id, EOLIAN_PROPERTY);
if (is_iface)
database_function_set_as_virtual_pure(foo_id, EOLIAN_UNRESOLVED);
}
database_class_function_add(class, foo_id);
}
EINA_LIST_FOREACH(kls->methods, l, meth)
{
Eolian_Function foo_id = database_function_new(meth->name, EOLIAN_METHOD);
database_function_scope_set(foo_id, meth->scope);
database_class_function_add(class, foo_id);
if (meth->ret)
{
database_function_return_type_set(foo_id, EOLIAN_METHOD, meth->ret->type);
database_function_return_comment_set(foo_id, EOLIAN_METHOD, meth->ret->comment);
database_function_return_flag_set_as_warn_unused(foo_id,
EOLIAN_METHOD, meth->ret->warn_unused);
database_function_return_dflt_val_set(foo_id,
EOLIAN_METHOD, meth->ret->dflt_ret_val);
meth->ret->type = NULL;
}
database_function_description_set(foo_id, EOLIAN_COMMENT, meth->comment);
database_function_data_set(foo_id, EOLIAN_LEGACY, meth->legacy);
database_function_object_set_as_const(foo_id, meth->obj_const);
EINA_LIST_FOREACH(meth->params, m, param)
{
Eolian_Function_Parameter p = database_method_parameter_add(foo_id,
(Eolian_Parameter_Dir)param->way, param->type, param->name, param->comment);
database_parameter_nonull_set(p, param->nonull);
param->type = NULL;
}
if (is_iface)
database_function_set_as_virtual_pure(foo_id, EOLIAN_METHOD);
}
EINA_LIST_FOREACH(kls->implements, l, impl)
{
const char *impl_name = impl->meth_name;
if (!strcmp(impl_name, "class.constructor"))
{
database_class_ctor_enable_set(class, EINA_TRUE);
continue;
}
if (!strcmp(impl_name, "class.destructor"))
{
database_class_dtor_enable_set(class, EINA_TRUE);
continue;
}
if (!strncmp(impl_name, "virtual.", 8))
{
char *virtual_name = strdup(impl_name);
char *func = strchr(virtual_name, '.');
if (func) *func = '\0';
func += 1;
Eolian_Function_Type ftype = EOLIAN_UNRESOLVED;
char *type_as_str = strchr(func, '.');
if (type_as_str)
{
*type_as_str = '\0';
if (!strcmp(type_as_str+1, "set")) ftype = EOLIAN_PROP_SET;
else if (!strcmp(type_as_str+1, "get")) ftype = EOLIAN_PROP_GET;
}
/* Search the function into the existing functions of the current class */
Eolian_Function foo_id = eolian_class_function_find_by_name(
class, func, ftype);
free(virtual_name);
if (!foo_id)
{
ERR("Error - %s not known in class %s", impl_name + 8, eolian_class_name_get(class));
eo_lexer_free(ls);
return EINA_FALSE;
}
database_function_set_as_virtual_pure(foo_id, ftype);
continue;
}
Eolian_Implement impl_desc = database_implement_new(impl_name);
database_class_implement_add(class, impl_desc);
}
EINA_LIST_FOREACH(kls->events, l, event)
{
Eolian_Event ev = database_event_new(event->name, event->type, event->comment);
database_class_event_add(class, ev);
}
}
EINA_LIST_FOREACH(ls->typedefs, k, type_def)
{
database_type_add(type_def->alias, type_def->type);
type_def->type = NULL;
}
eo_lexer_free(ls);
return EINA_TRUE;
error:
eo_lexer_free(ls);
return EINA_FALSE;
}

View File

@ -3,8 +3,8 @@
#include "eo_lexer.h"
Eina_Bool eo_parser_walk (Eo_Lexer *ls);
void eo_parser_dump (Eo_Lexer *ls);
Eina_Bool eo_parser_database_fill(const char *filename);
Eina_Bool eo_parser_walk (Eo_Lexer *ls, Eina_Bool eot);
Eina_Bool eo_parser_database_fill(const char *filename, Eina_Bool eot);
#endif /* __EO_PARSER_H__ */

View File

@ -17,6 +17,7 @@
static Eina_List *_classes = NULL;
static Eina_Hash *_types = NULL;
static Eina_Hash *_filenames = NULL; /* Hash: filename without extension -> full path */
static Eina_Hash *_tfilenames = NULL;
static int _database_init_count = 0;
typedef struct
@ -177,6 +178,7 @@ database_init()
eina_init();
_types = eina_hash_stringshared_new(_type_hash_free_cb);
_filenames = eina_hash_string_small_new(free);
_tfilenames = eina_hash_string_small_new(free);
return ++_database_init_count;
}
@ -197,6 +199,7 @@ database_shutdown()
_class_del((_Class_Desc *)class);
eina_hash_free(_types);
eina_hash_free(_filenames);
eina_hash_free(_tfilenames);
eina_shutdown();
}
return _database_init_count;
@ -674,6 +677,40 @@ eolian_function_name_get(Eolian_Function function_id)
return fid->name;
}
EAPI const char *
eolian_function_full_c_name_get(Eolian_Function foo_id, const char *prefix)
{
const char *funcn = eolian_function_name_get(foo_id);
const char *last_p = strrchr(prefix, '_');
const char *func_p = strchr(funcn, '_');
Eina_Strbuf *buf = eina_strbuf_new();
Eina_Stringshare *ret;
int len;
if (!last_p) last_p = prefix;
else last_p++;
if (!func_p) len = strlen(funcn);
else len = func_p - funcn;
if ((int)strlen(last_p) != len || strncmp(last_p, funcn, len))
{
eina_strbuf_append(buf, prefix);
eina_strbuf_append_char(buf, '_');
eina_strbuf_append(buf, funcn);
ret = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
return ret;
}
if (last_p != prefix)
eina_strbuf_append_n(buf, prefix, last_p - prefix); /* includes _ */
eina_strbuf_append(buf, funcn);
ret = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
return ret;
}
Eina_Bool
database_function_set_as_virtual_pure(Eolian_Function function_id, Eolian_Function_Type ftype)
{
@ -1368,6 +1405,16 @@ eolian_show(const Eolian_Class class)
}
#define EO_SUFFIX ".eo"
#define EOT_SUFFIX ".eot"
#define EO_SCAN_BODY(suffix, hash) \
if (eina_str_has_suffix(file, suffix)) \
{ \
int len = strlen(file); \
int idx = len - 1; \
while (idx >= 0 && file[idx] != '/' && file[idx] != '\\') idx--; \
eina_hash_add(hash, eina_stringshare_add_length(file+idx+1, len - idx - sizeof(suffix)), strdup(file)); \
}
EAPI Eina_Bool
eolian_directory_scan(const char *dir)
{
@ -1375,16 +1422,10 @@ eolian_directory_scan(const char *dir)
char *file;
/* Get all files from directory. Not recursively!!! */
Eina_Iterator *dir_files = eina_file_ls(dir);
EINA_ITERATOR_FOREACH(dir_files, file)
{
if (eina_str_has_suffix(file, EO_SUFFIX))
{
int len = strlen(file);
int idx = len - 1;
while (idx >= 0 && file[idx] != '/' && file[idx] != '\\') idx--;
eina_hash_add(_filenames, eina_stringshare_add_length(file+idx+1, len - idx - sizeof(EO_SUFFIX)), strdup(file));
}
}
EINA_ITERATOR_FOREACH(dir_files, file) EO_SCAN_BODY(EO_SUFFIX, _filenames);
eina_iterator_free(dir_files);
dir_files = eina_file_ls(dir);
EINA_ITERATOR_FOREACH(dir_files, file) EO_SCAN_BODY(EOT_SUFFIX, _tfilenames);
eina_iterator_free(dir_files);
return EINA_TRUE;
}
@ -1405,7 +1446,14 @@ _eolian_class_to_filename(const char *filename)
return ret;
}
EAPI Eina_Bool eolian_eo_file_parse(const char *filepath)
EAPI Eina_Bool
eolian_eot_file_parse(const char *filepath)
{
return eo_parser_database_fill(filepath, EINA_TRUE);
}
EAPI Eina_Bool
eolian_eo_file_parse(const char *filepath)
{
const Eina_List *itr;
Eolian_Class class = eolian_class_find_by_file(filepath);
@ -1413,7 +1461,7 @@ EAPI Eina_Bool eolian_eo_file_parse(const char *filepath)
Eolian_Implement impl;
if (!class)
{
if (!eo_parser_database_fill(filepath)) return EINA_FALSE;
if (!eo_parser_database_fill(filepath, EINA_FALSE)) return EINA_FALSE;
class = eolian_class_find_by_file(filepath);
if (!class)
{
@ -1456,6 +1504,21 @@ EAPI Eina_Bool eolian_eo_file_parse(const char *filepath)
return EINA_TRUE;
}
static Eina_Bool _tfile_parse(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
{
Eina_Bool *ret = fdata;
if (*ret) *ret = eolian_eot_file_parse(data);
return *ret;
}
EAPI Eina_Bool
eolian_all_eot_files_parse()
{
Eina_Bool ret = EINA_TRUE;
eina_hash_foreach(_tfilenames, _tfile_parse, &ret);
return ret;
}
static Eina_Bool _file_parse(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
{
Eina_Bool *ret = fdata;