2014-09-23 12:48:16 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2014-07-10 04:15:29 -07:00
|
|
|
#include <Eina.h>
|
2014-08-07 08:29:03 -07:00
|
|
|
#include "eo_lexer.h"
|
2014-07-10 04:15:29 -07:00
|
|
|
|
|
|
|
void
|
2014-07-10 06:44:17 -07:00
|
|
|
database_type_del(Eolian_Type *tp)
|
2014-07-10 04:15:29 -07:00
|
|
|
{
|
2018-02-21 07:36:08 -08:00
|
|
|
if (!tp || eolian_object_unref(&tp->base)) return;
|
2018-03-08 10:30:40 -08:00
|
|
|
eina_stringshare_del(tp->base.file);
|
|
|
|
eina_stringshare_del(tp->base.name);
|
2019-05-16 06:31:37 -07:00
|
|
|
eina_stringshare_del(tp->base.c_name);
|
2015-12-15 08:01:02 -08:00
|
|
|
database_type_del(tp->base_type);
|
2016-06-10 06:28:19 -07:00
|
|
|
database_type_del(tp->next_type);
|
2014-07-10 06:44:17 -07:00
|
|
|
free(tp);
|
2014-07-10 04:15:29 -07:00
|
|
|
}
|
|
|
|
|
2015-12-15 08:01:02 -08:00
|
|
|
void
|
|
|
|
database_typedecl_del(Eolian_Typedecl *tp)
|
|
|
|
{
|
2018-02-21 07:36:08 -08:00
|
|
|
if (!tp || eolian_object_unref(&tp->base)) return;
|
2018-03-08 10:30:40 -08:00
|
|
|
eina_stringshare_del(tp->base.file);
|
|
|
|
eina_stringshare_del(tp->base.name);
|
2019-05-16 06:31:37 -07:00
|
|
|
eina_stringshare_del(tp->base.c_name);
|
2016-03-01 07:37:57 -08:00
|
|
|
database_type_del(tp->base_type);
|
|
|
|
if (tp->fields) eina_hash_free(tp->fields);
|
|
|
|
if (tp->field_list) eina_list_free(tp->field_list);
|
2019-08-16 04:33:27 -07:00
|
|
|
database_function_del(tp->function_pointer);
|
|
|
|
eina_stringshare_del(tp->freefunc);
|
2016-03-01 07:37:57 -08:00
|
|
|
database_doc_del(tp->doc);
|
2015-12-15 08:01:02 -08:00
|
|
|
free(tp);
|
|
|
|
}
|
|
|
|
|
2014-07-22 02:39:34 -07:00
|
|
|
void
|
2018-02-21 08:59:39 -08:00
|
|
|
database_type_add(Eolian_Unit *unit, Eolian_Typedecl *tp)
|
2014-07-10 04:15:29 -07:00
|
|
|
{
|
2018-03-08 10:30:40 -08:00
|
|
|
EOLIAN_OBJECT_ADD(unit, tp->base.name, tp, aliases);
|
2018-03-22 10:01:31 -07:00
|
|
|
eina_hash_set(unit->state->staging.aliases_f, tp->base.file, eina_list_append
|
|
|
|
((Eina_List*)eina_hash_find(unit->state->staging.aliases_f, tp->base.file),
|
2018-02-21 08:59:39 -08:00
|
|
|
tp));
|
2018-03-08 14:59:40 -08:00
|
|
|
database_object_add(unit, &tp->base);
|
2014-07-10 04:15:29 -07:00
|
|
|
}
|
|
|
|
|
2014-09-12 06:20:52 -07:00
|
|
|
void
|
2019-02-28 11:25:51 -08:00
|
|
|
database_struct_add(Eolian_Unit *unit, Eolian_Typedecl *tp)
|
2014-07-10 04:15:29 -07:00
|
|
|
{
|
2019-02-28 11:25:51 -08:00
|
|
|
EOLIAN_OBJECT_ADD(unit, tp->base.name, tp, structs);
|
|
|
|
Eina_Hash *sh = unit->state->staging.structs_f;
|
eolian: add support for inlist structs
This adds support for inlist structs, a special type of struct
that can only be used with inlists. This differs from regular
structs in a couple ways:
1) They are stored separately. Just like structs, enums, aliases
have their own storage, so do inlist structs.
2) They can't be @extern, nor they can be opaque.
3) They are their own type of typedecl.
4) When they contain only one field, this field must be a value
type always, cannot be a pointer.
Like regular structs, they can have arbitrary fields, and they
can have a pre-set free function via @free().
In C, the inlist structs will be generated exactly like ordinary
ones, except they will have EINA_INLIST before the first field.
Other binding generators can deal with them as they wish, for
example to provide high level interfaces to them.
This does not yet do the plumbing necessary to hook these into
the type system, nor it adds generator support.
@feature
2019-01-29 06:46:05 -08:00
|
|
|
eina_hash_set(sh, tp->base.file, eina_list_append
|
|
|
|
((Eina_List*)eina_hash_find(sh, tp->base.file), tp));
|
2018-03-08 14:59:40 -08:00
|
|
|
database_object_add(unit, &tp->base);
|
2014-07-10 04:15:29 -07:00
|
|
|
}
|
|
|
|
|
2014-09-12 06:20:52 -07:00
|
|
|
void
|
2018-02-21 08:59:39 -08:00
|
|
|
database_enum_add(Eolian_Unit *unit, Eolian_Typedecl *tp)
|
2014-08-12 06:25:53 -07:00
|
|
|
{
|
2018-03-08 10:30:40 -08:00
|
|
|
EOLIAN_OBJECT_ADD(unit, tp->base.name, tp, enums);
|
2018-03-22 10:01:31 -07:00
|
|
|
eina_hash_set(unit->state->staging.enums_f, tp->base.file, eina_list_append
|
|
|
|
((Eina_List*)eina_hash_find(unit->state->staging.enums_f, tp->base.file), tp));
|
2018-03-08 14:59:40 -08:00
|
|
|
database_object_add(unit, &tp->base);
|
2014-08-12 06:25:53 -07:00
|
|
|
}
|
|
|
|
|
2017-08-10 03:41:03 -07:00
|
|
|
Eina_Bool
|
2019-09-26 06:58:17 -07:00
|
|
|
database_type_is_ownable(const Eolian_Unit *unit, const Eolian_Type *tp, Eina_Bool allow_void, const Eolian_Type **otp)
|
2017-08-10 03:41:03 -07:00
|
|
|
{
|
2019-09-26 06:58:17 -07:00
|
|
|
if (otp) *otp = tp;
|
2017-08-10 03:41:03 -07:00
|
|
|
if (tp->is_ptr)
|
|
|
|
return EINA_TRUE;
|
|
|
|
if (tp->type == EOLIAN_TYPE_REGULAR)
|
|
|
|
{
|
2018-03-11 07:55:10 -07:00
|
|
|
int kw = eo_lexer_keyword_str_to_id(tp->base.name);
|
2017-09-22 09:08:36 -07:00
|
|
|
const char *ct = eo_lexer_get_c_type(kw);
|
2017-08-10 03:41:03 -07:00
|
|
|
if (!ct)
|
2017-09-13 15:34:06 -07:00
|
|
|
{
|
2018-01-12 08:52:44 -08:00
|
|
|
const Eolian_Typedecl *tpp = database_type_decl_find(unit, tp);
|
2017-09-13 15:34:06 -07:00
|
|
|
if (!tpp)
|
|
|
|
return EINA_FALSE;
|
|
|
|
if (tpp->type == EOLIAN_TYPEDECL_FUNCTION_POINTER)
|
|
|
|
return EINA_TRUE;
|
|
|
|
if (tpp->type == EOLIAN_TYPEDECL_ALIAS)
|
2019-09-26 06:58:17 -07:00
|
|
|
return database_type_is_ownable(unit, tpp->base_type, allow_void, otp);
|
2017-09-13 15:34:06 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2017-08-10 03:41:03 -07:00
|
|
|
return (ct[strlen(ct) - 1] == '*');
|
|
|
|
}
|
2018-05-03 08:10:31 -07:00
|
|
|
if (allow_void && (tp->type == EOLIAN_TYPE_VOID))
|
|
|
|
return EINA_TRUE;
|
2017-11-03 07:30:10 -07:00
|
|
|
return (tp->type == EOLIAN_TYPE_CLASS);
|
2017-08-10 03:41:03 -07:00
|
|
|
}
|
|
|
|
|
2016-07-01 06:34:24 -07:00
|
|
|
static void
|
|
|
|
_buf_add_suffix(Eina_Strbuf *buf, const char *suffix)
|
|
|
|
{
|
|
|
|
if (!suffix) return;
|
|
|
|
if (eina_strbuf_string_get(buf)[eina_strbuf_length_get(buf) - 1] != '*')
|
|
|
|
eina_strbuf_append_char(buf, ' ');
|
|
|
|
eina_strbuf_append(buf, suffix);
|
|
|
|
}
|
|
|
|
|
2016-03-01 06:55:10 -08:00
|
|
|
void
|
2018-01-16 07:36:45 -08:00
|
|
|
database_type_to_str(const Eolian_Type *tp,
|
2017-12-15 08:00:36 -08:00
|
|
|
Eina_Strbuf *buf, const char *name,
|
2019-09-04 06:56:32 -07:00
|
|
|
Eolian_C_Type_Type ctype, Eina_Bool by_ref)
|
2016-03-01 06:55:10 -08:00
|
|
|
{
|
2017-08-10 03:41:03 -07:00
|
|
|
if ((tp->type == EOLIAN_TYPE_REGULAR
|
2017-09-22 08:46:02 -07:00
|
|
|
|| tp->type == EOLIAN_TYPE_CLASS
|
2017-08-10 03:41:03 -07:00
|
|
|
|| tp->type == EOLIAN_TYPE_VOID)
|
|
|
|
&& tp->is_const
|
2019-09-26 06:58:17 -07:00
|
|
|
&& ((ctype != EOLIAN_C_TYPE_RETURN) || by_ref || database_type_is_ownable(NULL, tp, EINA_FALSE, NULL)))
|
2017-08-10 03:41:03 -07:00
|
|
|
{
|
|
|
|
eina_strbuf_append(buf, "const ");
|
|
|
|
}
|
2016-03-01 06:55:10 -08:00
|
|
|
if (tp->type == EOLIAN_TYPE_REGULAR
|
|
|
|
|| tp->type == EOLIAN_TYPE_CLASS)
|
|
|
|
{
|
2018-03-11 07:55:10 -07:00
|
|
|
int kw = eo_lexer_keyword_str_to_id(tp->base.name);
|
2016-03-01 06:55:10 -08:00
|
|
|
if (kw && eo_lexer_is_type_keyword(kw))
|
2017-09-22 08:10:42 -07:00
|
|
|
eina_strbuf_append(buf, eo_lexer_get_c_type(kw));
|
2016-03-01 06:55:10 -08:00
|
|
|
else
|
2019-05-30 07:20:09 -07:00
|
|
|
eina_strbuf_append(buf, tp->base.c_name);
|
2016-03-01 06:55:10 -08:00
|
|
|
}
|
2020-04-20 05:36:14 -07:00
|
|
|
else if (tp->type == EOLIAN_TYPE_ERROR)
|
|
|
|
eina_strbuf_append(buf, "Eina_Error");
|
2016-03-01 06:55:10 -08:00
|
|
|
else if (tp->type == EOLIAN_TYPE_VOID)
|
|
|
|
eina_strbuf_append(buf, "void");
|
2016-05-10 10:06:56 -07:00
|
|
|
else if (tp->type == EOLIAN_TYPE_UNDEFINED)
|
|
|
|
eina_strbuf_append(buf, "__undefined_type");
|
2016-03-01 06:55:10 -08:00
|
|
|
else
|
|
|
|
{
|
2016-06-30 06:04:03 -07:00
|
|
|
/* handles arrays and pointers as they all serialize to pointers */
|
2018-01-16 07:36:45 -08:00
|
|
|
database_type_to_str(tp->base_type, buf, NULL,
|
2019-09-04 06:56:32 -07:00
|
|
|
EOLIAN_C_TYPE_DEFAULT, EINA_FALSE);
|
2016-07-01 06:34:24 -07:00
|
|
|
_buf_add_suffix(buf, "*");
|
2017-08-10 03:41:03 -07:00
|
|
|
if (tp->is_const && (ctype != EOLIAN_C_TYPE_RETURN))
|
|
|
|
eina_strbuf_append(buf, " const");
|
2016-03-01 06:55:10 -08:00
|
|
|
}
|
2017-09-22 08:46:02 -07:00
|
|
|
if (tp->type == EOLIAN_TYPE_CLASS)
|
2016-07-01 06:34:24 -07:00
|
|
|
_buf_add_suffix(buf, "*");
|
2016-11-03 06:21:57 -07:00
|
|
|
if (tp->is_ptr)
|
2016-07-01 06:34:24 -07:00
|
|
|
_buf_add_suffix(buf, "*");
|
2019-09-04 06:56:32 -07:00
|
|
|
if (by_ref)
|
|
|
|
_buf_add_suffix(buf, "*");
|
2016-07-01 06:34:24 -07:00
|
|
|
_buf_add_suffix(buf, name);
|
2016-03-01 06:55:10 -08:00
|
|
|
}
|
|
|
|
|
2014-07-10 04:15:29 -07:00
|
|
|
static void
|
2018-01-16 07:36:45 -08:00
|
|
|
_stype_to_str(const Eolian_Typedecl *tp, Eina_Strbuf *buf)
|
2014-07-10 04:15:29 -07:00
|
|
|
{
|
|
|
|
eina_strbuf_append(buf, "struct ");
|
2019-05-30 07:20:09 -07:00
|
|
|
eina_strbuf_append(buf, tp->base.c_name);
|
2016-03-01 06:55:10 -08:00
|
|
|
if (tp->type == EOLIAN_TYPEDECL_STRUCT_OPAQUE)
|
2016-06-06 07:50:15 -07:00
|
|
|
return;
|
2016-06-06 08:15:14 -07:00
|
|
|
eina_strbuf_append(buf, " { ");
|
2018-03-11 07:55:10 -07:00
|
|
|
Eina_List *l;
|
|
|
|
Eolian_Struct_Type_Field *sf;
|
2014-10-01 06:34:33 -07:00
|
|
|
EINA_LIST_FOREACH(tp->field_list, l, sf)
|
2014-08-12 07:07:46 -07:00
|
|
|
{
|
2018-03-08 10:30:40 -08:00
|
|
|
database_type_to_str(sf->type, buf, sf->base.name,
|
2019-09-04 06:56:32 -07:00
|
|
|
EOLIAN_C_TYPE_DEFAULT, sf->by_ref);
|
2014-08-12 07:07:46 -07:00
|
|
|
eina_strbuf_append(buf, "; ");
|
|
|
|
}
|
2014-07-10 04:15:29 -07:00
|
|
|
eina_strbuf_append(buf, "}");
|
|
|
|
}
|
|
|
|
|
2014-08-12 06:48:31 -07:00
|
|
|
static void
|
2018-01-16 07:36:45 -08:00
|
|
|
_etype_to_str(const Eolian_Typedecl *tp, Eina_Strbuf *buf)
|
2014-08-12 06:48:31 -07:00
|
|
|
{
|
|
|
|
eina_strbuf_append(buf, "enum ");
|
2019-05-30 07:20:09 -07:00
|
|
|
eina_strbuf_append(buf, tp->base.c_name);
|
2016-06-06 08:15:14 -07:00
|
|
|
eina_strbuf_append(buf, " { ");
|
2018-03-11 07:55:10 -07:00
|
|
|
Eina_List *l;
|
|
|
|
Eolian_Enum_Type_Field *ef;
|
2014-10-01 06:34:33 -07:00
|
|
|
EINA_LIST_FOREACH(tp->field_list, l, ef)
|
2014-08-12 07:07:46 -07:00
|
|
|
{
|
2018-03-08 10:30:40 -08:00
|
|
|
eina_strbuf_append(buf, ef->base.name);
|
2014-08-12 07:07:46 -07:00
|
|
|
if (ef->value)
|
|
|
|
{
|
2018-01-16 07:10:43 -08:00
|
|
|
Eolian_Value val = eolian_expression_eval(ef->value,
|
|
|
|
EOLIAN_MASK_INT);
|
2014-08-12 07:07:46 -07:00
|
|
|
const char *ret;
|
|
|
|
eina_strbuf_append(buf, " = ");
|
2014-08-18 05:12:08 -07:00
|
|
|
ret = eolian_expression_value_to_literal(&val);
|
2014-08-12 07:07:46 -07:00
|
|
|
eina_strbuf_append(buf, ret);
|
|
|
|
eina_stringshare_del(ret);
|
|
|
|
}
|
2014-08-22 08:17:33 -07:00
|
|
|
if (l != eina_list_last(tp->field_list))
|
2014-08-12 07:07:46 -07:00
|
|
|
eina_strbuf_append(buf, ", ");
|
|
|
|
}
|
2014-08-12 08:29:02 -07:00
|
|
|
eina_strbuf_append(buf, " }");
|
2014-08-12 06:48:31 -07:00
|
|
|
}
|
|
|
|
|
2016-03-14 10:16:41 -07:00
|
|
|
static void
|
2018-01-16 07:36:45 -08:00
|
|
|
_atype_to_str(const Eolian_Typedecl *tp, Eina_Strbuf *buf)
|
2016-03-14 10:16:41 -07:00
|
|
|
{
|
2014-07-22 04:11:06 -07:00
|
|
|
eina_strbuf_append(buf, "typedef ");
|
2019-05-30 07:20:09 -07:00
|
|
|
database_type_to_str(tp->base_type, buf, tp->base.c_name,
|
2019-09-04 06:56:32 -07:00
|
|
|
EOLIAN_C_TYPE_DEFAULT, EINA_FALSE);
|
2014-07-22 04:11:06 -07:00
|
|
|
}
|
|
|
|
|
2014-07-10 05:13:46 -07:00
|
|
|
void
|
2018-01-16 07:36:45 -08:00
|
|
|
database_typedecl_to_str(const Eolian_Typedecl *tp, Eina_Strbuf *buf)
|
2014-07-10 04:15:29 -07:00
|
|
|
{
|
2016-03-11 05:04:33 -08:00
|
|
|
switch (tp->type)
|
2014-07-22 04:11:06 -07:00
|
|
|
{
|
2016-03-11 05:04:33 -08:00
|
|
|
case EOLIAN_TYPEDECL_ALIAS:
|
2018-01-16 07:36:45 -08:00
|
|
|
_atype_to_str(tp, buf);
|
2016-03-11 05:04:33 -08:00
|
|
|
break;
|
|
|
|
case EOLIAN_TYPEDECL_ENUM:
|
2018-01-16 07:36:45 -08:00
|
|
|
_etype_to_str(tp, buf);
|
2016-03-11 05:04:33 -08:00
|
|
|
break;
|
|
|
|
case EOLIAN_TYPEDECL_STRUCT:
|
|
|
|
case EOLIAN_TYPEDECL_STRUCT_OPAQUE:
|
2018-01-16 07:36:45 -08:00
|
|
|
_stype_to_str(tp, buf);
|
2016-03-11 05:04:33 -08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2014-07-10 04:15:29 -07:00
|
|
|
}
|
|
|
|
}
|
2018-01-12 08:52:44 -08:00
|
|
|
|
|
|
|
Eolian_Typedecl *database_type_decl_find(const Eolian_Unit *unit, const Eolian_Type *tp)
|
|
|
|
{
|
|
|
|
if (tp->type != EOLIAN_TYPE_REGULAR)
|
|
|
|
return NULL;
|
|
|
|
if (tp->tdecl)
|
|
|
|
return tp->tdecl;
|
|
|
|
/* try looking up if it belongs to a struct, enum or an alias... otherwise
|
|
|
|
* return NULL, but first check for builtins
|
|
|
|
*/
|
2018-03-08 10:30:40 -08:00
|
|
|
int kw = eo_lexer_keyword_str_to_id(tp->base.name);
|
2018-01-12 08:52:44 -08:00
|
|
|
if (!kw || kw < KW_byte || kw >= KW_true)
|
|
|
|
{
|
2018-03-08 14:59:40 -08:00
|
|
|
Eolian_Object *decl = eina_hash_find(unit->objects, tp->base.name);
|
|
|
|
if (decl && decl->type == EOLIAN_OBJECT_TYPEDECL)
|
|
|
|
return (Eolian_Typedecl *)decl;
|
2018-01-12 08:52:44 -08:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|