summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--glob.c36
-rw-r--r--unwind.h3
2 files changed, 38 insertions, 1 deletions
diff --git a/glob.c b/glob.c
index dcab2ed8..76673a59 100644
--- a/glob.c
+++ b/glob.c
@@ -27,19 +27,40 @@
#include <stdarg.h>
#include <wchar.h>
#include <signal.h>
+#include <stdlib.h>
#include <glob.h>
#include "config.h"
#include "lib.h"
#include "gc.h"
#include "utf8.h"
#include "eval.h"
+#include "signal.h"
+#include "unwind.h"
#include "glob.h"
static val s_errfunc;
+static uw_frame_t *s_exit_point;
static int errfunc_thunk(const char *errpath, int errcode)
{
- val result = funcall2(s_errfunc, string_utf8(errpath), num(errcode));
+ val result = t;
+ uw_frame_t cont_guard;
+
+ uw_push_guard(&cont_guard);
+
+ uw_simple_catch_begin;
+
+ result = funcall2(s_errfunc, string_utf8(errpath), num(errcode));
+
+ uw_unwind {
+ s_exit_point = uw_curr_exit_point;
+ uw_curr_exit_point = 0; /* stops unwinding */
+ }
+
+ uw_catch_end;
+
+ uw_pop_frame(&cont_guard);
+
return result ? 1 : 0;
}
@@ -48,11 +69,24 @@ val glob_wrap(val pattern, val flags, val errfunc)
char *pat_u8 = utf8_dup_to(c_str(pattern));
glob_t gl;
+ if (s_errfunc)
+ uw_throwf(error_s, lit("glob: glob cannot be re-entered from "
+ "its error callback function"), nao);
+
s_errfunc = default_bool_arg(errfunc);
(void) glob(pat_u8, c_num(default_arg(flags, zero)),
s_errfunc ? errfunc_thunk : 0, &gl);
+ s_errfunc = nil;
+
+ if (s_exit_point) {
+ uw_frame_t *ep = s_exit_point;
+ s_exit_point = 0;
+ globfree(&gl);
+ uw_continue(ep);
+ }
+
{
size_t i;
list_collect_decl (out, ptail);
diff --git a/unwind.h b/unwind.h
index 3a88574b..fb353b15 100644
--- a/unwind.h
+++ b/unwind.h
@@ -212,6 +212,9 @@ noreturn val type_mismatch(val, ...);
/* prevent looping */ \
uw_catch.ca.visible = 0;
+#define uw_curr_exit_point \
+ (uw_catch.ca.cont)
+
#define uw_catch_end \
break; \
default: \