summaryrefslogtreecommitdiffstats
path: root/unwind.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-07-31 17:26:18 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-07-31 17:28:32 -0700
commitf8010dc6f95b967ffc6b653b33300e4b4d850c14 (patch)
tree46a5d790b2fdc14ace7a384f65b5e7f2be2cee75 /unwind.c
parent5c880c971907b6a55aac5649b0d07e9c748e6e5e (diff)
downloadtxr-f8010dc6f95b967ffc6b653b33300e4b4d850c14.tar.gz
txr-f8010dc6f95b967ffc6b653b33300e4b4d850c14.tar.bz2
txr-f8010dc6f95b967ffc6b653b33300e4b4d850c14.zip
txr-011 2009-09-25txr-011
Diffstat (limited to 'unwind.c')
-rw-r--r--unwind.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/unwind.c b/unwind.c
new file mode 100644
index 00000000..c573c16d
--- /dev/null
+++ b/unwind.c
@@ -0,0 +1,88 @@
+/* Copyright 2009
+ * Kaz Kylheku <kkylheku@gmail.com>
+ * Vancouver, Canada
+ * All rights reserved.
+ *
+ * BSD License:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <setjmp.h>
+#include <dirent.h>
+#include "lib.h"
+#include "unwind.h"
+
+static uw_frame_t *uw_stack;
+static uw_frame_t *uw_exit_point;
+
+static void uw_unwind_to_exit_point()
+{
+ while (uw_stack && uw_stack != uw_exit_point)
+ uw_stack = uw_stack->uw.up;
+
+ if (!uw_stack)
+ abort();
+
+ uw_exit_point = 0;
+
+ switch (uw_stack->uw.type) {
+ case UW_BLOCK:
+ longjmp(uw_stack->bl.jb, 1);
+ break;
+ }
+
+ abort();
+}
+
+void uw_push_block(uw_frame_t *fr, obj_t *tag)
+{
+ fr->bl.type = UW_BLOCK;
+ fr->bl.tag = tag;
+ fr->bl.result = nil;
+ fr->bl.up = uw_stack;
+ uw_stack = fr;
+}
+
+void uw_pop_frame(uw_frame_t *fr)
+{
+ assert (fr == uw_stack);
+ uw_stack = uw_stack->uw.up;
+}
+
+obj_t *uw_block_return(obj_t *tag, obj_t *result)
+{
+ uw_frame_t *ex;
+
+ for (ex = uw_stack; ex != 0; ex = ex->uw.up) {
+ if (ex->uw.type == UW_BLOCK && ex->bl.tag == tag)
+ break;
+ }
+
+ if (ex == 0)
+ return nil;
+
+ ex->bl.result = result;
+ uw_exit_point = ex;
+ uw_unwind_to_exit_point();
+ abort();
+}