q66 pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=8ec7d1cc48585893a993dddf887b7b6f6105ff41

commit 8ec7d1cc48585893a993dddf887b7b6f6105ff41
Author: Daniel Kolesa <d.kol...@osg.samsung.com>
Date:   Fri May 15 15:10:58 2015 +0100

    eolian: much better and stricter redefinition checking
    
    We can now check redefinitions between different types of declarations,
    such as redefinition of struct as variable etc.
    
    @feature
---
 src/lib/eolian/database_type.c   |  3 ++
 src/lib/eolian/database_var.c    |  2 ++
 src/lib/eolian/eo_lexer.c        | 10 +++---
 src/lib/eolian/eo_parser.c       | 66 ++++++++++++++++++++++++++--------------
 src/lib/eolian/eolian_database.c | 13 ++++++++
 src/lib/eolian/eolian_database.h | 20 ++++++++++++
 6 files changed, 87 insertions(+), 27 deletions(-)

diff --git a/src/lib/eolian/database_type.c b/src/lib/eolian/database_type.c
index cfe0dad..60a4f0e 100644
--- a/src/lib/eolian/database_type.c
+++ b/src/lib/eolian/database_type.c
@@ -51,6 +51,7 @@ database_type_add(Eolian_Type *def)
    eina_hash_set(_aliases, def->full_name, def);
    eina_hash_set(_aliasesf, def->base.file, eina_list_append
                 ((Eina_List*)eina_hash_find(_aliasesf, def->base.file), def));
+   database_decl_add(def->full_name, EOLIAN_DECL_ALIAS, def);
 }
 
 void
@@ -59,6 +60,7 @@ database_struct_add(Eolian_Type *tp)
    eina_hash_set(_structs, tp->full_name, tp);
    eina_hash_set(_structsf, tp->base.file, eina_list_append
                 ((Eina_List*)eina_hash_find(_structsf, tp->base.file), tp));
+   database_decl_add(tp->full_name, EOLIAN_DECL_STRUCT, tp);
 }
 
 void
@@ -67,6 +69,7 @@ database_enum_add(Eolian_Type *tp)
    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));
+   database_decl_add(tp->full_name, EOLIAN_DECL_ENUM, tp);
 }
 
 static void
diff --git a/src/lib/eolian/database_var.c b/src/lib/eolian/database_var.c
index f629d48..39bb52a 100644
--- a/src/lib/eolian/database_var.c
+++ b/src/lib/eolian/database_var.c
@@ -28,6 +28,7 @@ database_var_global_add(Eolian_Variable *var)
    eina_hash_set(_globals, var->full_name, var);
    eina_hash_set(_globalsf, var->base.file, eina_list_append
                  ((Eina_List*)eina_hash_find(_globalsf, var->base.file), var));
+   database_decl_add(var->full_name, EOLIAN_DECL_VAR, var);
 }
 
 static void
@@ -36,6 +37,7 @@ database_var_constant_add(Eolian_Variable *var)
    eina_hash_set(_constants, var->full_name, var);
    eina_hash_set(_constantsf, var->base.file, eina_list_append
                  ((Eina_List*)eina_hash_find(_constantsf, var->base.file), 
var));
+   database_decl_add(var->full_name, EOLIAN_DECL_VAR, var);
 }
 
 void
diff --git a/src/lib/eolian/eo_lexer.c b/src/lib/eolian/eo_lexer.c
index 883f2b4..32787f1 100644
--- a/src/lib/eolian/eo_lexer.c
+++ b/src/lib/eolian/eo_lexer.c
@@ -92,15 +92,15 @@ throw(Eo_Lexer *ls, const char *fmt, ...)
    va_start(ap, fmt);
    eina_strbuf_append_vprintf(buf, fmt, ap);
    va_end(ap);
-   eina_strbuf_append_char(buf, ' ');
+   eina_strbuf_append(buf, "\n ");
    while (ln != end && !is_newline(*ln))
      eina_strbuf_append_char(buf,*(ln++));
    eina_strbuf_append_char(buf, '\n');
    for (i = 0; i < ls->column; ++i)
      eina_strbuf_append_char(buf, ' ');
    eina_strbuf_append(buf, "^\n");
-   fprintf(stderr, "eolian:%s:%d: %s\n", ls->source, ls->line_number,
-           eina_strbuf_string_get(buf));
+   fprintf(stderr, "eolian:%s:%d:%d: %s\n", ls->source, ls->line_number,
+           ls->column, eina_strbuf_string_get(buf));
    eina_strbuf_free(buf);
    longjmp(ls->err_jmp, EINA_TRUE);
 }
@@ -767,10 +767,10 @@ eo_lexer_lex_error(Eo_Lexer *ls, const char *msg, int 
token)
      {
         char buf[256];
         txt_token(ls, token, buf);
-        throw(ls, "%s at column %d near '%s'\n", msg, ls->column, buf);
+        throw(ls, "%s near '%s'", msg, buf);
      }
    else
-     throw(ls, "%s at column %d\n", msg, ls->column);
+     throw(ls, "%s", msg);
 }
 
 void
diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c
index 9b3b76f..dfbcbb5 100644
--- a/src/lib/eolian/eo_parser.c
+++ b/src/lib/eolian/eo_parser.c
@@ -135,20 +135,27 @@ compare_class_file(const char *fn1, const char *fn2)
    return !strcmp(fn1, fn2);
 }
 
+static const char *declnames[] = {
+    "class", "type alias", "struct", "enum", "variable"
+};
+
 static void
-redef_error(Eo_Lexer *ls, Eolian_Type_Type type, Eolian_Type *old)
+redef_error(Eo_Lexer *ls, Eolian_Declaration *decl, Eolian_Declaration_Type 
newt)
 {
-   char  buf[256];
-   char fbuf[256] = { '\0' };
-   const char *file = eina_stringshare_ref(ls->filename);
-   if (file != old->base.file)
-     snprintf(fbuf, sizeof(fbuf), " in file '%s'", old->base.file);
-   eina_stringshare_del(file);
-   snprintf(buf, sizeof(buf),
-            "%s '%s' redefined (originally at line %d, column %d%s)",
-            (type == EOLIAN_TYPE_ENUM) ? "enum" : ((type == EOLIAN_TYPE_STRUCT)
-                ? "struct" : "type alias"),
-            old->full_name, old->base.line, old->base.column, fbuf);
+   Eolian_Object *obj = (Eolian_Object *)decl->data;
+   char buf[256], fbuf[256] = { '\0' };
+   if (ls->filename != obj->file)
+     snprintf(fbuf, sizeof(fbuf), "%s:%d:%d", obj->file, obj->line, 
obj->column);
+   else
+     snprintf(fbuf, sizeof(fbuf), "%d:%d", obj->line, obj->column);
+
+   if (newt != decl->type)
+     snprintf(buf, sizeof(buf), "%s '%s' redefined as %s (originally at %s)",
+              declnames[decl->type], decl->name, declnames[newt], fbuf);
+   else
+     snprintf(buf, sizeof(buf), "%s '%s' redefined (originally at %s)",
+              declnames[decl->type], decl->name, fbuf);
+
    eo_lexer_syntax_error(ls, buf);
 }
 
@@ -841,6 +848,7 @@ parse_ptr:
 static Eolian_Type *
 parse_typedef(Eo_Lexer *ls)
 {
+   Eolian_Declaration *decl;
    Eolian_Type *def = push_type(ls);
    Eina_Bool has_extern;
    const char *freefunc;
@@ -857,11 +865,11 @@ parse_typedef(Eo_Lexer *ls)
    parse_name(ls, buf);
    _fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
               &def->full_name, &def->name, &def->namespaces);
-   Eolian_Type *tp = (Eolian_Type*)eina_hash_find(_aliases, def->full_name);
-   if (tp)
+   decl = (Eolian_Declaration *)eina_hash_find(_decls, def->full_name);
+   if (decl)
      {
         eo_lexer_context_restore(ls);
-        redef_error(ls, EOLIAN_TYPE_ALIAS, tp);
+        redef_error(ls, decl, EOLIAN_DECL_ALIAS);
      }
    eo_lexer_context_pop(ls);
    check_next(ls, ':');
@@ -879,6 +887,7 @@ parse_typedef(Eo_Lexer *ls)
 static Eolian_Variable *
 parse_variable(Eo_Lexer *ls, Eina_Bool global)
 {
+   Eolian_Declaration *decl;
    Eolian_Variable *def = calloc(1, sizeof(Eolian_Variable));
    Eina_Bool has_extern = EINA_FALSE;
    Eina_Strbuf *buf;
@@ -899,6 +908,13 @@ parse_variable(Eo_Lexer *ls, Eina_Bool global)
    parse_name(ls, buf);
    _fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
               &def->full_name, &def->name, &def->namespaces);
+   decl = (Eolian_Declaration *)eina_hash_find(_decls, def->full_name);
+   if (decl)
+     {
+        eo_lexer_context_restore(ls);
+        redef_error(ls, decl, EOLIAN_DECL_VAR);
+     }
+   eo_lexer_context_pop(ls);
    check_next(ls, ':');
    def->base_type = parse_type(ls);
    pop_type(ls);
@@ -1702,6 +1718,7 @@ parse_class_body(Eo_Lexer *ls, Eolian_Class_Type type)
 static void
 parse_class(Eo_Lexer *ls, Eolian_Class_Type type)
 {
+   Eolian_Declaration *decl;
    const char *bnm;
    char *fnm;
    Eina_Bool same;
@@ -1723,10 +1740,16 @@ parse_class(Eo_Lexer *ls, Eolian_Class_Type type)
         eo_lexer_context_restore(ls);
         eo_lexer_syntax_error(ls, "class and file names differ");
      }
-   eo_lexer_context_pop(ls);
    _fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
               &ls->tmp.kls->full_name, &ls->tmp.kls->name,
               &ls->tmp.kls->namespaces);
+   decl = (Eolian_Declaration *)eina_hash_find(_decls, ls->tmp.kls->full_name);
+   if (decl)
+     {
+        eo_lexer_context_restore(ls);
+        redef_error(ls, decl, EOLIAN_DECL_CLASS);
+     }
+   eo_lexer_context_pop(ls);
    pop_strbuf(ls);
    if (ls->t.token != '{')
      {
@@ -1784,7 +1807,7 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
            Eina_Bool is_enum = (ls->t.kw == KW_enum);
            const char *name;
            int line, col;
-           Eolian_Type *tp;
+           Eolian_Declaration *decl;
            Eina_Bool has_extern;
            const char *freefunc;
            Eina_Strbuf *buf;
@@ -1796,14 +1819,12 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
            col = ls->column;
            parse_name(ls, buf);
            name = eina_stringshare_add(eina_strbuf_string_get(buf));
-           tp = (Eolian_Type*)eina_hash_find(is_enum ? _enums
-                                                     : _structs, name);
-           if (tp)
+           decl = (Eolian_Declaration *)eina_hash_find(_decls, name);
+           if (decl)
              {
                 eina_stringshare_del(name);
                 eo_lexer_context_restore(ls);
-                redef_error(ls, is_enum ? EOLIAN_TYPE_ENUM
-                                        : EOLIAN_TYPE_STRUCT, tp);
+                redef_error(ls, decl, is_enum ? EOLIAN_DECL_ENUM : 
EOLIAN_DECL_STRUCT);
              }
            eo_lexer_context_pop(ls);
            pop_strbuf(ls);
@@ -1840,6 +1861,7 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
      }
    return EINA_FALSE;
 found_class:
+   database_decl_add(ls->tmp.kls->full_name, EOLIAN_DECL_CLASS, ls->tmp.kls);
    ls->tmp.classes = eina_list_append(ls->tmp.classes, ls->tmp.kls);
    ls->tmp.kls = NULL;
    return EINA_TRUE;
diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c
index e5a3f6f..615c774 100644
--- a/src/lib/eolian/eolian_database.c
+++ b/src/lib/eolian/eolian_database.c
@@ -22,6 +22,7 @@ Eina_Hash *_constantsf = NULL;
 Eina_Hash *_filenames  = NULL;
 Eina_Hash *_tfilenames = NULL;
 Eina_Hash *_depclasses = NULL;
+Eina_Hash *_decls      = NULL;
 
 static int _database_init_count = 0;
 
@@ -64,6 +65,7 @@ database_init()
    _filenames  = eina_hash_string_small_new(free);
    _tfilenames = eina_hash_string_small_new(free);
    _depclasses = eina_hash_stringshared_new(EINA_FREE_CB(_deplist_free));
+   _decls      = eina_hash_stringshared_new(free);
    return ++_database_init_count;
 }
 
@@ -94,11 +96,22 @@ database_shutdown()
         eina_hash_free(_filenames ); _filenames  = NULL;
         eina_hash_free(_tfilenames); _tfilenames = NULL;
         eina_hash_free(_depclasses); _depclasses = NULL;
+        eina_hash_free(_decls     ); _decls      = NULL;
         eina_shutdown();
      }
    return _database_init_count;
 }
 
+void
+database_decl_add(Eina_Stringshare *name, Eolian_Declaration_Type type, void 
*ptr)
+{
+   Eolian_Declaration *decl = calloc(1, sizeof(Eolian_Declaration));
+   decl->type = type;
+   decl->name = name;
+   decl->data = ptr;
+   eina_hash_set(_decls, name, decl);
+}
+
 #define EO_SUFFIX ".eo"
 #define EOT_SUFFIX ".eot"
 
diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h
index 2f4b82e..5ea8674 100644
--- a/src/lib/eolian/eolian_database.h
+++ b/src/lib/eolian/eolian_database.h
@@ -49,6 +49,9 @@ extern Eina_Hash *_tfilenames;
 /* a hash holding lists of deps */
 extern Eina_Hash *_depclasses;
 
+/* a hash holding all declarations, for redef checking etc */
+extern Eina_Hash *_decls;
+
 typedef struct _Eolian_Object
 {
    const char *file;
@@ -63,6 +66,21 @@ typedef struct _Eolian_Dependency
    Eina_Stringshare *name;
 } Eolian_Dependency;
 
+typedef enum {
+    EOLIAN_DECL_CLASS,
+    EOLIAN_DECL_ALIAS,
+    EOLIAN_DECL_STRUCT,
+    EOLIAN_DECL_ENUM,
+    EOLIAN_DECL_VAR
+} Eolian_Declaration_Type;
+
+typedef struct _Eolian_Declaration
+{
+   Eolian_Declaration_Type type;
+   Eina_Stringshare *name;
+   void *data;
+} Eolian_Declaration;
+
 struct _Eolian_Class
 {
    Eolian_Object base;
@@ -251,6 +269,8 @@ char *database_class_to_filename(const char *cname);
 Eina_Bool database_validate(void);
 Eina_Bool database_class_name_validate(const char *class_name, const 
Eolian_Class **cl);
 
+void database_decl_add(Eina_Stringshare *name, Eolian_Declaration_Type type, 
void *ptr);
+
 /* types */
 
 void database_type_add(Eolian_Type *def);

-- 


Reply via email to