Support catching CFC exceptions from C Needed to fix CLOWNFISH-14.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/5d0a3efe Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/5d0a3efe Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/5d0a3efe Branch: refs/heads/master Commit: 5d0a3efefc68ae1ea81564a0184d70273db75623 Parents: 65387c4 Author: Nick Wellnhofer <wellnho...@aevum.de> Authored: Fri Mar 4 17:58:28 2016 +0100 Committer: Nick Wellnhofer <wellnho...@aevum.de> Committed: Sat Mar 5 17:51:27 2016 +0100 ---------------------------------------------------------------------- compiler/src/CFCUtil.c | 71 +++++++++++++++++++++++++++++++++++++++++---- compiler/src/CFCUtil.h | 23 +++++++++++++++ 2 files changed, 88 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5d0a3efe/compiler/src/CFCUtil.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCUtil.c b/compiler/src/CFCUtil.c index da546af..a2a0993 100644 --- a/compiler/src/CFCUtil.c +++ b/compiler/src/CFCUtil.c @@ -23,6 +23,7 @@ #include <stdarg.h> #include <errno.h> #include <sys/stat.h> +#include <setjmp.h> // For mkdir. #ifdef CHY_HAS_DIRECT_H @@ -36,6 +37,9 @@ #include "CFCUtil.h" +static char *thrown_error; +static jmp_buf *current_env; + void CFCUtil_null_check(const void *arg, const char *name, const char *file, int line) { @@ -594,6 +598,21 @@ CFCUtil_closedir(void *dirhandle, const char *dir) { /***************************************************************************/ +jmp_buf* +CFCUtil_try_start(jmp_buf *env) { + jmp_buf *prev_env = current_env; + current_env = env; + return prev_env; +} + +char* +CFCUtil_try_end(jmp_buf *prev_env) { + current_env = prev_env; + char *error = thrown_error; + thrown_error = NULL; + return error; +} + #ifdef CFCPERL #include "EXTERN.h" @@ -605,8 +624,27 @@ void CFCUtil_die(const char* format, ...) { va_list args; va_start(args, format); - vcroak(format, &args); - va_end(args); + + if (current_env) { + thrown_error = CFCUtil_vsprintf(format, args); + va_end(args); + longjmp(*current_env, 1); + } + else { + vcroak(format, &args); + va_end(args); + } +} + +void +CFCUtil_rethrow(char *error) { + if (current_env) { + thrown_error = error; + longjmp(*current_env, 1); + } + else { + croak("%s", error); + } } void @@ -623,10 +661,31 @@ void CFCUtil_die(const char* format, ...) { va_list args; va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - fprintf(stderr, "\n"); - exit(1); + + if (current_env) { + thrown_error = CFCUtil_vsprintf(format, args); + va_end(args); + longjmp(*current_env, 1); + } + else { + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + abort(); + } +} + +void +CFCUtil_rethrow(char *error) { + if (current_env) { + thrown_error = error; + longjmp(*current_env, 1); + } + else { + fprintf(stderr, "%s\n", error); + FREEMEM(error); + abort(); + } } void http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5d0a3efe/compiler/src/CFCUtil.h ---------------------------------------------------------------------- diff --git a/compiler/src/CFCUtil.h b/compiler/src/CFCUtil.h index 3e06b03..73286ef 100644 --- a/compiler/src/CFCUtil.h +++ b/compiler/src/CFCUtil.h @@ -29,6 +29,18 @@ extern "C" { #include <stdarg.h> #include <stddef.h> +#include <setjmp.h> + +#define CFCUTIL_TRY \ + do { \ + jmp_buf env; \ + jmp_buf *prev_env = CFCUtil_try_start(&env); \ + if (!setjmp(env)) + +#define CFCUTIL_CATCH(error) \ + error = CFCUtil_try_end(prev_env); \ + } while (0) + /** Create an inner Perl object with a refcount of 1. For use in actual * Perl-space, it is necessary to wrap this inner object in an RV. @@ -223,11 +235,22 @@ CFCUtil_free_string_array(char **strings); void CFCUtil_die(const char *format, ...); +/* Rethrow an error. + */ +void +CFCUtil_rethrow(char *error); + /* Print an error message to stderr. */ void CFCUtil_warn(const char *format, ...); +jmp_buf* +CFCUtil_try_start(jmp_buf *env); + +char* +CFCUtil_try_end(jmp_buf *prev_env); + #ifdef __cplusplus } #endif