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