aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/edje
diff options
context:
space:
mode:
authorJeeyong Um <conr2d@gmail.com>2017-10-27 11:49:02 -0700
committerCedric Bail <cedric@osg.samsung.com>2017-10-27 13:34:01 -0700
commit64fb807b63362fb922caf4a0a917b8f34c3eec10 (patch)
treeb59d2eec35da0b44defbf7d383be3b0dcf73e0c6 /src/bin/edje
parentevas: add a missing description for a newly added parameter (diff)
downloadefl-64fb807b63362fb922caf4a0a917b8f34c3eec10.tar.gz
edje_cc: support script inheritance
Summary: When inherit_script is set to 1, script of current group contains variables and funtions from script of parent groups. If there is same name variable or function, newly defined one will replace that of parents. Reviewers: cedric, jpeg Subscribers: taxi2se Differential Revision: https://phab.enlightenment.org/D5062 Signed-off-by: Cedric Bail <cedric@osg.samsung.com>
Diffstat (limited to 'src/bin/edje')
-rw-r--r--src/bin/edje/edje_cc.h9
-rw-r--r--src/bin/edje/edje_cc_handlers.c102
-rw-r--r--src/bin/edje/edje_cc_script.c465
3 files changed, 564 insertions, 12 deletions
diff --git a/src/bin/edje/edje_cc.h b/src/bin/edje/edje_cc.h
index 9e3c9a88d3..55c151b02a 100644
--- a/src/bin/edje/edje_cc.h
+++ b/src/bin/edje/edje_cc.h
@@ -91,7 +91,10 @@ struct _Code
char *shared;
char *original;
Eina_List *programs;
- int is_lua;
+ Eina_List *vars;
+ Eina_List *func;
+ Eina_Bool parsed : 1;
+ Eina_Bool is_lua : 1;
};
struct _Code_Program
@@ -160,8 +163,10 @@ struct _Edje_Part_Collection_Parser
Eina_List *target_groups;
Eina_List *links;
Eina_Hash *link_hash;
+ Eina_List *base_codes;
Eina_Bool default_mouse_events;
Eina_Bool inherit_only;
+ Eina_Bool inherit_script : 1;
};
typedef enum
@@ -297,6 +302,8 @@ int get_param_index(char *str);
void color_tree_root_free(void);
void convert_color_code(char *str, int *r, int *g, int *b, int *a);
+void script_rewrite(Code *code);
+
/* global vars */
extern Eina_List *ext_dirs;
extern Eina_List *img_dirs;
diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c
index 909b0e153b..3f83283c75 100644
--- a/src/bin/edje/edje_cc_handlers.c
+++ b/src/bin/edje/edje_cc_handlers.c
@@ -163,7 +163,7 @@ static Edje_Part_Description_Common *parent_desc = NULL;
static Edje_Program *current_program = NULL;
static Eina_List *current_program_lookups = NULL;
Eina_Bool current_group_inherit = EINA_FALSE;
-Eina_Bool script_override = EINA_FALSE;
+Eina_Bool script_is_replaceable = EINA_FALSE;
static Edje_Program *sequencing = NULL;
static Eina_List *sequencing_lookups = NULL;
static int *anonymous_delete = NULL;
@@ -268,6 +268,7 @@ static void st_collections_group_data_item(void);
static void st_collections_group_orientation(void);
static void st_collections_group_mouse_events(void);
static void st_collections_group_use_custom_seat_names(void);
+static void st_collections_group_inherit_script(void);
static void st_collections_group_limits_vertical(void);
static void st_collections_group_limits_horizontal(void);
@@ -550,6 +551,7 @@ static void st_collections_group_mouse(void);
static void st_collections_group_nomouse(void);
static void st_collections_group_broadcast(void);
static void st_collections_group_nobroadcast(void);
+static void st_collections_group_noinherit_script(void);
static void st_images_vector(void);
static void _handle_vector_image(void);
@@ -746,6 +748,7 @@ New_Statement_Handler statement_handlers[] =
{"collections.group.broadcast_signal", st_collections_group_broadcast_signal},
{"collections.group.orientation", st_collections_group_orientation},
{"collections.group.mouse_events", st_collections_group_mouse_events},
+ {"collections.group.inherit_script", st_collections_group_inherit_script},
{"collections.group.data.item", st_collections_group_data_item},
{"collections.group.limits.horizontal", st_collections_group_limits_horizontal},
{"collections.group.limits.vertical", st_collections_group_limits_vertical},
@@ -1143,6 +1146,8 @@ New_Statement_Handler statement_handlers_short[] =
nobroadcast; -> broadcast_signal: 0;
mouse; -> mouse_events: 1;
nomouse; -> mouse_events: 0;
+ inherit_script; -> inherit_script: 1;
+ noinherit_script; -> inherit_script: 0;
parts {
part {
mouse; -> mouse_events: 1;
@@ -1191,6 +1196,8 @@ New_Statement_Handler statement_handlers_short_single[] =
{"collections.group.nomouse", st_collections_group_nomouse},
{"collections.group.broadcast", st_collections_group_broadcast},
{"collections.group.nobroadcast", st_collections_group_nobroadcast},
+ {"collections.group.inherit_script", st_collections_group_inherit_script},
+ {"collections.group.noinherit_script", st_collections_group_noinherit_script},
{"collections.group.parts.part.description.inherit", st_collections_group_parts_part_description_inherit},
};
@@ -4238,7 +4245,7 @@ ob_collections_group(void)
current_desc = NULL;
current_group_inherit = EINA_FALSE;
- script_override = EINA_FALSE;
+ script_is_replaceable = EINA_FALSE;
current_de = mem_alloc(SZ(Edje_Part_Collection_Directory_Entry));
current_de->id = eina_list_count(edje_collections);
@@ -4257,6 +4264,7 @@ ob_collections_group(void)
pcp = (Edje_Part_Collection_Parser *)pc;
pcp->default_mouse_events = 1;
+ pcp->inherit_script = EINA_FALSE;
pc->scene_size.width = 0;
pc->scene_size.height = 0;
@@ -4835,6 +4843,7 @@ st_collections_group_inherit(void)
pcp = (Edje_Part_Collection_Parser *)pc;
pcp2 = (Edje_Part_Collection_Parser *)pc2;
pcp->default_mouse_events = pcp2->default_mouse_events;
+ pcp->inherit_script = pcp2->inherit_script;
/* as of 7 April 2014, target groups cannot be modified and are not freed.
* this code will break if that ever changes.
@@ -4961,6 +4970,9 @@ st_collections_group_inherit(void)
cd = eina_list_data_get(eina_list_last(codes));
cd->is_lua = cd2->is_lua;
+ if (!cd2->is_lua)
+ pcp->base_codes = eina_list_append(pcp->base_codes, cd2);
+
if (cd2->shared)
{
if (cd->shared)
@@ -4975,7 +4987,7 @@ st_collections_group_inherit(void)
cd->shared = STRDUP(cd2->shared);
cd->original = STRDUP(cd2->original);
- script_override = EINA_TRUE;
+ script_is_replaceable = EINA_TRUE;
}
EINA_LIST_FOREACH(cd2->programs, l, cp2)
@@ -5271,6 +5283,76 @@ st_collections_group_nomouse(void)
/**
@page edcref
@property
+ inherit_script
+ @parameters
+ [1 or 0]
+ @effect
+ Determine whether to inherit script block from parent group.
+ If it is set to 0, script from parent group will be replaced with
+ new script block.
+ Defaults to 0 if not set, to maintain compatibility.
+ @endproperty
+ */
+static void
+st_collections_group_inherit_script(void)
+{
+ Edje_Part_Collection_Parser *pcp;
+
+ pcp = eina_list_last_data_get(edje_collections);
+
+ if (get_arg_count() == 1)
+ pcp->inherit_script = parse_bool(0);
+ else
+ pcp->inherit_script = EINA_TRUE;
+}
+
+static void
+st_collections_group_noinherit_script(void)
+{
+ Edje_Part_Collection_Parser *pcp;
+
+ check_arg_count(0);
+
+ pcp = eina_list_last_data_get(edje_collections);
+ pcp->inherit_script = EINA_FALSE;
+}
+
+static void
+_script_flush(void)
+{
+ Edje_Part_Collection_Parser *pcp;
+ Code *code;
+
+ pcp = eina_list_last_data_get(edje_collections);
+ code = eina_list_last_data_get(codes);
+
+ if (!pcp->inherit_script || code->is_lua) return;
+
+ // If script is replaceable and overridable, code->shared will be inherited
+ // script. Free it to avoid duplication.
+ if (script_is_replaceable)
+ {
+ if (code->shared)
+ {
+ free(code->shared);
+ code->shared = NULL;
+ }
+ if (code->original)
+ {
+ free(code->original);
+ code->original = NULL;
+ }
+ }
+
+ script_rewrite(code);
+
+ eina_list_free(pcp->base_codes);
+}
+
+
+/**
+ @page edcref
+ @property
program_source
@parameters
[source name]
@@ -5327,10 +5409,8 @@ st_collections_group_program_source(void)
static void
ob_collections_group_script(void)
{
- Edje_Part_Collection *pc;
Code *cd;
- pc = eina_list_last_data_get(edje_collections);
cd = eina_list_data_get(eina_list_last(codes));
if (!is_verbatim()) track_verbatim(1);
@@ -5345,14 +5425,11 @@ ob_collections_group_script(void)
cd->l2 = get_verbatim_line2();
if (cd->shared)
{
- if (script_override)
+ if (script_is_replaceable)
{
free(cd->shared);
free(cd->original);
- script_override = EINA_FALSE;
-
- WRN("%s:%i. Inherited script block in group \"%s\" is redefined. "
- "This can break inherited edje programs.", file_in, line - 1, pc->part);
+ script_is_replaceable = EINA_FALSE;
}
else
{
@@ -15825,7 +15902,10 @@ edje_cc_handlers_pop_notify(const char *token)
else if (current_program && (!strcmp(token, "link")))
current_program = NULL;
else if (current_de && (!strcmp(token, "group")))
- _link_combine();
+ {
+ _link_combine();
+ _script_flush();
+ }
else if (current_desc && (!strcmp(token, "description")))
free_anchors();
}
diff --git a/src/bin/edje/edje_cc_script.c b/src/bin/edje/edje_cc_script.c
new file mode 100644
index 0000000000..60618f8af3
--- /dev/null
+++ b/src/bin/edje/edje_cc_script.c
@@ -0,0 +1,465 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "edje_cc.h"
+
+#define MESSAGE_OVERRIDE
+
+typedef struct _Code_Symbol
+{
+ const char *name;
+ const char *tag;
+ Eina_List *args;
+ char *body;
+ Eina_Bool is_public : 1;
+} Code_Symbol;
+
+typedef enum
+{
+ TOKEN_TYPE_INVALID = -1,
+ TOKEN_TYPE_EOF,
+ TOKEN_TYPE_COLON = (1 << 0),
+ TOKEN_TYPE_SEMICOLON = (1 << 1),
+ TOKEN_TYPE_COMMA = (1 << 2),
+ TOKEN_TYPE_PARENS = (1 << 3),
+ TOKEN_TYPE_BRACES = (1 << 4),
+ TOKEN_TYPE_EQUAL_MARK = (1 << 5),
+ TOKEN_TYPE_PUBLIC = (1 << 6),
+ TOKEN_TYPE_IDENTIFIER = (1 << 7)
+} Token_Type;
+
+typedef struct _Token
+{
+ char *str;
+ Token_Type type;
+} Token;
+
+static void code_parse_internal(Code *code);
+static Token *next_token(char **begin, char *end);
+
+static void
+code_parse(Code *code)
+{
+ Edje_Part_Collection_Parser *pcp;
+ Code *base;
+ Eina_List *l;
+ int id;
+
+ if (code->is_lua) return;
+
+ id = eina_list_data_idx(codes, code);
+ pcp = eina_list_nth(edje_collections, id);
+
+ EINA_LIST_FOREACH(pcp->base_codes, l, base)
+ {
+ if (!base->parsed)
+ code_parse(base);
+ }
+
+ if (code->shared)
+ code_parse_internal(code);
+
+ code->parsed = EINA_TRUE;
+}
+
+static void
+code_parse_internal(Code *code)
+{
+ Code_Symbol *sym = NULL, *func;
+ Token *token, *tmp;
+ char *begin = code->shared;
+ char *end = begin + strlen(begin);
+ char *body;
+ Eina_Array *stack;
+ Eina_Bool is_args = EINA_FALSE;
+ Eina_Bool is_public = EINA_FALSE;
+ int depth = 0;
+
+ stack = eina_array_new(4);
+
+ while ((token = next_token(&begin, end)))
+ {
+ if (token->type == TOKEN_TYPE_EOF)
+ break;
+
+ // Variables in script cannot be initialized by assignment.
+ // Skip until value assignment expression ends.
+ if (token->type == TOKEN_TYPE_EQUAL_MARK)
+ {
+ while ((tmp = next_token(&begin, end)))
+ {
+ if ((tmp->type == TOKEN_TYPE_COMMA) ||
+ (tmp->type == TOKEN_TYPE_SEMICOLON))
+ {
+ token = tmp;
+ break;
+ }
+ }
+ }
+
+ switch (token->type)
+ {
+ case TOKEN_TYPE_COLON:
+ if (!sym)
+ sym = mem_alloc(SZ(Code_Symbol));
+ sym->tag = eina_array_pop(stack);
+ break;
+ case TOKEN_TYPE_SEMICOLON:
+ if (eina_array_count(stack))
+ {
+ if (!sym)
+ sym = mem_alloc(SZ(Code_Symbol));
+ sym->name = eina_array_pop(stack);
+ sym->is_public = is_public;
+ code->vars = eina_list_append(code->vars, sym);
+ sym = NULL;
+ }
+ is_public = EINA_FALSE;
+ break;
+ case TOKEN_TYPE_COMMA:
+ if (!sym)
+ sym = mem_alloc(SZ(Code_Symbol));
+ sym->name = eina_array_pop(stack);
+ if (is_args)
+ func->args = eina_list_append(func->args, sym);
+ else
+ {
+ sym->is_public = is_public;
+ code->vars = eina_list_append(code->vars, sym);
+ }
+ sym = NULL;
+ break;
+ case TOKEN_TYPE_PARENS:
+ is_args = !is_args;
+ if (is_args)
+ {
+ if (!sym)
+ func = mem_alloc(SZ(Code_Symbol));
+ else
+ {
+ func = sym;
+ sym = NULL;
+ }
+ func->name = eina_array_pop(stack);
+ }
+ else
+ {
+ if (eina_array_count(stack))
+ {
+ if (!sym)
+ sym = mem_alloc(SZ(Code_Symbol));
+ sym->name = eina_array_pop(stack);
+ func->args = eina_list_append(func->args, sym);
+ }
+ sym = func;
+ }
+ break;
+ case TOKEN_TYPE_BRACES:
+ depth = 1;
+ body = begin;
+ while ((tmp = next_token(&begin, end)))
+ {
+ if (tmp->type == TOKEN_TYPE_BRACES)
+ {
+ switch (tmp->str[0])
+ {
+ case '{':
+ depth++;
+ break;
+ case '}':
+ depth--;
+ break;
+ }
+ }
+ if (!depth)
+ break;
+ }
+ if ((begin - 1) > body)
+ {
+ sym->body = mem_alloc(sizeof(char) * (begin - body - 1));
+ strncpy(sym->body, body, (begin - body - 2));
+ }
+ sym->is_public = is_public;
+ code->func = eina_list_append(code->func, sym);
+ sym = NULL;
+ is_public = EINA_FALSE;
+ break;
+ case TOKEN_TYPE_PUBLIC:
+ is_public = EINA_TRUE;
+ break;
+ case TOKEN_TYPE_IDENTIFIER:
+ eina_array_push(stack, token->str);
+ token->str = NULL;
+ break;
+ default:
+ break;
+ }
+
+ if (token->str)
+ free(token->str);
+ free(token);
+ }
+
+ eina_array_free(stack);
+}
+
+static Token *
+next_token(char **begin, char *end)
+{
+ char buf[PATH_MAX] = { 0, };
+ char *src;
+ int index;
+ Token *token;
+ Eina_Bool parsed = EINA_FALSE;
+
+ if (!begin || (*begin >= end))
+ return NULL;
+
+ token = mem_alloc(SZ(Token));
+ token->type = TOKEN_TYPE_INVALID;
+
+ src = *begin - 1;
+ index = 0;
+
+ while (++src < end)
+ {
+ char ch = *src;
+
+ switch (ch)
+ {
+ case ' ':
+ case '\t':
+ case '\n':
+ if (index > 0)
+ parsed = EINA_TRUE;
+ break;
+ case ':':
+ case ';':
+ case ',':
+ case '(':
+ case ')':
+ case '{':
+ case '}':
+ case '=':
+ if (!index)
+ {
+ buf[index++] = ch;
+ src++;
+ }
+ goto exit;
+ default:
+ if (parsed)
+ goto exit;
+ buf[index++] = ch;
+ break;
+ }
+ }
+
+exit:
+ switch (buf[0])
+ {
+ case ':':
+ token->type = TOKEN_TYPE_COLON;
+ break;
+ case ';':
+ token->type = TOKEN_TYPE_SEMICOLON;
+ break;
+ case ',':
+ token->type = TOKEN_TYPE_COMMA;
+ break;
+ case '(':
+ case ')':
+ token->type = TOKEN_TYPE_PARENS;
+ break;
+ case '{':
+ case '}':
+ token->type = TOKEN_TYPE_BRACES;
+ break;
+ case '=':
+ token->type = TOKEN_TYPE_EQUAL_MARK;
+ break;
+ case '\0':
+ token->type = TOKEN_TYPE_EOF;
+ break;
+ }
+
+ if (token->type < 0)
+ {
+ if (!strcmp(buf, "public"))
+ token->type = TOKEN_TYPE_PUBLIC;
+ else
+ token->type = TOKEN_TYPE_IDENTIFIER;
+ }
+
+ *begin = src;
+ token->str = strdup(buf);
+ return token;
+}
+
+static void
+_push_symbol(Eina_List **total, Code_Symbol *sym, Edje_Part_Collection *pc)
+{
+ Eina_List *list, *l;
+ Code_Symbol *sym2;
+
+ list = *total;
+
+ EINA_LIST_FOREACH(list, l, sym2)
+ {
+ if (!strcmp(sym2->name, sym->name))
+ {
+ WRN("Symbols in group \"%s\" have same name \"%s\". Latter defined "
+ "will shadow former one.", pc->part, sym->name);
+ list = eina_list_remove(list, sym2);
+ break;
+ }
+ }
+ list = eina_list_append(list, sym);
+ *total = list;
+}
+
+void
+script_rewrite(Code *code)
+{
+ Edje_Part_Collection *pc;
+ Edje_Part_Collection_Parser *pcp;
+ Code *base;
+ Eina_List *l, *ll;
+ int id, count;
+ Eina_Strbuf *buf;
+ Eina_List *vars = NULL;
+ Eina_List *func = NULL;
+#ifdef MESSAGE_OVERRIDE
+ Eina_List *message = NULL;
+#endif
+ Code_Symbol *sym, *arg;
+
+ code_parse(code);
+
+ id = eina_list_data_idx(codes, code);
+ pc = eina_list_nth(edje_collections, id);
+ pcp = (Edje_Part_Collection_Parser *)pc;
+
+ EINA_LIST_FOREACH(pcp->base_codes, l, base)
+ {
+ EINA_LIST_FOREACH(base->vars, ll, sym)
+ _push_symbol(&vars, sym, pc);
+
+ EINA_LIST_FOREACH(base->func, ll, sym)
+ {
+#ifndef MESSAGE_OVERRIDE
+ _push_symbol(&func, sym, pc);
+#else
+ if (strcmp(sym->name, "message"))
+ _push_symbol(&func, sym, pc);
+ else
+ message = eina_list_append(message, sym);
+#endif
+ }
+ }
+
+ EINA_LIST_FOREACH(code->vars, l, sym)
+ _push_symbol(&vars, sym, pc);
+ EINA_LIST_FOREACH(code->func, l, sym)
+ {
+#ifndef MESSAGE_OVERRIDE
+ _push_symbol(&func, sym, pc);
+#else
+ if (strcmp(sym->name, "message"))
+ _push_symbol(&func, sym, pc);
+ else
+ message = eina_list_append(message, sym);
+#endif
+ }
+
+ buf = eina_strbuf_new();
+
+ if (vars)
+ {
+ count = 0;
+ EINA_LIST_FOREACH(vars, l, sym)
+ {
+ if (!sym->is_public) continue;
+
+ if (count++)
+ eina_strbuf_append(buf, ", ");
+ else
+ eina_strbuf_append(buf, "public ");
+
+ if (sym->tag)
+ eina_strbuf_append_printf(buf, "%s:", sym->tag);
+ eina_strbuf_append(buf, sym->name);
+ }
+ if (count)
+ eina_strbuf_append(buf, ";\n");
+
+ count = 0;
+ EINA_LIST_FOREACH(vars, l, sym)
+ {
+ if (sym->is_public) continue;
+
+ if (count++)
+ eina_strbuf_append(buf, ", ");
+
+ if (sym->tag)
+ eina_strbuf_append_printf(buf, "%s:", sym->tag);
+ eina_strbuf_append(buf, sym->name);
+ }
+ if (count)
+ eina_strbuf_append(buf, ";\n");
+ }
+
+ if (func)
+ {
+ EINA_LIST_FOREACH(func, l, sym)
+ {
+ eina_strbuf_append(buf, "\n");
+ if (sym->is_public)
+ eina_strbuf_append(buf, "public ");
+
+ if (sym->tag)
+ eina_strbuf_append_printf(buf, "%s:", sym->tag);
+ eina_strbuf_append_printf(buf, "%s(", sym->name);
+
+ count = 0;
+ EINA_LIST_FOREACH(sym->args, ll, arg)
+ {
+ if (count++)
+ eina_strbuf_append(buf, ", ");
+
+ if (arg->tag)
+ eina_strbuf_append_printf(buf, "%s:", arg->tag);
+ eina_strbuf_append(buf, arg->name);
+ }
+ eina_strbuf_append(buf, ") {");
+ if (sym->body)
+ {
+ eina_strbuf_append(buf, sym->body);
+ eina_strbuf_rtrim(buf);
+ }
+ eina_strbuf_append(buf, "\n}\n");
+ }
+ }
+
+#ifdef MESSAGE_OVERRIDE
+ if (message)
+ {
+ eina_strbuf_append(buf, "\npublic message(Msg_Type:type, id, ...) {");
+ EINA_LIST_FOREACH(message, l, sym)
+ {
+ eina_strbuf_append(buf, sym->body);
+ eina_strbuf_rtrim(buf);
+ eina_strbuf_append(buf, "\n");
+ }
+ eina_strbuf_append(buf, "}\n");
+ }
+#endif
+
+ code->shared = eina_strbuf_string_steal(buf);
+ code->original = strdup(code->shared);
+ eina_strbuf_free(buf);
+
+ eina_list_free(vars);
+ eina_list_free(func);
+}