jaehyun pushed a commit to branch master.

http://git.enlightenment.org/tools/enventor.git/commit/?id=335575eb84a87e38ee1ef4ff16673d5336ab6fdf

commit 335575eb84a87e38ee1ef4ff16673d5336ab6fdf
Author: Jaehyun Cho <jae_hyun....@samsung.com>
Date:   Tue Dec 29 19:22:01 2015 +0900

    Support to use macro as a group name.
    
    Previously, group name was recognized with double quotation marks("").
    This makes defined macro cannot be used as a group name.
    Now, defined macro is parsed and listed. Macro group name is recognized
    from the defined macro list.
---
 src/lib/edc_editor.c       |   5 +
 src/lib/edc_parser.c       | 527 ++++++++++++++++++++++++++++++++++++++++++---
 src/lib/enventor_private.h |   4 +
 3 files changed, 505 insertions(+), 31 deletions(-)

diff --git a/src/lib/edc_editor.c b/src/lib/edc_editor.c
index c54ca59..2e9e5b9 100644
--- a/src/lib/edc_editor.c
+++ b/src/lib/edc_editor.c
@@ -276,6 +276,11 @@ edit_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, 
void *event_info)
    edit_data *ed = data;
    edit_changed_set(ed, EINA_TRUE);
 
+   const char *text = elm_entry_entry_get(ed->en_edit);
+   char *utf8 = elm_entry_markup_to_utf8(text);
+   parser_macro_list_set(ed->pd, utf8);
+   free(utf8);
+
    Eina_Bool syntax_color = EINA_TRUE;
    ed->error_line = -1;
    eina_stringshare_del(ed->error_target);
diff --git a/src/lib/edc_parser.c b/src/lib/edc_parser.c
index 09ece69..235137c 100644
--- a/src/lib/edc_parser.c
+++ b/src/lib/edc_parser.c
@@ -10,6 +10,20 @@ const char ATTR_PREPEND_NONE[] = "";
 const char ATTR_APPEND_SEMICOLON[] = ";";
 const char ATTR_APPEND_TRANSITION_TIME[] = " 1.0;";
 
+typedef enum {
+   PREPROC_DIRECTIVE_NONE,
+   PREPROC_DIRECTIVE_DEFINE,
+   PREPROC_DIRECTIVE_UNDEF
+} Preproc_Directive;
+
+typedef struct defined_macro_s
+{
+   char *name;
+   char *definition;
+   int begin_line;
+   int end_line;     //0 means that this macro is valid until the end of file.
+} defined_macro;
+
 typedef struct parser_attr_s
 {
    Eina_Stringshare *keyword;
@@ -43,6 +57,7 @@ struct parser_s
    Eina_Inarray *attrs;
    cur_name_td *cntd;
    type_init_td *titd;
+   Eina_List *macro_list;
 };
 
 
@@ -50,12 +65,230 @@ struct parser_s
 /* Internal method implementation                                            */
 /*****************************************************************************/
 
+/* Remove double quotation marks indicating a string to extract a pure string.
+ * Return translated macro.
+ */
+static char *
+double_quotation_marks_remove(const char *str)
+{
+   char *new_str = NULL;
+   int i;
+   int j;
+   int len;
+   int new_len;
+   int cnt;
+
+   if (!str) return NULL;
+
+   len = strlen(str);
+   cnt = 0;
+   for (i = 0; i < len; i++)
+     {
+        if (str[i] == '"')
+          {
+             cnt++;
+
+             if ((i > 0) && (str[i - 1] == '\\')) cnt--;
+          }
+     }
+
+   new_len = len - cnt;
+   new_str = (char *) calloc(new_len * sizeof(char), 1);
+   j = 0;
+   for (i = 0; i < len; i++)
+     {
+        if (str[i] != '"')
+          {
+             new_str[j] = str[i];
+             j++;
+          }
+        else
+          {
+             if ((i > 0) && (str[i - 1] == '\\'))
+               {
+                  new_str[j] = str[i];
+                  j++;
+               }
+          }
+     }
+
+   return new_str;
+}
+
+/* Convert input into output based on macro definitions of macro list.
+ * Return translated macro.
+ */
+static char *
+macro_translate(Eina_List *macro_list, const char *macro, int macro_line)
+{
+   defined_macro *macro_node = NULL;
+   Eina_List *l = NULL;
+   char *cur_trans_macro = NULL;
+   char *trans_macro = NULL;
+
+   if (!macro) return NULL;
+
+   trans_macro = strdup(macro);
+
+   EINA_LIST_REVERSE_FOREACH(macro_list, l, macro_node)
+     {
+        int cur_len;
+        int new_len;
+        int macro_name_len;
+        int macro_def_len;
+        long replace_begin_index;
+        char *sub_macro = NULL;
+
+        sub_macro = strstr(trans_macro, macro_node->name);
+        if (!sub_macro) continue;
+
+        if (macro_line < macro_node->begin_line) continue;
+
+        if ((macro_node->end_line != 0) &&
+            (macro_line > macro_node->end_line)) continue;
+
+        replace_begin_index = sub_macro - trans_macro;
+
+        cur_len = strlen(trans_macro);
+        macro_name_len = strlen(macro_node->name);
+        if (macro_node->definition)
+          macro_def_len = strlen(macro_node->definition);
+        else
+          macro_def_len = 0;
+        new_len = cur_len + (macro_def_len - macro_name_len);
+
+        cur_trans_macro = strdup(trans_macro);
+        free(trans_macro);
+
+        trans_macro = (char *) calloc(new_len * sizeof(char), 1);
+        strncpy(trans_macro, cur_trans_macro, replace_begin_index);
+        strncpy(&trans_macro[replace_begin_index], macro_node->definition,
+                macro_def_len);
+        strncpy(&trans_macro[replace_begin_index + macro_def_len],
+                &cur_trans_macro[replace_begin_index + macro_name_len],
+                new_len - (replace_begin_index + macro_def_len));
+
+        free(cur_trans_macro);
+     }
+
+   cur_trans_macro = strdup(trans_macro);
+   free(trans_macro);
+
+   trans_macro = double_quotation_marks_remove(cur_trans_macro);
+   free(cur_trans_macro);
+
+   return trans_macro;
+}
+
+/* Parse macro into name and definition.
+ * Return EINA_TRUE if parsing is successful.
+ * Return EINA_FALSE if parsing is failed.
+ */
+static Eina_Bool
+define_parse(const char *macro, char **name, char **definition)
+{
+   int i;
+   int macro_len;
+   int name_len;
+   int def_len;
+   int name_end_index;
+   int def_begin_index;
+   char *macro_name;
+   char *macro_def;
+
+   if (!macro) return EINA_FALSE;
+
+   macro_len = strlen(macro);
+   name_end_index = -1;
+   def_begin_index = -1;
+
+   for (i = 0; i < macro_len; i++)
+     {
+        if (isspace(macro[i]))
+          {
+             if (name_end_index == -1)
+               name_end_index = i - 1;
+          }
+        else
+          {
+             if (name_end_index != -1)
+               {
+                  def_begin_index = i;
+                  break;
+               }
+          }
+     }
+
+   if (i == macro_len)
+     {
+        name_end_index = i - 1;
+        def_begin_index = macro_len;
+     }
+
+   if (name)
+     {
+        name_len = name_end_index + 1;
+
+        if (name_len == 0)
+          *name = NULL;
+        else
+          {
+             macro_name = strndup(macro, name_len);
+             *name = macro_name;
+          }
+     }
+
+   if (definition)
+     {
+        def_len = macro_len - def_begin_index;
+        if (def_len == 0)
+          *definition = NULL;
+        else
+          {
+             macro_def = strndup(&macro[def_begin_index], def_len);
+             *definition = macro_def;
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+macro_node_free(defined_macro *macro)
+{
+   if (!macro) return;
+
+   if (macro->name)
+     {
+        free(macro->name);
+        macro->name = NULL;
+     }
+   if (macro->definition)
+     {
+        free(macro->definition);
+        macro->definition = NULL;
+     }
+}
+
+static void
+macro_list_free(Eina_List *macro_list)
+{
+   defined_macro *macro = NULL;
+
+   EINA_LIST_FREE(macro_list, macro)
+     {
+        macro_node_free(macro);
+     }
+}
+
 static void
 group_name_thread_blocking(void *data, Ecore_Thread *thread EINA_UNUSED)
 {
    const char *quot = QUOT_UTF8;
+   const char *semicol = SEMICOL_UTF8;
    const char *group = "group";
    const int quot_len = QUOT_UTF8_LEN;
+   const int semicol_len = SEMICOL_UTF8_LEN;
    const int group_len = 5;  //strlen("group");
 
    cur_name_td *td = data;
@@ -68,8 +301,13 @@ group_name_thread_blocking(void *data, Ecore_Thread *thread 
EINA_UNUSED)
    const char *group_name = NULL;
    int group_name_len = 0;
 
+   int cur_line = 1;
+   Eina_List *macro_list = parser_macro_list_get(td->pd);
+
    while (p <= end)
      {
+        if (*p == '\n') cur_line++;
+
         //Skip "" range
         if (!strncmp(p, quot, quot_len))
           {
@@ -77,6 +315,7 @@ group_name_thread_blocking(void *data, Ecore_Thread *thread 
EINA_UNUSED)
              p = strstr(p, quot);
              if (!p) goto end;
              p += quot_len;
+             continue;
           }
 
         if (*p == '{')
@@ -99,22 +338,53 @@ group_name_thread_blocking(void *data, Ecore_Thread 
*thread EINA_UNUSED)
         if (!strncmp(p, group, group_len))
           {
              p += group_len;
-             char *name_begin = strstr(p, quot);
-             if (!name_begin) goto end;
-             name_begin += quot_len;
-             p = name_begin;
-             char *name_end = strstr(p, quot);
+
+             char *name_end = strstr(p, semicol);
              if (!name_end) goto end;
+
+             char *space_pos = NULL;
+             char *temp_pos = strchr(p, ' ');
+             while (temp_pos && (temp_pos < name_end))
+               {
+                  space_pos = temp_pos;
+                  temp_pos++;
+                  temp_pos = strchr(temp_pos, ' ');
+               }
+
+             char *tab_pos = NULL;
+             temp_pos = strchr(p, '\t');
+             while (temp_pos && (temp_pos < name_end))
+               {
+                  tab_pos = temp_pos;
+                  temp_pos++;
+                  temp_pos = strchr(p, '\t');
+               }
+
+             char *name_begin = space_pos > tab_pos ? space_pos : tab_pos;
+             if (!name_begin) goto end;
+             name_begin++;
+
              group_name = name_begin;
              group_name_len = name_end - name_begin;
-             p = name_end + quot_len;
+             p = name_end + semicol_len;
              bracket++;
              continue;
           }
         p++;
      }
    if (group_name)
-     group_name = eina_stringshare_add_length(group_name, group_name_len);
+     {
+        group_name = eina_stringshare_add_length(group_name, group_name_len);
+
+        char *trans_group_name = NULL;
+        trans_group_name = macro_translate(macro_list, group_name, cur_line);
+        if (trans_group_name)
+          {
+             eina_stringshare_del(group_name);
+             group_name = eina_stringshare_add(trans_group_name);
+             free(trans_group_name);
+          }
+     }
 
 end:
    free(utf8);
@@ -160,12 +430,17 @@ cur_state_thread_blocking(void *data, Ecore_Thread 
*thread EINA_UNUSED)
    int value_len = 0;
    double value_convert = 0.0;
 
+   int cur_line = 1;
+   Eina_List *macro_list = parser_macro_list_get(td->pd);
+
    td->part_name = NULL;
    td->group_name = NULL;
    td->state_name = NULL;
 
    while (p && p <= end)
      {
+        if (*p == '\n') cur_line++;
+
         //Skip "" range
         if (!strncmp(p, QUOT_UTF8, QUOT_UTF8_LEN))
           {
@@ -173,6 +448,7 @@ cur_state_thread_blocking(void *data, Ecore_Thread *thread 
EINA_UNUSED)
              p = strstr(p, QUOT_UTF8);
              if (!p) goto end;
              p += QUOT_UTF8_LEN;
+             continue;
           }
 
         //Enter one depth into Bracket.
@@ -344,15 +620,35 @@ cur_state_thread_blocking(void *data, Ecore_Thread 
*thread EINA_UNUSED)
              if (!strncmp(p, GROUP, strlen(GROUP)))
                {
                   p += strlen(GROUP);
-                  char *name_begin = strstr(p, QUOT_UTF8);
-                  if (!name_begin) goto end;
-                  name_begin += QUOT_UTF8_LEN;
-                  p = name_begin;
-                  char *name_end = strstr(p, QUOT_UTF8);
+
+                  char *name_end = strstr(p, SEMICOL_UTF8);
                   if (!name_end) goto end;
+
+                  char *space_pos = NULL;
+                  char *temp_pos = strchr(p, ' ');
+                  while (temp_pos && (temp_pos < name_end))
+                    {
+                       space_pos = temp_pos;
+                       temp_pos++;
+                       temp_pos = strchr(temp_pos, ' ');
+                    }
+
+                  char *tab_pos = NULL;
+                  temp_pos = strchr(p, '\t');
+                  while (temp_pos && (temp_pos < name_end))
+                    {
+                       tab_pos = temp_pos;
+                       temp_pos++;
+                       temp_pos = strchr(p, '\t');
+                    }
+
+                  char *name_begin = space_pos > tab_pos ? space_pos : tab_pos;
+                  if (!name_begin) goto end;
+                  name_begin++;
+
                   group_name = name_begin;
                   group_name_len = name_end - name_begin;
-                  p = name_end + QUOT_UTF8_LEN;
+                  p = name_end + SEMICOL_UTF8_LEN;
                   bracket++;
                   continue;
                }
@@ -362,10 +658,21 @@ cur_state_thread_blocking(void *data, Ecore_Thread 
*thread EINA_UNUSED)
 
    if (part_name)
      part_name = eina_stringshare_add_length(part_name, part_name_len);
-   if (group_name)
-     group_name = eina_stringshare_add_length(group_name, group_name_len);
    if (desc_name)
      desc_name = eina_stringshare_add_length(desc_name, desc_name_len);
+   if (group_name)
+     {
+        group_name = eina_stringshare_add_length(group_name, group_name_len);
+
+        char *trans_group_name = NULL;
+        trans_group_name = macro_translate(macro_list, group_name, cur_line);
+        if (trans_group_name)
+          {
+             eina_stringshare_del(group_name);
+             group_name = eina_stringshare_add(trans_group_name);
+             free(trans_group_name);
+          }
+     }
 
    td->part_name = part_name;
    td->group_name = group_name;
@@ -1322,6 +1629,7 @@ parser_cur_name_fast_get(Evas_Object *entry, const char 
*scope)
              p = strstr(p, quot);
              if (!p) goto end;
              p += quot_len;
+             continue;
           }
 
         if (*p == '{')
@@ -1449,20 +1757,141 @@ parser_line_cnt_get(parser_data *pd EINA_UNUSED, const 
char *src)
    return cnt;
 }
 
+void
+parser_macro_list_set(parser_data *pd, const char *text)
+{
+   const char str_define[] = "#define";
+   const char str_undef[] = "#undef";
+   int len;
+   int i;
+   int cur_line;
+   Eina_List *macro_list = NULL;
+   Preproc_Directive found_directive = PREPROC_DIRECTIVE_NONE;
+
+   if (!text) return;
+
+   len = strlen(text);
+   cur_line = 1;
+   for (i = 0; i < len; i++)
+     {
+        if (isspace(text[i]))
+          {
+             if (text[i] == '\n') cur_line++;
+
+             continue;
+          }
+
+        if (found_directive == PREPROC_DIRECTIVE_DEFINE)
+          {
+             defined_macro *macro_node;
+             char *macro = NULL;
+             char *macro_name = NULL;
+             char *macro_def = NULL;
+             char *trans_macro = NULL;
+             const char *new_line_pos = strchr(&text[i], '\n');
+             long macro_len = new_line_pos - &text[i];
+
+             if (macro_len > 0)
+               {
+                  macro = strndup(&text[i], (int) macro_len);
+
+                  define_parse(macro, &macro_name, &macro_def);
+
+                  trans_macro = macro_translate(macro_list, macro_def,
+                                                cur_line);
+
+                  macro_node = calloc(sizeof(defined_macro), 1);
+                  macro_node->name = strdup(macro_name);
+                  macro_node->definition = trans_macro;
+                  macro_node->begin_line = cur_line;
+                  macro_node->end_line = 0;
+
+                  macro_list = eina_list_append(macro_list, macro_node);
+
+                  i += strlen(macro) - 1;
+                  free(macro);
+               }
+             found_directive = PREPROC_DIRECTIVE_NONE;
+          }
+        else if (found_directive == PREPROC_DIRECTIVE_UNDEF)
+          {
+             Eina_List *l = NULL;
+             defined_macro *macro_node;
+             char *macro_name = NULL;
+             const char *new_line_pos = strchr(&text[i], '\n');
+             long macro_name_len = new_line_pos - &text[i];
+
+             if (macro_name_len > 0)
+               {
+                  macro_name = strndup(&text[i], (int) macro_name_len);
+
+                  EINA_LIST_FOREACH(macro_list, l, macro_node)
+                    {
+                       if (!strcmp(macro_name, macro_node->name) &&
+                           (macro_node->end_line == -1))
+                         {
+                            macro_node->end_line = cur_line;
+                            break;
+                         }
+                    }
+                  i += strlen(macro_name) - 1;
+                  free(macro_name);
+               }
+             found_directive = PREPROC_DIRECTIVE_NONE;
+          }
+        else
+          {
+             if (text[i] == '#')
+               {
+                  if (!strncmp(&text[i], str_define, strlen(str_define)))
+                    {
+                       found_directive = PREPROC_DIRECTIVE_DEFINE;
+                       i += strlen(str_define) - 1;
+                    }
+                  else if (!strncmp(&text[i], str_undef, strlen(str_undef)))
+                    {
+                       found_directive = PREPROC_DIRECTIVE_UNDEF;
+                       i += strlen(str_undef) - 1;
+                    }
+               }
+          }
+     }
+
+   if (pd->macro_list) macro_list_free(pd->macro_list);
+
+   pd->macro_list = macro_list;
+}
+
+Eina_List *
+parser_macro_list_get(parser_data *pd)
+{
+   return pd->macro_list;
+}
+
 Eina_Stringshare *
-parser_first_group_name_get(parser_data *pd EINA_UNUSED, Evas_Object *entry)
+parser_first_group_name_get(parser_data *pd, Evas_Object *entry)
 {
-   Evas_Object *tb = elm_entry_textblock_get(entry);
-   char *text = (char *) evas_object_textblock_text_markup_get(tb);
-   char *p = text;
+   const char *markup = elm_entry_entry_get(entry);
+   char *utf8 = elm_entry_markup_to_utf8(markup);
+   char *p = utf8;
 
-   const char *quot = QUOT;
-   int quot_len = QUOT_LEN;
+   const char *quot = QUOT_UTF8;
+   const char *semicol = SEMICOL_UTF8;
    const char *group = "group";
-   int group_len = 5; //strlen("group");
+   const int quot_len = QUOT_UTF8_LEN;
+   const int semicol_len = SEMICOL_UTF8_LEN;
+   const int group_len = 5; //strlen("group");
+
+   const char *group_name = NULL;
 
-   while (p < (text + strlen(text)))
+   int cur_line = 1;
+   parser_macro_list_set(pd, (const char *) utf8);
+   Eina_List *macro_list = parser_macro_list_get(pd);
+
+   while (p < (utf8 + strlen(utf8)))
      {
+        if (*p == '\n') cur_line++;
+
         //Skip "" range
         if (!strncmp(p, quot, quot_len))
           {
@@ -1470,24 +1899,57 @@ parser_first_group_name_get(parser_data *pd 
EINA_UNUSED, Evas_Object *entry)
              p = strstr(p, quot);
              if (!p) return NULL;
              p += quot_len;
+             continue;
           }
 
        if (!strncmp(p, group, group_len))
           {
              p += group_len;
-             char *name_begin = strstr(p, quot);
-             if (!name_begin) return NULL;
-             name_begin += quot_len;
-             p = name_begin;
-             char *name_end = strstr(p, quot);
+
+             char *name_end = strstr(p, semicol);
              if (!name_end) return NULL;
-             return eina_stringshare_add_length(name_begin,
-                                                name_end - name_begin);
+
+             char *space_pos = NULL;
+             char *temp_pos = strchr(p, ' ');
+             while (temp_pos && (temp_pos < name_end))
+               {
+                  space_pos = temp_pos;
+                  temp_pos++;
+                  temp_pos = strchr(temp_pos, ' ');
+               }
+
+             char *tab_pos = NULL;
+             temp_pos = strchr(p, '\t');
+             while (temp_pos && (temp_pos < name_end))
+               {
+                  tab_pos = temp_pos;
+                  temp_pos++;
+                  temp_pos = strchr(p, '\t');
+               }
+
+             char *name_begin = space_pos > tab_pos ? space_pos : tab_pos;
+             if (!name_begin) return NULL;
+             name_begin++;
+
+             group_name = eina_stringshare_add_length(name_begin,
+                                                      name_end - name_begin);
              break;
           }
         p++;
      }
-   return NULL;
+
+   if (group_name)
+     {
+        char *trans_group_name = NULL;
+        trans_group_name = macro_translate(macro_list, group_name, cur_line);
+        if (trans_group_name)
+          {
+             eina_stringshare_del(group_name);
+             group_name = eina_stringshare_add(trans_group_name);
+             free(trans_group_name);
+          }
+     }
+   return group_name;
 }
 
 Eina_List *
@@ -1566,6 +2028,9 @@ parser_term(parser_data *pd)
 
    eina_inarray_free(pd->attrs);
 
+   macro_list_free(pd->macro_list);
+   pd->macro_list = NULL;
+
    free(pd);
 }
 
diff --git a/src/lib/enventor_private.h b/src/lib/enventor_private.h
index 0e65d61..b3fe055 100644
--- a/src/lib/enventor_private.h
+++ b/src/lib/enventor_private.h
@@ -26,6 +26,8 @@
 #define QUOT_LEN 6
 #define QUOT_UTF8 "\""
 #define QUOT_UTF8_LEN 1
+#define SEMICOL_UTF8 ";"
+#define SEMICOL_UTF8_LEN 1
 #define EOL "<br/>"
 #define EOL_LEN 5
 #define TAB "<tab/>"
@@ -135,6 +137,8 @@ Eina_Bool parser_images_pos_get(const Evas_Object *entry, 
int *ret);
 Eina_Bool parser_styles_pos_get(const Evas_Object *entry, int *ret);
 const char *parser_colon_pos_get(parser_data *pd EINA_UNUSED, const char *cur);
 Eina_Bool parser_state_info_get(Evas_Object *entry, state_info *info);
+void parser_macro_list_set(parser_data *pd, const char *text);
+Eina_List *parser_macro_list_get(parser_data *pd);
 
 
 /* syntax helper */

-- 


Reply via email to