diff --git a/src/lib/eolian/database_type.c b/src/lib/eolian/database_type.c index cfe0dad918..60a4f0e535 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 f629d48ca1..39bb52a84d 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 883f2b486b..32787f121a 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 9b3b76f24e..dfbcbb54f4 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 e5a3f6f643..615c7741ad 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 2f4b82e3ab..5ea8674a06 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);