summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2014-08-12 14:25:53 +0100
committerDaniel Kolesa <d.kolesa@samsung.com>2014-08-21 09:26:04 +0100
commite2fb43b7b5afeada56273d41e672b27991676062 (patch)
tree0da3f669e3fbf890504426036666b4dfe06b11f0
parent75ee3b031d6b1e3ec784cc9d3a63937f0c1a56fb (diff)
downloadefl-e2fb43b7b5afeada56273d41e672b27991676062.tar.gz
eolian: enum API implementation
This implements the previously declared APIs to manipulate enum types. Also, it implements the appropriate lookups in expression evaluation so that you can refer to constants and enums inside constant expressions.
-rw-r--r--src/lib/eolian/Eolian.h1
-rw-r--r--src/lib/eolian/database_expr.c108
-rw-r--r--src/lib/eolian/database_type.c20
-rw-r--r--src/lib/eolian/database_type_api.c65
-rw-r--r--src/lib/eolian/eo_parser.c11
5 files changed, 200 insertions, 5 deletions
diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h
index e79eaa66a7..080ca45c3a 100644
--- a/src/lib/eolian/Eolian.h
+++ b/src/lib/eolian/Eolian.h
@@ -157,6 +157,7 @@ typedef enum
EOLIAN_EXPR_NULL,
EOLIAN_EXPR_BOOL,
EOLIAN_EXPR_NAME,
+ EOLIAN_EXPR_ENUM,
EOLIAN_EXPR_UNARY,
EOLIAN_EXPR_BINARY
} Eolian_Expression_Type;
diff --git a/src/lib/eolian/database_expr.c b/src/lib/eolian/database_expr.c
index 48889a6823..f2b202c209 100644
--- a/src/lib/eolian/database_expr.c
+++ b/src/lib/eolian/database_expr.c
@@ -59,6 +59,14 @@ expr_type_error(const Eolian_Expression *expr, int type, int mask)
return node_error((const Eolian_Object*)expr, buf);
}
+static Eina_Bool
+expr_error(const Eolian_Expression *expr, const char *msg)
+{
+ char buf[512];
+ snprintf(buf, sizeof(buf), "%s '%s'", msg, expr->value.s);
+ return node_error((const Eolian_Object*)expr, buf);
+}
+
static int
expr_type_to_mask(const Eolian_Expression *expr)
{
@@ -407,6 +415,22 @@ eval_binary(const Eolian_Expression *expr, Eolian_Expression_Mask mask,
}
static Eina_Bool
+split_enum_name(const char *str, char **ename, char **memb)
+{
+ char *fulln = strdup(str);
+ char *memb_s = strrchr(fulln, '.');
+ if (!memb_s)
+ {
+ free(fulln);
+ return EINA_FALSE;
+ }
+ *(memb_s++) = '\0';
+ *ename = fulln;
+ *memb = memb_s;
+ return EINA_TRUE;
+}
+
+static Eina_Bool
eval_exp(const Eolian_Expression *expr, Eolian_Expression_Mask mask,
Eolian_Expression *out)
{
@@ -467,6 +491,90 @@ eval_exp(const Eolian_Expression *expr, Eolian_Expression_Mask mask,
*out = *expr;
return EINA_TRUE;
}
+ case EOLIAN_EXPR_NAME:
+ {
+ const Eolian_Variable *var = eolian_variable_constant_get_by_name
+ (expr->value.s);
+ const Eolian_Expression *exp = NULL;
+
+ if (!var)
+ {
+ const Eolian_Type *etp;
+
+ /* try aliases, hoping it'll be enum */
+ char *fulln = NULL, *memb = NULL;
+
+ if (!split_enum_name(expr->value.s, &fulln, &memb))
+ return expr_error(expr, "undefined variable");
+
+ etp = eolian_type_alias_get_by_name(fulln);
+ while (etp && etp->type == EOLIAN_TYPE_ALIAS)
+ {
+ etp = eolian_type_base_type_get(etp);
+ if (etp->type == EOLIAN_TYPE_ENUM)
+ break;
+ if (etp->type == EOLIAN_TYPE_REGULAR_ENUM)
+ break;
+ if (etp->type != EOLIAN_TYPE_REGULAR)
+ {
+ etp = NULL;
+ break;
+ }
+ etp = eolian_type_alias_get_by_name(etp->full_name);
+ }
+
+ if (etp && etp->type == EOLIAN_TYPE_REGULAR_ENUM)
+ etp = eolian_type_enum_get_by_name(etp->full_name);
+
+ if (!etp || etp->type != EOLIAN_TYPE_ENUM)
+ {
+ free(fulln);
+ return expr_error(expr, "undefined variable");
+ }
+
+ exp = eolian_type_enum_field_get(etp, memb);
+ free(fulln);
+
+ if (!exp)
+ return expr_error(expr, "invalid enum field");
+ }
+ else
+ exp = var->value;
+
+ if (!exp)
+ return expr_error(expr, "undefined variable");
+
+ return eval_exp(exp, mask, out);
+ }
+ case EOLIAN_EXPR_ENUM:
+ {
+ const Eolian_Type *etp;
+ const Eolian_Expression *exp;
+
+ char *fulln = NULL, *memb = NULL;
+ if (!split_enum_name(expr->value.s, &fulln, &memb))
+ {
+ return expr_error(expr, "invalid enum");
+ }
+
+ etp = eolian_type_enum_get_by_name(fulln);
+ if (etp && etp->type == EOLIAN_TYPE_REGULAR_ENUM)
+ etp = eolian_type_enum_get_by_name(etp->full_name);
+
+ if (!etp)
+ {
+ free(fulln);
+ return expr_error(expr, "invalid enum");
+ }
+
+ exp = eolian_type_enum_field_get(etp, memb);
+ free(fulln);
+
+ if (!exp)
+ return expr_error(expr, "invalid enum field");
+
+ return eval_exp(exp, mask, out);
+ }
case EOLIAN_EXPR_UNARY:
return eval_unary(expr, mask, out);
case EOLIAN_EXPR_BINARY:
diff --git a/src/lib/eolian/database_type.c b/src/lib/eolian/database_type.c
index 0df7f59c7f..abf252b752 100644
--- a/src/lib/eolian/database_type.c
+++ b/src/lib/eolian/database_type.c
@@ -27,9 +27,14 @@ database_typedef_del(Eolian_Type *tp)
{
if (!tp) return;
Eolian_Type *btp = tp->base_type;
- /* prevent deletion of named structs as they're deleted later on */
- if (btp && btp->type == EOLIAN_TYPE_STRUCT && btp->name)
- tp->base_type = NULL;
+ /* prevent deletion of named structs/enums as they're deleted later on */
+ if (btp)
+ {
+ if (btp->type == EOLIAN_TYPE_ENUM)
+ tp->base_type = NULL;
+ else if (btp->type == EOLIAN_TYPE_STRUCT && btp->name)
+ tp->base_type = NULL;
+ }
database_type_del(tp);
}
@@ -52,6 +57,15 @@ Eina_Bool database_struct_add(Eolian_Type *tp)
return EINA_TRUE;
}
+Eina_Bool database_enum_add(Eolian_Type *tp)
+{
+ if (!_enums) return EINA_FALSE;
+ eina_hash_set(_enums, tp->full_name, tp);
+ eina_hash_set(_enumsf, tp->base.file, eina_list_append
+ ((Eina_List*)eina_hash_find(_enumsf, tp->base.file), tp));
+ return EINA_TRUE;
+}
+
static void
_ftype_to_str(const Eolian_Type *tp, Eina_Strbuf *buf, const char *name)
{
diff --git a/src/lib/eolian/database_type_api.c b/src/lib/eolian/database_type_api.c
index 2fa6404ebb..ab0ea75c7d 100644
--- a/src/lib/eolian/database_type_api.c
+++ b/src/lib/eolian/database_type_api.c
@@ -22,6 +22,16 @@ eolian_type_struct_get_by_name(const char *name)
return tp;
}
+EAPI const Eolian_Type *
+eolian_type_enum_get_by_name(const char *name)
+{
+ if (!_enums) return NULL;
+ Eina_Stringshare *shr = eina_stringshare_add(name);
+ Eolian_Type *tp = eina_hash_find(_enums, shr);
+ eina_stringshare_del(shr);
+ return tp;
+}
+
EAPI Eina_Iterator *
eolian_type_aliases_get_by_file(const char *fname)
{
@@ -44,6 +54,17 @@ eolian_type_structs_get_by_file(const char *fname)
return eina_list_iterator_new(l);
}
+EAPI Eina_Iterator *
+eolian_type_enums_get_by_file(const char *fname)
+{
+ if (!_structsf) return NULL;
+ Eina_Stringshare *shr = eina_stringshare_add(fname);
+ Eina_List *l = eina_hash_find(_enumsf, shr);
+ eina_stringshare_del(shr);
+ if (!l) return NULL;
+ return eina_list_iterator_new(l);
+}
+
EAPI Eolian_Type_Type
eolian_type_type_get(const Eolian_Type *tp)
{
@@ -106,6 +127,50 @@ eolian_type_struct_field_description_get(const Eolian_Type *tp, const char *fiel
return sf->comment;
}
+EAPI Eina_Iterator *
+eolian_type_enum_field_names_get(const Eolian_Type *tp)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(tp->type == EOLIAN_TYPE_ENUM, NULL);
+ return eina_hash_iterator_key_new(tp->fields);
+}
+
+EAPI Eina_Bool
+eolian_type_enum_field_exists(const Eolian_Type *tp, const char *field)
+{
+ Eolian_Enum_Field *ef = NULL;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tp, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(tp->type == EOLIAN_TYPE_ENUM, EINA_FALSE);
+ ef = eina_hash_find(tp->fields, field);
+ if (!ef)
+ return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+EAPI const Eolian_Expression *
+eolian_type_enum_field_get(const Eolian_Type *tp, const char *field)
+{
+ Eolian_Enum_Field *ef = NULL;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(field, NULL);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(tp->type == EOLIAN_TYPE_ENUM, NULL);
+ ef = eina_hash_find(tp->fields, field);
+ if (!ef) return NULL;
+ return ef->value;
+}
+
+EAPI Eina_Stringshare *
+eolian_type_enum_field_description_get(const Eolian_Type *tp, const char *field)
+{
+ Eolian_Enum_Field *ef = NULL;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(field, NULL);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(tp->type == EOLIAN_TYPE_ENUM, NULL);
+ ef = eina_hash_find(tp->fields, field);
+ if (!ef) return NULL;
+ return ef->comment;
+}
+
EAPI Eina_Stringshare *
eolian_type_description_get(const Eolian_Type *tp)
{
diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c
index ceb82c03d3..133ada50ab 100644
--- a/src/lib/eolian/eo_parser.c
+++ b/src/lib/eolian/eo_parser.c
@@ -411,11 +411,18 @@ parse_expr_simple(Eo_Lexer *ls)
eo_lexer_get(ls);
break;
}
+ case KW_enum:
default:
{
Eina_Strbuf *buf = push_strbuf(ls);
+ Eolian_Expression_Type tp = EOLIAN_EXPR_NAME;
+ if (ls->t.kw == KW_enum)
+ {
+ eo_lexer_get(ls);
+ tp = EOLIAN_EXPR_ENUM;
+ }
expr = push_expr(ls);
- expr->type = EOLIAN_EXPR_NAME;
+ expr->type = tp;
parse_name(ls, buf);
expr->value.s = eina_stringshare_add(eina_strbuf_string_get
(buf));
@@ -701,7 +708,7 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool is_extern,
def->base.file = eina_stringshare_ref(ls->filename);
def->base.line = line;
def->base.column = column;
- if (name) database_struct_add(def);
+ if (name) database_enum_add(def);
return def;
}