diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h index 54300cf483..3e07f761dd 100644 --- a/src/lib/eolian/Eolian.h +++ b/src/lib/eolian/Eolian.h @@ -201,6 +201,7 @@ typedef struct _Eolian_Unit Eolian_Unit; #define EOLIAN_UNIT(expr) EOLIAN_CAST(Eolian_Unit, expr) typedef void (*Eolian_Panic_Cb)(const Eolian_State *state, Eina_Stringshare *msg); +typedef void (*Eolian_Error_Cb)(const Eolian_Object *obj, const char *msg, void *data); typedef enum { @@ -492,7 +493,7 @@ EAPI int eolian_shutdown(void); * This will assign a default panic function, which printers the error * message passed to it into the standard Eolian log. * - * @see eolian_panic_cb_set + * @see eolian_state_panic_cb_set * * @return A new state (or NULL on failure). * @@ -500,6 +501,18 @@ EAPI int eolian_shutdown(void); */ EAPI Eolian_State *eolian_state_new(void); +/* + * @brief Free an Eolian state. + * + * You can use this to free an Eolian state. + * + * If the input is NULL, this function has no effect. + * + * @param[in] state the state to free + * + */ +EAPI void eolian_state_free(Eolian_State *state); + /* * @brief Set the panic function for the state. * @@ -520,20 +533,45 @@ EAPI Eolian_State *eolian_state_new(void); * * If you set a panic function and jump, you're responsible for the error * message and have to delete it with eina_stringshare_del. + * + * If you want to catch error messages that are standard (such as parse + * errors), there is another, separate mechanism in place. + * + * @return The old panic callback. + * + * @see eolian_state_error_cb_set */ -EAPI Eolian_Panic_Cb eolian_panic_cb_set(Eolian_State *state, Eolian_Panic_Cb cb); +EAPI Eolian_Panic_Cb eolian_state_panic_cb_set(Eolian_State *state, Eolian_Panic_Cb cb); /* - * @brief Free an Eolian state. + * @brief Set the error function for the state. * - * You can use this to free an Eolian state. + * When a regular error (such as parse error) happens, you can use this + * callback to catch the error. There is no jump involved and the outer + * function will fail normally and safely. You are provided with the + * object the error happened on (for line/column/file/other information) + * as well as the error message. Additionally, a data pointer is passed + * in so you can pass some of the information into local memory somewhere. * - * If the input is NULL, this function has no effect. - * - * @param[in] state the state to free + * @return The old error callback. * + * @see eolian_state_panic_cb_set + * @see eolian_state_error_data_set */ -EAPI void eolian_state_free(Eolian_State *state); +EAPI Eolian_Error_Cb eolian_state_error_cb_set(Eolian_State *state, Eolian_Error_Cb cb); + +/* + * @brief Set a data pointer to be passed to the error function. + * + * By default, the data is `NULL`. You can use this to set a data pointer + * to be passed. This is useful to e.g. expose some local memory so you can + * write back from the callback without using globals. + * + * @return The old data pointer. + * + * @see eolian_state_error_cb_set + */ +EAPI void *eolian_state_error_data_set(Eolian_State *state, void *data); /* * @brief Get the type of an Eolian object. diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c index 70fe7a8d4d..6db89eaa5b 100644 --- a/src/lib/eolian/eolian_database.c +++ b/src/lib/eolian/eolian_database.c @@ -570,6 +570,12 @@ _default_panic_cb(const Eolian_State *state EINA_UNUSED, const char *msg) _eolian_log(msg); } +static void +_default_error_cb(const Eolian_Object *obj, const char *msg, void *data EINA_UNUSED) +{ + _eolian_log_line(obj->file, obj->line, obj->column, msg); +} + EAPI Eolian_State * eolian_state_new(void) { @@ -586,6 +592,8 @@ eolian_state_new(void) exit(EXIT_FAILURE); } + state->error = _default_error_cb; + database_unit_init(state, &state->unit, NULL); state->filenames_eo = eina_hash_string_small_new(free); @@ -630,6 +638,30 @@ eolian_state_free(Eolian_State *state) free(state); } +EAPI Eolian_Panic_Cb +eolian_state_panic_cb_set(Eolian_State *state, Eolian_Panic_Cb cb) +{ + Eolian_Panic_Cb old_cb = state->panic; + state->panic = cb; + return old_cb; +} + +EAPI Eolian_Error_Cb +eolian_state_error_cb_set(Eolian_State *state, Eolian_Error_Cb cb) +{ + Eolian_Error_Cb old_cb = state->error; + state->error = cb; + return old_cb; +} + +EAPI void * +eolian_state_error_data_set(Eolian_State *state, void *data) +{ + void *old_data = state->error_data; + state->error_data = data; + return old_data; +} + #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 813f3f5e1c..eff2b966a5 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -55,6 +55,9 @@ struct _Eolian_State Eina_Stringshare *panic_msg; jmp_buf jmp_env; + Eolian_Error_Cb error; + void *error_data; + Eina_Hash *filenames_eo; /* filename to full path mapping */ Eina_Hash *filenames_eot;