summaryrefslogtreecommitdiff
path: root/src/lib/eolian
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2019-06-21 15:05:50 +0200
committerDaniel Kolesa <d.kolesa@samsung.com>2019-06-24 15:15:30 +0200
commit1bbf4380abce4c704eb101d1bbfd8795ee31044b (patch)
treee0117464464d17ea8be870172e48d3c9bafc1495 /src/lib/eolian
parent61235a6e5c47a564d217576fbcdef4e3c0a59b6f (diff)
eolian: add library support for declaring and using errors
You can now declare errors like this: error Foo = "message"; [[documentation]] Then you can use them as types like this: foo { return: error(Error1, Error2, ...); } They have a separate type category and storage. They are checked for redefinitions the same as anything else though. This does not add any generator support nor it adds any advanced checking. Ref T6890
Diffstat (limited to 'src/lib/eolian')
-rw-r--r--src/lib/eolian/Eolian.h178
-rw-r--r--src/lib/eolian/database_type_api.c9
-rw-r--r--src/lib/eolian/database_validate.c22
-rw-r--r--src/lib/eolian/eo_lexer.h14
-rw-r--r--src/lib/eolian/eo_parser.c102
-rw-r--r--src/lib/eolian/eolian_database.c70
-rw-r--r--src/lib/eolian/eolian_database.h15
7 files changed, 406 insertions, 4 deletions
diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h
index 80ccd1ef94..4c9535dc03 100644
--- a/src/lib/eolian/Eolian.h
+++ b/src/lib/eolian/Eolian.h
@@ -170,6 +170,12 @@ typedef struct _Eolian_Expression Eolian_Expression;
170 */ 170 */
171typedef struct _Eolian_Variable Eolian_Variable; 171typedef struct _Eolian_Variable Eolian_Variable;
172 172
173/* Error information
174 *
175 * @ingroup Eolian
176 */
177typedef struct _Eolian_Error Eolian_Error;
178
173/* Struct field information 179/* Struct field information
174 * 180 *
175 * @ingroup Eolian 181 * @ingroup Eolian
@@ -222,7 +228,8 @@ typedef enum
222 EOLIAN_OBJECT_PART, 228 EOLIAN_OBJECT_PART,
223 EOLIAN_OBJECT_IMPLEMENT, 229 EOLIAN_OBJECT_IMPLEMENT,
224 EOLIAN_OBJECT_CONSTRUCTOR, 230 EOLIAN_OBJECT_CONSTRUCTOR,
225 EOLIAN_OBJECT_DOCUMENTATION 231 EOLIAN_OBJECT_DOCUMENTATION,
232 EOLIAN_OBJECT_ERROR
226} Eolian_Object_Type; 233} Eolian_Object_Type;
227 234
228typedef enum 235typedef enum
@@ -276,6 +283,7 @@ typedef enum
276 EOLIAN_TYPE_VOID, 283 EOLIAN_TYPE_VOID,
277 EOLIAN_TYPE_REGULAR, 284 EOLIAN_TYPE_REGULAR,
278 EOLIAN_TYPE_CLASS, 285 EOLIAN_TYPE_CLASS,
286 EOLIAN_TYPE_ERROR,
279 EOLIAN_TYPE_UNDEFINED 287 EOLIAN_TYPE_UNDEFINED
280} Eolian_Type_Type; 288} Eolian_Type_Type;
281 289
@@ -1079,6 +1087,16 @@ EAPI const Eolian_Variable *eolian_unit_global_by_name_get(const Eolian_Unit *un
1079EAPI const Eolian_Variable *eolian_unit_constant_by_name_get(const Eolian_Unit *unit, const char *name); 1087EAPI const Eolian_Variable *eolian_unit_constant_by_name_get(const Eolian_Unit *unit, const char *name);
1080 1088
1081/* 1089/*
1090 * @brief Get an error declaration in a unit by name.
1091 *
1092 * @param[in] unit The unit.
1093 * @param[in] name the name of the error
1094 *
1095 * @ingroup Eolian
1096 */
1097EAPI const Eolian_Error *eolian_unit_error_by_name_get(const Eolian_Unit *unit, const char *name);
1098
1099/*
1082 * @brief Get an iterator to all constant variables in the Eolian database. 1100 * @brief Get an iterator to all constant variables in the Eolian database.
1083 * 1101 *
1084 * @return the iterator or NULL 1102 * @return the iterator or NULL
@@ -1101,6 +1119,17 @@ EAPI Eina_Iterator *eolian_unit_constants_get(const Eolian_Unit *unit);
1101EAPI Eina_Iterator *eolian_unit_globals_get(const Eolian_Unit *unit); 1119EAPI Eina_Iterator *eolian_unit_globals_get(const Eolian_Unit *unit);
1102 1120
1103/* 1121/*
1122 * @brief Get an iterator to all error declarations in the Eolian database.
1123 *
1124 * @return the iterator or NULL
1125 *
1126 * Thanks to internal caching, this is an O(1) operation.
1127 *
1128 * @ingroup Eolian
1129 */
1130EAPI Eina_Iterator *eolian_unit_errors_get(const Eolian_Unit *unit);
1131
1132/*
1104 * @brief Get an alias type declaration within a unit by name. 1133 * @brief Get an alias type declaration within a unit by name.
1105 * 1134 *
1106 * @param[in] unit The unit. 1135 * @param[in] unit The unit.
@@ -1266,6 +1295,19 @@ eolian_state_constant_by_name_get(const Eolian_State *state, const char *name)
1266} 1295}
1267 1296
1268/* 1297/*
1298 * @brief A helper function to get an error declaration in a state by name.
1299 *
1300 * @see eolian_unit_error_by_name_get
1301 *
1302 * @ingroup Eolian
1303 */
1304static inline const Eolian_Error *
1305eolian_state_error_by_name_get(const Eolian_State *state, const char *name)
1306{
1307 return eolian_unit_error_by_name_get(EOLIAN_UNIT(state), name);
1308}
1309
1310/*
1269 * @brief Get an iterator to all global variables contained in a file. 1311 * @brief Get an iterator to all global variables contained in a file.
1270 * 1312 *
1271 * @param[in] state The state. 1313 * @param[in] state The state.
@@ -1291,6 +1333,19 @@ EAPI Eina_Iterator *eolian_state_globals_by_file_get(const Eolian_State *state,
1291EAPI Eina_Iterator *eolian_state_constants_by_file_get(const Eolian_State *state, const char *file_name); 1333EAPI Eina_Iterator *eolian_state_constants_by_file_get(const Eolian_State *state, const char *file_name);
1292 1334
1293/* 1335/*
1336 * @brief Get an iterator to all error declarations contained in a file.
1337 *
1338 * @param[in] state The state.
1339 * @param[in] file_name The file name.
1340 * @return the iterator or NULL
1341 *
1342 * Thanks to internal caching, this is an O(1) operation.
1343 *
1344 * @ingroup Eolian
1345 */
1346EAPI Eina_Iterator *eolian_state_errors_by_file_get(const Eolian_State *state, const char *file_name);
1347
1348/*
1294 * @brief A helper function to get all globals in a state. 1349 * @brief A helper function to get all globals in a state.
1295 * 1350 *
1296 * @see eolian_unit_globals_get 1351 * @see eolian_unit_globals_get
@@ -1317,6 +1372,19 @@ eolian_state_constants_get(const Eolian_State *state)
1317} 1372}
1318 1373
1319/* 1374/*
1375 * @brief A helper function to get all error declarations in a state.
1376 *
1377 * @see eolian_unit_errors_get
1378 *
1379 * @ingroup Eolian
1380 */
1381static inline Eina_Iterator *
1382eolian_state_errors_get(const Eolian_State *state)
1383{
1384 return eolian_unit_errors_get(EOLIAN_UNIT(state));
1385}
1386
1387/*
1320 * @brief A helper function to get an alias in a state by name. 1388 * @brief A helper function to get an alias in a state by name.
1321 * 1389 *
1322 * @see eolian_unit_alias_by_name_get 1390 * @see eolian_unit_alias_by_name_get
@@ -2704,7 +2772,8 @@ EAPI const Eolian_Type *eolian_type_base_type_get(const Eolian_Type *tp);
2704 * 2772 *
2705 * The inner types of a complex type form a chain. Therefore, you first retrieve 2773 * The inner types of a complex type form a chain. Therefore, you first retrieve
2706 * the first one via eolian_type_base_type_get and then get the next one via 2774 * the first one via eolian_type_base_type_get and then get the next one via
2707 * this API function called on the first inner type if necessary. 2775 * this API function called on the first inner type if necessary. Another use
2776 * for this is with errors, specifying error(Foo, Bar, ...) makes a chain.
2708 * 2777 *
2709 * @param[in] tp the type. 2778 * @param[in] tp the type.
2710 * @return the next type or NULL. 2779 * @return the next type or NULL.
@@ -2753,6 +2822,16 @@ EAPI const Eolian_Type *eolian_type_aliased_base_get(const Eolian_Type *tp);
2753EAPI const Eolian_Class *eolian_type_class_get(const Eolian_Type *tp); 2822EAPI const Eolian_Class *eolian_type_class_get(const Eolian_Type *tp);
2754 2823
2755/* 2824/*
2825 * @brief Get the error declaration associated with an EOLIAN_TYPE_ERROR type.
2826 *
2827 * @param[in] tp the type.
2828 * @return the error or NULL.
2829 *
2830 * @ingroup Eolian
2831 */
2832EAPI const Eolian_Error *eolian_type_error_get(const Eolian_Type *tp);
2833
2834/*
2756 * @brief Get whether the given type is owned. 2835 * @brief Get whether the given type is owned.
2757 * 2836 *
2758 * This is true when a parameter, return or whatever is marked as @owned. 2837 * This is true when a parameter, return or whatever is marked as @owned.
@@ -3131,6 +3210,101 @@ eolian_variable_is_beta(const Eolian_Variable *var)
3131} 3210}
3132 3211
3133/* 3212/*
3213 * @brief Get the message of an error declaration.
3214 *
3215 * @param[in] err the error.
3216 * @return the message or NULL.
3217 *
3218 * @ingroup Eolian
3219 */
3220EAPI const char *eolian_error_message_get(const Eolian_Error *err);
3221
3222/*
3223 * @brief Get the documentation of an error declaration.
3224 *
3225 * @param[in] err the error declaration.
3226 * @return the documentation or NULL.
3227 *
3228 * @ingroup Eolian
3229 */
3230EAPI const Eolian_Documentation *eolian_error_documentation_get(const Eolian_Error *err);
3231
3232/*
3233 * @brief A helper function to get the full name of an error declaration.
3234 *
3235 * @see eolian_object_name_get
3236 *
3237 * @ingroup Eolian
3238 */
3239static inline const char *
3240eolian_error_name_get(const Eolian_Error *err)
3241{
3242 return eolian_object_name_get(EOLIAN_OBJECT(err));
3243}
3244
3245/*
3246 * @brief A helper function to get the C name of an error declaration.
3247 *
3248 * @see eolian_object_c_name_get
3249 *
3250 * @ingroup Eolian
3251 */
3252static inline const char *
3253eolian_error_c_name_get(const Eolian_Error *err)
3254{
3255 return eolian_object_c_name_get(EOLIAN_OBJECT(err));
3256}
3257
3258/*
3259 * @brief A helper function to get the short name of an error declaration.
3260 *
3261 * @see eolian_object_short_name_get
3262 *
3263 * @ingroup Eolian
3264 */
3265static inline const char *
3266eolian_error_short_name_get(const Eolian_Error *err)
3267{
3268 return eolian_object_short_name_get(EOLIAN_OBJECT(err));
3269}
3270
3271/*
3272 * @brief A helper function to get the namespaces of an error declaration.
3273 *
3274 * @see eolian_object_namespaces_get
3275 *
3276 * @ingroup Eolian
3277 */
3278static inline Eina_Iterator *
3279eolian_error_namespaces_get(const Eolian_Error *err)
3280{
3281 return eolian_object_namespaces_get(EOLIAN_OBJECT(err));
3282}
3283
3284/*
3285 * @brief Get whether an error declaration is beta.
3286 *
3287 * @see eolian_object_is_beta
3288 *
3289 * @ingroup Eolian
3290 */
3291static inline Eina_Bool
3292eolian_error_is_beta(const Eolian_Error *err)
3293{
3294 return eolian_object_is_beta(EOLIAN_OBJECT(err));
3295}
3296
3297/*
3298 * @brief Check if an error declaration is extern.
3299 *
3300 * @param[in] err the errpr decůaratopm.
3301 * @return EINA_TRUE if it's extern, EINA_FALSE otherwise.
3302 *
3303 * @ingroup Eolian
3304 */
3305EAPI Eina_Bool eolian_error_is_extern(const Eolian_Error *err);
3306
3307/*
3134 * @brief Get the summary of the documentation. 3308 * @brief Get the summary of the documentation.
3135 * 3309 *
3136 * This should never return NULL unless the input is invalid. 3310 * This should never return NULL unless the input is invalid.
diff --git a/src/lib/eolian/database_type_api.c b/src/lib/eolian/database_type_api.c
index b10a9a700f..d4869e2866 100644
--- a/src/lib/eolian/database_type_api.c
+++ b/src/lib/eolian/database_type_api.c
@@ -197,6 +197,15 @@ eolian_type_class_get(const Eolian_Type *tp)
197 return tp->klass; 197 return tp->klass;
198} 198}
199 199
200EAPI const Eolian_Error *
201eolian_type_error_get(const Eolian_Type *tp)
202{
203 EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL);
204 if (eolian_type_type_get(tp) != EOLIAN_TYPE_ERROR)
205 return NULL;
206 return tp->error;
207}
208
200EAPI Eina_Bool 209EAPI Eina_Bool
201eolian_type_is_owned(const Eolian_Type *tp) 210eolian_type_is_owned(const Eolian_Type *tp)
202{ 211{
diff --git a/src/lib/eolian/database_validate.c b/src/lib/eolian/database_validate.c
index 71c05d7d8f..8deea6d595 100644
--- a/src/lib/eolian/database_validate.c
+++ b/src/lib/eolian/database_validate.c
@@ -351,9 +351,29 @@ _validate_type(Validate_State *vals, Eolian_Type *tp)
351 } 351 }
352 if (!tp->freefunc) 352 if (!tp->freefunc)
353 tp->freefunc = eina_stringshare_add(eo_obj_free); 353 tp->freefunc = eina_stringshare_add(eo_obj_free);
354 tp->base.c_name = eina_stringshare_ref(tp->tdecl->base.c_name); 354 tp->base.c_name = eina_stringshare_ref(tp->klass->base.c_name);
355 return _validate_ownable(tp); 355 return _validate_ownable(tp);
356 } 356 }
357 case EOLIAN_TYPE_ERROR:
358 {
359 tp->error = (Eolian_Error *)eolian_unit_error_by_name_get(src, tp->base.name);
360 if (!tp->error)
361 {
362 _eo_parser_log(&tp->base, "undefined error %s "
363 "(likely wrong namespacing)", tp->base.name);
364 return EINA_FALSE;
365 }
366 else if (vals->stable && tp->error->base.is_beta)
367 {
368 _eo_parser_log(&tp->base, "beta error '%s' used in stable context",
369 tp->error->base.name);
370 return EINA_FALSE;
371 }
372 tp->base.c_name = eina_stringshare_ref(tp->error->base.c_name);
373 if (tp->next_type && !_validate_type(vals, tp->next_type))
374 return EINA_FALSE;
375 return _validate(&tp->base);
376 }
357 default: 377 default:
358 return EINA_FALSE; 378 return EINA_FALSE;
359 } 379 }
diff --git a/src/lib/eolian/eo_lexer.h b/src/lib/eolian/eo_lexer.h
index 5bc7064151..0e7921726f 100644
--- a/src/lib/eolian/eo_lexer.h
+++ b/src/lib/eolian/eo_lexer.h
@@ -28,7 +28,7 @@ enum Tokens
28#define KEYWORDS KW(class), KW(const), KW(enum), KW(return), KW(struct), \ 28#define KEYWORDS KW(class), KW(const), KW(enum), KW(return), KW(struct), \
29 \ 29 \
30 KW(abstract), KW(c_prefix), KW(composite), KW(constructor), KW(constructors), \ 30 KW(abstract), KW(c_prefix), KW(composite), KW(constructor), KW(constructors), \
31 KW(data), KW(destructor), KW(event_prefix), KW(events), KW(extends), \ 31 KW(data), KW(destructor), KW(error), KW(event_prefix), KW(events), KW(extends), \
32 KW(free), KW(get), KW(implements), KW(import), KW(interface), \ 32 KW(free), KW(get), KW(implements), KW(import), KW(interface), \
33 KW(keys), KW(legacy), KW(methods), KW(mixin), KW(params), \ 33 KW(keys), KW(legacy), KW(methods), KW(mixin), KW(params), \
34 KW(parse), KW(parts), KW(ptr), KW(set), KW(type), KW(values), KW(var), KW(requires), \ 34 KW(parse), KW(parts), KW(ptr), KW(set), KW(type), KW(values), KW(var), KW(requires), \
@@ -296,6 +296,18 @@ eo_lexer_expr_release_ref(Eo_Lexer *ls, Eolian_Expression *expr)
296 return eo_lexer_expr_release(ls, expr); 296 return eo_lexer_expr_release(ls, expr);
297} 297}
298 298
299static inline Eolian_Error *
300eo_lexer_error_new(Eo_Lexer *ls)
301{
302 return (Eolian_Error *)eo_lexer_node_new(ls, sizeof(Eolian_Error));
303}
304
305static inline Eolian_Error *
306eo_lexer_error_release(Eo_Lexer *ls, Eolian_Error *err)
307{
308 return (Eolian_Error *)eo_lexer_node_release(ls, (Eolian_Object *)err);
309}
310
299/* "stack" management, only to protect against errors (jumps) in parsing */ 311/* "stack" management, only to protect against errors (jumps) in parsing */
300void eo_lexer_dtor_push(Eo_Lexer *ls, Eina_Free_Cb free_cb, void *data); 312void eo_lexer_dtor_push(Eo_Lexer *ls, Eina_Free_Cb free_cb, void *data);
301void eo_lexer_dtor_pop(Eo_Lexer *ls); 313void eo_lexer_dtor_pop(Eo_Lexer *ls);
diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c
index ee056b7cf5..f33db75f67 100644
--- a/src/lib/eolian/eo_parser.c
+++ b/src/lib/eolian/eo_parser.c
@@ -646,6 +646,29 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool is_extern,
646 return def; 646 return def;
647} 647}
648 648
649/* error(Error1, Error2, Error3, ...) */
650static Eolian_Type *
651parse_type_error(Eo_Lexer *ls)
652{
653 Eolian_Type *def = eo_lexer_type_new(ls);
654 Eina_Strbuf *buf = eina_strbuf_new();
655 eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
656 for (Eolian_Type *cdef = def;; cdef = cdef->next_type)
657 {
658 FILL_BASE(cdef->base, ls, ls->line_number, ls->column, TYPE);
659 parse_name(ls, buf);
660 cdef->type = EOLIAN_TYPE_ERROR;
661 cdef->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
662 eina_strbuf_reset(buf);
663 if (ls->t.token != ',')
664 break;
665 eo_lexer_get(ls);
666 cdef->next_type = eo_lexer_type_release(ls, eo_lexer_type_new(ls));
667 }
668 eo_lexer_dtor_pop(ls);
669 return def;
670}
671
649static Eolian_Type * 672static Eolian_Type *
650parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr) 673parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr)
651{ 674{
@@ -698,6 +721,17 @@ parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr)
698 check_match(ls, ')', '(', pline, pcolumn); 721 check_match(ls, ')', '(', pline, pcolumn);
699 return def; 722 return def;
700 } 723 }
724 case KW_error:
725 {
726 int pline, pcolumn;
727 eo_lexer_get(ls);
728 pline = ls->line_number;
729 pcolumn = ls->column;
730 check_next(ls, '(');
731 def = parse_type_error(ls);
732 check_match(ls, ')', '(', pline, pcolumn);
733 return def;
734 }
701 default: 735 default:
702 break; 736 break;
703 } 737 }
@@ -910,6 +944,71 @@ tags_done:
910 return def; 944 return def;
911} 945}
912 946
947static Eolian_Error *
948parse_error(Eo_Lexer *ls)
949{
950 Eolian_Error *def = eo_lexer_error_new(ls);
951 Eina_Strbuf *buf;
952 eo_lexer_get(ls);
953 Eina_Stringshare *cname = NULL;
954 Eina_Bool has_extern = EINA_FALSE, has_beta = EINA_FALSE, has_c_name = EINA_FALSE;
955 for (;;) switch (ls->t.kw)
956 {
957 case KW_at_extern:
958 CASE_LOCK(ls, extern, "extern qualifier");
959 def->is_extern = EINA_TRUE;
960 eo_lexer_get(ls);
961 break;
962 case KW_at_beta:
963 CASE_LOCK(ls, beta, "beta qualifier");
964 def->base.is_beta = EINA_TRUE;
965 eo_lexer_get(ls);
966 break;
967 case KW_at_c_name:
968 CASE_LOCK(ls, c_name, "@c_name specifier");
969 cname = parse_c_name(ls);
970 eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)cname);
971 break;
972 default:
973 goto tags_done;
974 }
975tags_done:
976 buf = eina_strbuf_new();
977 eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
978 eo_lexer_context_push(ls);
979 FILL_BASE(def->base, ls, ls->line_number, ls->column, ERROR);
980 parse_name(ls, buf);
981 def->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
982 if (cname)
983 {
984 def->base.c_name = cname;
985 eo_lexer_dtor_pop(ls);
986 }
987 else
988 def->base.c_name = make_c_name(def->base.name);
989 Eolian_Object *decl = _eolian_decl_get(ls, def->base.name);
990 if (decl)
991 {
992 eo_lexer_context_restore(ls);
993 redef_error(ls, decl, &def->base);
994 }
995 eo_lexer_context_pop(ls);
996 check(ls, '=');
997 /* we need to parse a string so switch to exprmode */
998 ls->expr_mode = EINA_TRUE;
999 /* consume = to get string */
1000 eo_lexer_get(ls);
1001 /* verify and switch back to plain syntax mode */
1002 check(ls, TOK_STRING);
1003 ls->expr_mode = EINA_FALSE;
1004 def->msg = eina_stringshare_ref(ls->t.value.s);
1005 eo_lexer_get(ls);
1006 check_next(ls, ';');
1007 FILL_DOC(ls, def, doc);
1008 eo_lexer_dtor_pop(ls);
1009 return def;
1010}
1011
913typedef struct _Eo_Ret_Def 1012typedef struct _Eo_Ret_Def
914{ 1013{
915 Eolian_Type *type; 1014 Eolian_Type *type;
@@ -2273,6 +2372,9 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
2273 parse_variable(ls, ls->t.kw == KW_var))); 2372 parse_variable(ls, ls->t.kw == KW_var)));
2274 break; 2373 break;
2275 } 2374 }
2375 case KW_error:
2376 database_error_add(ls->unit, eo_lexer_error_release(ls, parse_error(ls)));
2377 break;
2276 case KW_struct: 2378 case KW_struct:
2277 case KW_enum: 2379 case KW_enum:
2278 { 2380 {
diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c
index 40b0ca156f..caa43407a4 100644
--- a/src/lib/eolian/eolian_database.c
+++ b/src/lib/eolian/eolian_database.c
@@ -568,6 +568,7 @@ database_unit_init(Eolian_State *state, Eolian_Unit *unit, const char *file)
568 unit->classes = eina_hash_stringshared_new(EINA_FREE_CB(database_class_del)); 568 unit->classes = eina_hash_stringshared_new(EINA_FREE_CB(database_class_del));
569 unit->globals = eina_hash_stringshared_new(EINA_FREE_CB(database_var_del)); 569 unit->globals = eina_hash_stringshared_new(EINA_FREE_CB(database_var_del));
570 unit->constants = eina_hash_stringshared_new(EINA_FREE_CB(database_var_del)); 570 unit->constants = eina_hash_stringshared_new(EINA_FREE_CB(database_var_del));
571 unit->errors = eina_hash_stringshared_new(EINA_FREE_CB(database_error_del));
571 unit->aliases = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del)); 572 unit->aliases = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del));
572 unit->structs = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del)); 573 unit->structs = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del));
573 unit->enums = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del)); 574 unit->enums = eina_hash_stringshared_new(EINA_FREE_CB(database_typedecl_del));
@@ -585,6 +586,7 @@ _unit_contents_del(Eolian_Unit *unit)
585 eina_hash_free(unit->classes); 586 eina_hash_free(unit->classes);
586 eina_hash_free(unit->globals); 587 eina_hash_free(unit->globals);
587 eina_hash_free(unit->constants); 588 eina_hash_free(unit->constants);
589 eina_hash_free(unit->errors);
588 eina_hash_free(unit->aliases); 590 eina_hash_free(unit->aliases);
589 eina_hash_free(unit->structs); 591 eina_hash_free(unit->structs);
590 eina_hash_free(unit->enums); 592 eina_hash_free(unit->enums);
@@ -637,6 +639,7 @@ _state_area_init(Eolian_State *state, Eolian_State_Area *a)
637 a->enums_f = eina_hash_stringshared_new(NULL); 639 a->enums_f = eina_hash_stringshared_new(NULL);
638 a->globals_f = eina_hash_stringshared_new(NULL); 640 a->globals_f = eina_hash_stringshared_new(NULL);
639 a->constants_f = eina_hash_stringshared_new(NULL); 641 a->constants_f = eina_hash_stringshared_new(NULL);
642 a->errors_f = eina_hash_stringshared_new(NULL);
640 a->objects_f = eina_hash_stringshared_new(NULL); 643 a->objects_f = eina_hash_stringshared_new(NULL);
641} 644}
642 645
@@ -663,6 +666,7 @@ _state_area_contents_del(Eolian_State_Area *a)
663 _hashlist_free(a->enums_f); 666 _hashlist_free(a->enums_f);
664 _hashlist_free(a->globals_f); 667 _hashlist_free(a->globals_f);
665 _hashlist_free(a->constants_f); 668 _hashlist_free(a->constants_f);
669 _hashlist_free(a->errors_f);
666 _hashlist_free(a->objects_f); 670 _hashlist_free(a->objects_f);
667} 671}
668 672
@@ -1240,6 +1244,17 @@ eolian_state_constants_by_file_get(const Eolian_State *state, const char *file_n
1240} 1244}
1241 1245
1242EAPI Eina_Iterator * 1246EAPI Eina_Iterator *
1247eolian_state_errors_by_file_get(const Eolian_State *state, const char *file_name)
1248{
1249 if (!state) return NULL;
1250 Eina_Stringshare *shr = eina_stringshare_add(file_name);
1251 Eina_List *l = eina_hash_find(state->main.errors_f, shr);
1252 eina_stringshare_del(shr);
1253 if (!l) return NULL;
1254 return eina_list_iterator_new(l);
1255}
1256
1257EAPI Eina_Iterator *
1243eolian_state_aliases_by_file_get(const Eolian_State *state, const char *file_name) 1258eolian_state_aliases_by_file_get(const Eolian_State *state, const char *file_name)
1244{ 1259{
1245 if (!state) return NULL; 1260 if (!state) return NULL;
@@ -1361,6 +1376,16 @@ eolian_unit_constant_by_name_get(const Eolian_Unit *unit, const char *name)
1361 return v; 1376 return v;
1362} 1377}
1363 1378
1379EAPI const Eolian_Error *
1380eolian_unit_error_by_name_get(const Eolian_Unit *unit, const char *name)
1381{
1382 if (!unit) return NULL;
1383 Eina_Stringshare *shr = eina_stringshare_add(name);
1384 Eolian_Error *v = eina_hash_find(unit->errors, shr);
1385 eina_stringshare_del(shr);
1386 return v;
1387}
1388
1364EAPI Eina_Iterator * 1389EAPI Eina_Iterator *
1365eolian_unit_constants_get(const Eolian_Unit *unit) 1390eolian_unit_constants_get(const Eolian_Unit *unit)
1366{ 1391{
@@ -1373,6 +1398,12 @@ eolian_unit_globals_get(const Eolian_Unit *unit)
1373 return (unit ? eina_hash_iterator_data_new(unit->globals) : NULL); 1398 return (unit ? eina_hash_iterator_data_new(unit->globals) : NULL);
1374} 1399}
1375 1400
1401EAPI Eina_Iterator *
1402eolian_unit_errors_get(const Eolian_Unit *unit)
1403{
1404 return (unit ? eina_hash_iterator_data_new(unit->errors) : NULL);
1405}
1406
1376EAPI const Eolian_Typedecl * 1407EAPI const Eolian_Typedecl *
1377eolian_unit_alias_by_name_get(const Eolian_Unit *unit, const char *name) 1408eolian_unit_alias_by_name_get(const Eolian_Unit *unit, const char *name)
1378{ 1409{
@@ -1424,6 +1455,45 @@ eolian_unit_enums_get(const Eolian_Unit *unit)
1424 return (unit ? eina_hash_iterator_data_new(unit->enums) : NULL); 1455 return (unit ? eina_hash_iterator_data_new(unit->enums) : NULL);
1425} 1456}
1426 1457
1458EAPI const char *
1459eolian_error_message_get(const Eolian_Error *err)
1460{
1461 if (!err) return NULL;
1462 return err->msg;
1463}
1464
1465EAPI Eina_Bool
1466eolian_error_is_extern(const Eolian_Error *err)
1467{
1468 if (!err) return EINA_FALSE;
1469 return err->is_extern;
1470}
1471
1472EAPI const Eolian_Documentation *
1473eolian_error_documentation_get(const Eolian_Error *err)
1474{
1475 EINA_SAFETY_ON_NULL_RETURN_VAL(err, NULL);
1476 return err->doc;
1477}
1478
1479void
1480database_error_del(Eolian_Error *err)
1481{
1482 if (!err || eolian_object_unref(&err->base)) return;
1483 eina_stringshare_del(err->msg);
1484 free(err);
1485}
1486
1487void
1488database_error_add(Eolian_Unit *unit, Eolian_Error *err)
1489{
1490 EOLIAN_OBJECT_ADD(unit, err->base.name, err, errors);
1491 eina_hash_set(unit->state->staging.errors_f, err->base.file, eina_list_append
1492 ((Eina_List*)eina_hash_find(unit->state->staging.errors_f, err->base.file),
1493 err));
1494 database_object_add(unit, &err->base);
1495}
1496
1427char * 1497char *
1428database_class_to_filename(const char *cname) 1498database_class_to_filename(const char *cname)
1429{ 1499{
diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h
index 0dce769370..950e4114d4 100644
--- a/src/lib/eolian/eolian_database.h
+++ b/src/lib/eolian/eolian_database.h
@@ -41,6 +41,7 @@ struct _Eolian_Unit
41 Eina_Hash *classes; 41 Eina_Hash *classes;
42 Eina_Hash *globals; 42 Eina_Hash *globals;
43 Eina_Hash *constants; 43 Eina_Hash *constants;
44 Eina_Hash *errors;
44 Eina_Hash *aliases; 45 Eina_Hash *aliases;
45 Eina_Hash *structs; 46 Eina_Hash *structs;
46 Eina_Hash *enums; 47 Eina_Hash *enums;
@@ -60,6 +61,7 @@ typedef struct _Eolian_State_Area
60 Eina_Hash *enums_f; 61 Eina_Hash *enums_f;
61 Eina_Hash *globals_f; 62 Eina_Hash *globals_f;
62 Eina_Hash *constants_f; 63 Eina_Hash *constants_f;
64 Eina_Hash *errors_f;
63 Eina_Hash *objects_f; 65 Eina_Hash *objects_f;
64} Eolian_State_Area; 66} Eolian_State_Area;
65 67
@@ -267,6 +269,7 @@ struct _Eolian_Type
267 { 269 {
268 Eolian_Class *klass; 270 Eolian_Class *klass;
269 Eolian_Typedecl *tdecl; 271 Eolian_Typedecl *tdecl;
272 Eolian_Error *error;
270 }; 273 };
271 Eina_Bool is_const :1; 274 Eina_Bool is_const :1;
272 Eina_Bool is_ptr :1; 275 Eina_Bool is_ptr :1;
@@ -325,6 +328,14 @@ struct _Eolian_Event
325 Eina_Bool is_restart :1; 328 Eina_Bool is_restart :1;
326}; 329};
327 330
331struct _Eolian_Error
332{
333 Eolian_Object base;
334 Eina_Stringshare *msg;
335 Eolian_Documentation *doc;
336 Eina_Bool is_extern :1;
337};
338
328struct _Eolian_Struct_Type_Field 339struct _Eolian_Struct_Type_Field
329{ 340{
330 Eolian_Object base; 341 Eolian_Object base;
@@ -448,4 +459,8 @@ void database_event_del(Eolian_Event *event);
448/* parts */ 459/* parts */
449void database_part_del(Eolian_Part *part); 460void database_part_del(Eolian_Part *part);
450 461
462/* errors */
463void database_error_del(Eolian_Error *err);
464void database_error_add(Eolian_Unit *unit, Eolian_Error *err);
465
451#endif 466#endif