Index: benchmark/Makefile.am
===================================================================
--- benchmark/Makefile.am	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/Makefile.am	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -11,6 +11,6 @@
 ## Created On       : Sun May 31 09:08:15 2015
 ## Last Modified By : Peter A. Buhr
-## Last Modified On : Mon Jan 20 11:50:13 2020
-## Update Count     : 244
+## Last Modified On : Sat Jan 25 09:20:44 2020
+## Update Count     : 255
 ###############################################################################
 
@@ -75,9 +75,9 @@
 .ONESHELL:		# use one shell to execute recipe
 .NOTPARALLEL:
-.PHONY: compile.csv basic.csv ctxswitch.csv mutex.csv signal.csv
-
-## =========================================================================================================
-
-all : basic$(EXEEXT) ctxswitch$(EXEEXT) mutex$(EXEEXT) signal$(EXEEXT) waitfor$(EXEEXT) creation$(EXEEXT)
+.PHONY: compile.csv basic.csv ctxswitch.csv mutex.csv schedint.csv
+
+## =========================================================================================================
+
+all : basic$(EXEEXT) ctxswitch$(EXEEXT) mutex$(EXEEXT) schedint$(EXEEXT) schedext$(EXEEXT) creation$(EXEEXT)
 
 basic_loop_DURATION = 15000000000
@@ -89,18 +89,20 @@
 ctxswitch_rust_thread_DURATION = $(ctxswitch_pthread_DURATION)
 ctxswitch_cfa_generator_DURATION = 5000000000
+ctxswitch_nodejs_await_DURATION = 5000000
 ctxswitch_DURATION = 100000000
 
-mutex_java_DURATION = 10000000
+#mutex_java_DURATION = 10000000
 mutex_DURATION = 50000000
 
-signal_pthread_DURATION = 1000000
-signal_java_DURATION = $(signal_pthread_DURATION)
-signal_rust_DURATION = $(signal_pthread_DURATION)
-signal_DURATION = 10000000
-
-waitfor_DURATION = 10000000
+schedint_pthread_DURATION = 1000000
+schedint_java_DURATION = $(schedint_pthread_DURATION)
+schedint_rust_DURATION = $(schedint_pthread_DURATION)
+schedint_DURATION = 10000000
+
+schedext_DURATION = 10000000
 
 creation_pthread_DURATION = 250000
-creation_rust_DURATION = ${creation_pthread_DURATION}
+creation_rust_thread_DURATION = ${creation_pthread_DURATION}
+creation_java_thread_DURATION = ${creation_pthread_DURATION}
 creation_cfa_coroutine_DURATION = 100000000
 creation_cfa_coroutine_eager_DURATION = 10000000
@@ -151,6 +153,6 @@
 	+make mutex.csv
 	-+make mutex.diff.csv
-	+make signal.csv
-	-+make signal.diff.csv
+	+make schedint.csv
+	-+make schedint.diff.csv
 @DOifskipcompile@
 	cat compile.csv
@@ -163,6 +165,6 @@
 	cat mutex.csv
 	-cat mutex.diff.csv
-	cat signal.csv
-	-cat signal.diff.csv
+	cat schedint.csv
+	-cat schedint.diff.csv
 
 compile.csv:
@@ -198,10 +200,10 @@
 	$(srcdir)/fixcsv.sh $@
 
-signal.csv:
-	echo "signal-1,signal-2,waitfor-1,waitfor-2" > $@
-	+make signal-cfa1.runquiet >> $@ && echo -n ',' >> $@
-	+make signal-cfa2.runquiet >> $@ && echo -n ',' >> $@
-	+make waitfor-cfa1.runquiet >> $@ && echo -n ',' >> $@
-	+make waitfor-cfa2.runquiet >> $@
+schedint.csv:
+	echo "schedint-1,schedint-2,schedext-1,schedext-2" > $@
+	+make schedint-cfa1.runquiet >> $@ && echo -n ',' >> $@
+	+make schedint-cfa2.runquiet >> $@ && echo -n ',' >> $@
+	+make schedext-cfa1.runquiet >> $@ && echo -n ',' >> $@
+	+make schedext-cfa2.runquiet >> $@
 	$(srcdir)/fixcsv.sh $@
 
@@ -247,4 +249,5 @@
 	ctxswitch-python_coroutine.run	\
 	ctxswitch-nodejs_coroutine.run	\
+	ctxswitch-nodejs_await.run	\
 	ctxswitch-goroutine_thread.run	\
 	ctxswitch-rust_thread.run	\
@@ -293,4 +296,9 @@
 	echo "#!/bin/sh" > a.out
 	echo "nodejs $(srcdir)/ctxswitch/node_cor.js" >> a.out
+	chmod a+x a.out
+
+ctxswitch-nodejs_await$(EXEEXT):
+	echo "#!/bin/sh" > a.out
+	echo "nodejs $(srcdir)/ctxswitch/node_await.js" >> a.out
 	chmod a+x a.out
 
@@ -351,60 +359,66 @@
 ## =========================================================================================================
 
-signal$(EXEEXT) :		\
-	signal-cfa1.run		\
-	signal-cfa2.run		\
-	signal-cfa4.run		\
-	signal-upp.run		\
-	signal-rust.run		\
-	signal-java.run		\
-	signal-pthread.run
-
-signal-pthread$(EXEEXT):
+schedint$(EXEEXT) :		\
+	schedint-cfa1.run	\
+	schedint-cfa2.run	\
+	schedint-cfa4.run	\
+	schedint-upp.run	\
+	schedint-rust.run	\
+	schedint-java.run	\
+	schedint-pthread.run
+
+schedint-cfa1$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa1.cfa
+
+schedint-cfa2$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa2.cfa
+
+schedint-cfa4$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa4.cfa
+
+schedint-upp$(EXEEXT):
+	$(BENCH_V_UPP)$(UPPCOMPILE) $(srcdir)/schedint/upp.cc
+
+schedint-rust$(EXEEXT):
+	$(BENCH_V_RUSTC)rustc -C opt-level=3 -o a.out $(srcdir)/schedint/rust.rs
+
+schedint-java$(EXEEXT):
+	$(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/schedint/JavaThread.java
+	echo "#!/bin/sh" > a.out
+	echo "java JavaThread" >> a.out
+	chmod a+x a.out
+
+schedint-pthread$(EXEEXT):
 	$(BENCH_V_CC)$(COMPILE) $(srcdir)/schedint/pthreads.c
 
-signal-upp$(EXEEXT):
-	$(BENCH_V_UPP)$(UPPCOMPILE) $(srcdir)/schedint/upp.cc
-
-signal-cfa1$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa1.cfa
-
-signal-cfa2$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa2.cfa
-
-signal-cfa4$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa4.cfa
-
-signal-rust$(EXEEXT):
-	$(BENCH_V_RUSTC)rustc -C opt-level=3 -o a.out $(srcdir)/schedint/rust.rs
-
-signal-java$(EXEEXT):
-	$(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/schedint/JavaThread.java
-	echo "#!/bin/sh" > a.out
-	echo "java JavaThread" >> a.out
-	chmod a+x a.out
-
-## =========================================================================================================
-
-waitfor$(EXEEXT) :		\
-	waitfor-cfa1.run	\
-	waitfor-cfa2.run	\
-	waitfor-cfa4.run	\
-	waitfor-upp.run
-
-waitfor-upp$(EXEEXT):
+## =========================================================================================================
+
+schedext$(EXEEXT) :		\
+	schedext-cfa1.run	\
+	schedext-cfa2.run	\
+	schedext-cfa4.run	\
+	schedext-upp.run	\
+	schedext-goroutine.run
+
+schedext-cfa1$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa1.cfa
+
+schedext-cfa2$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa2.cfa
+
+schedext-cfa4$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa4.cfa
+
+schedext-upp$(EXEEXT):
 	$(BENCH_V_UPP)$(UPPCOMPILE) $(srcdir)/schedext/upp.cc
 
-waitfor-cfa1$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa1.cfa
-
-waitfor-cfa2$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa2.cfa
-
-waitfor-cfa4$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa4.cfa
+schedext-goroutine$(EXEEXT):
+	$(BENCH_V_GOC)go build -o a.out $(srcdir)/schedext/goroutine.go
+
 
 ## =========================================================================================================
 
 creation$(EXEEXT) :				\
+	creation-cfa_generator.run		\
 	creation-cfa_coroutine.run		\
 	creation-cfa_coroutine_eager.run	\
@@ -419,4 +433,7 @@
 	creation-pthread.run
 
+creation-cfa_generator$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/creation/cfa_gen.cfa
+
 creation-cfa_coroutine$(EXEEXT):
 	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/creation/cfa_cor.cfa
@@ -450,5 +467,5 @@
 	$(BENCH_V_RUSTC)rustc -C opt-level=3 -o a.out $(srcdir)/creation/rust_thrd.rs
 
-creation-java$(EXEEXT):
+creation-java_thread$(EXEEXT):
 	$(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/creation/JavaThread.java
 	echo "#!/bin/sh" > a.out
Index: benchmark/Makefile.in
===================================================================
--- benchmark/Makefile.in	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/Makefile.in	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -426,14 +426,17 @@
 ctxswitch_rust_thread_DURATION = $(ctxswitch_pthread_DURATION)
 ctxswitch_cfa_generator_DURATION = 5000000000
+ctxswitch_nodejs_await_DURATION = 5000000
 ctxswitch_DURATION = 100000000
-mutex_java_DURATION = 10000000
+
+#mutex_java_DURATION = 10000000
 mutex_DURATION = 50000000
-signal_pthread_DURATION = 1000000
-signal_java_DURATION = $(signal_pthread_DURATION)
-signal_rust_DURATION = $(signal_pthread_DURATION)
-signal_DURATION = 10000000
-waitfor_DURATION = 10000000
+schedint_pthread_DURATION = 1000000
+schedint_java_DURATION = $(schedint_pthread_DURATION)
+schedint_rust_DURATION = $(schedint_pthread_DURATION)
+schedint_DURATION = 10000000
+schedext_DURATION = 10000000
 creation_pthread_DURATION = 250000
-creation_rust_DURATION = ${creation_pthread_DURATION}
+creation_rust_thread_DURATION = ${creation_pthread_DURATION}
+creation_java_thread_DURATION = ${creation_pthread_DURATION}
 creation_cfa_coroutine_DURATION = 100000000
 creation_cfa_coroutine_eager_DURATION = 10000000
@@ -454,8 +457,8 @@
 	ctxswitch-cfa_thread2.run ctxswitch-upp_coroutine.run \
 	ctxswitch-upp_thread.run ctxswitch-python_coroutine.run \
-	ctxswitch-nodejs_coroutine.run ctxswitch-goroutine_thread.run \
-	ctxswitch-rust_thread.run ctxswitch-nodejs_coroutine.run \
-	ctxswitch-java_thread.run ctxswitch-pthread.run \
-	$(am__append_1)
+	ctxswitch-nodejs_coroutine.run ctxswitch-nodejs_await.run \
+	ctxswitch-goroutine_thread.run ctxswitch-rust_thread.run \
+	ctxswitch-nodejs_coroutine.run ctxswitch-java_thread.run \
+	ctxswitch-pthread.run $(am__append_1)
 testdir = $(top_srcdir)/tests
 all: all-am
@@ -784,7 +787,7 @@
 .ONESHELL:		# use one shell to execute recipe
 .NOTPARALLEL:
-.PHONY: compile.csv basic.csv ctxswitch.csv mutex.csv signal.csv
-
-all : basic$(EXEEXT) ctxswitch$(EXEEXT) mutex$(EXEEXT) signal$(EXEEXT) waitfor$(EXEEXT) creation$(EXEEXT)
+.PHONY: compile.csv basic.csv ctxswitch.csv mutex.csv schedint.csv
+
+all : basic$(EXEEXT) ctxswitch$(EXEEXT) mutex$(EXEEXT) schedint$(EXEEXT) schedext$(EXEEXT) creation$(EXEEXT)
 
 %.run : %$(EXEEXT) ${REPEAT}
@@ -825,6 +828,6 @@
 	+make mutex.csv
 	-+make mutex.diff.csv
-	+make signal.csv
-	-+make signal.diff.csv
+	+make schedint.csv
+	-+make schedint.diff.csv
 @DOifskipcompile@
 	cat compile.csv
@@ -837,6 +840,6 @@
 	cat mutex.csv
 	-cat mutex.diff.csv
-	cat signal.csv
-	-cat signal.diff.csv
+	cat schedint.csv
+	-cat schedint.diff.csv
 
 compile.csv:
@@ -872,10 +875,10 @@
 	$(srcdir)/fixcsv.sh $@
 
-signal.csv:
-	echo "signal-1,signal-2,waitfor-1,waitfor-2" > $@
-	+make signal-cfa1.runquiet >> $@ && echo -n ',' >> $@
-	+make signal-cfa2.runquiet >> $@ && echo -n ',' >> $@
-	+make waitfor-cfa1.runquiet >> $@ && echo -n ',' >> $@
-	+make waitfor-cfa2.runquiet >> $@
+schedint.csv:
+	echo "schedint-1,schedint-2,schedext-1,schedext-2" > $@
+	+make schedint-cfa1.runquiet >> $@ && echo -n ',' >> $@
+	+make schedint-cfa2.runquiet >> $@ && echo -n ',' >> $@
+	+make schedext-cfa1.runquiet >> $@ && echo -n ',' >> $@
+	+make schedext-cfa2.runquiet >> $@
 	$(srcdir)/fixcsv.sh $@
 
@@ -935,4 +938,9 @@
 	echo "#!/bin/sh" > a.out
 	echo "nodejs $(srcdir)/ctxswitch/node_cor.js" >> a.out
+	chmod a+x a.out
+
+ctxswitch-nodejs_await$(EXEEXT):
+	echo "#!/bin/sh" > a.out
+	echo "nodejs $(srcdir)/ctxswitch/node_await.js" >> a.out
 	chmod a+x a.out
 
@@ -989,32 +997,29 @@
 	chmod a+x a.out
 
-signal$(EXEEXT) :		\
-	signal-cfa1.run		\
-	signal-cfa2.run		\
-	signal-cfa4.run		\
-	signal-upp.run		\
-	signal-rust.run		\
-	signal-java.run		\
-	signal-pthread.run
-
-signal-pthread$(EXEEXT):
-	$(BENCH_V_CC)$(COMPILE) $(srcdir)/schedint/pthreads.c
-
-signal-upp$(EXEEXT):
+schedint$(EXEEXT) :		\
+	schedint-cfa1.run	\
+	schedint-cfa2.run	\
+	schedint-cfa4.run	\
+	schedint-upp.run	\
+	schedint-rust.run	\
+	schedint-java.run	\
+	schedint-pthread.run
+
+schedint-cfa1$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa1.cfa
+
+schedint-cfa2$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa2.cfa
+
+schedint-cfa4$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa4.cfa
+
+schedint-upp$(EXEEXT):
 	$(BENCH_V_UPP)$(UPPCOMPILE) $(srcdir)/schedint/upp.cc
 
-signal-cfa1$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa1.cfa
-
-signal-cfa2$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa2.cfa
-
-signal-cfa4$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedint/cfa4.cfa
-
-signal-rust$(EXEEXT):
+schedint-rust$(EXEEXT):
 	$(BENCH_V_RUSTC)rustc -C opt-level=3 -o a.out $(srcdir)/schedint/rust.rs
 
-signal-java$(EXEEXT):
+schedint-java$(EXEEXT):
 	$(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/schedint/JavaThread.java
 	echo "#!/bin/sh" > a.out
@@ -1022,23 +1027,31 @@
 	chmod a+x a.out
 
-waitfor$(EXEEXT) :		\
-	waitfor-cfa1.run	\
-	waitfor-cfa2.run	\
-	waitfor-cfa4.run	\
-	waitfor-upp.run
-
-waitfor-upp$(EXEEXT):
+schedint-pthread$(EXEEXT):
+	$(BENCH_V_CC)$(COMPILE) $(srcdir)/schedint/pthreads.c
+
+schedext$(EXEEXT) :		\
+	schedext-cfa1.run	\
+	schedext-cfa2.run	\
+	schedext-cfa4.run	\
+	schedext-upp.run	\
+	schedext-goroutine.run
+
+schedext-cfa1$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa1.cfa
+
+schedext-cfa2$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa2.cfa
+
+schedext-cfa4$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa4.cfa
+
+schedext-upp$(EXEEXT):
 	$(BENCH_V_UPP)$(UPPCOMPILE) $(srcdir)/schedext/upp.cc
 
-waitfor-cfa1$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa1.cfa
-
-waitfor-cfa2$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa2.cfa
-
-waitfor-cfa4$(EXEEXT):
-	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/schedext/cfa4.cfa
+schedext-goroutine$(EXEEXT):
+	$(BENCH_V_GOC)go build -o a.out $(srcdir)/schedext/goroutine.go
 
 creation$(EXEEXT) :				\
+	creation-cfa_generator.run		\
 	creation-cfa_coroutine.run		\
 	creation-cfa_coroutine_eager.run	\
@@ -1053,4 +1066,7 @@
 	creation-pthread.run
 
+creation-cfa_generator$(EXEEXT):
+	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/creation/cfa_gen.cfa
+
 creation-cfa_coroutine$(EXEEXT):
 	$(BENCH_V_CFA)$(CFACOMPILE) $(srcdir)/creation/cfa_cor.cfa
@@ -1084,5 +1100,5 @@
 	$(BENCH_V_RUSTC)rustc -C opt-level=3 -o a.out $(srcdir)/creation/rust_thrd.rs
 
-creation-java$(EXEEXT):
+creation-java_thread$(EXEEXT):
 	$(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/creation/JavaThread.java
 	echo "#!/bin/sh" > a.out
Index: benchmark/creation/cfa_gen.cfa
===================================================================
--- benchmark/creation/cfa_gen.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ benchmark/creation/cfa_gen.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,22 @@
+#include "bench.h"
+
+struct C {
+	volatile int restart; // ensure compiler does not optimize away all the code
+};
+void ?{}( C & c ) { c.restart = 0; }
+void main( C & ) {}
+
+int main( int argc, char * argv[] ) {
+	BENCH_START()
+	BENCH(
+		for ( times ) {
+			 C c;
+		},
+		result
+	)
+	printf( "%g\n", result );
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// End: //
Index: benchmark/ctxswitch/node_await.js
===================================================================
--- benchmark/ctxswitch/node_await.js	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ benchmark/ctxswitch/node_await.js	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,26 @@
+var times = 5000000
+var argc = process.argv.length // node, path
+if ( argc > 3 ) process.exit( 1 )
+if ( argc == 3 ) times = Number( process.argv[2] )
+
+function instant() {
+     return new Promise(function(rs) {
+         setImmediate(rs);
+     });
+}
+
+async function l() {
+    var hrstart = process.hrtime()
+    for ( var i = 0; i < times; i += 1 )
+         await instant();
+	hrend = process.hrtime( hrstart )
+	var dur = (1000000000 * hrend[0] + hrend[1]) / times
+	console.log( dur )
+}
+
+l();
+
+// Local Variables: //
+// tab-width: 4 //
+// compile-command: "nodejs node_await.js" //
+// End: //
Index: benchmark/exclude
===================================================================
--- benchmark/exclude	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ benchmark/exclude	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,12 @@
+.deps
+baselines
+mutexC
+Makefile*
+kos_fibre*
+fixcsv.sh
+cxx.cpp
+c.c
+fetch_add.c
+interrupt_linux.c
+exclude
+Monitor.c
Index: benchmark/schedext/cfa1.cfa
===================================================================
--- benchmark/schedext/cfa1.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedext/cfa1.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -6,23 +6,17 @@
 #include "../bench.h"
 
-volatile int go = 0;
-
 monitor M {} m1;
 
 void __attribute__((noinline)) call( M & mutex p1 ) {}
-
 void __attribute__((noinline)) wait( M & mutex p1 ) {
-	go = 1;
 	for ( times ) {
 		waitfor( call : p1 );
 	}
-	go = 0;
 }
 
 thread T {};
 void main( T & ) {
-	while ( go == 0 ) { yield(); }
 	BENCH(
-		while ( go == 1 ) { call( m1 ); },
+		for ( times ) { call( m1 ); },
 		result
 	)
Index: benchmark/schedext/cfa2.cfa
===================================================================
--- benchmark/schedext/cfa2.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedext/cfa2.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -4,25 +4,20 @@
 #include <stdio.h>
 
-#include "bench.h"
-
-volatile int go = 0;
+#include "../bench.h"
 
 monitor M {} m1, m2;
 
 void __attribute__((noinline)) call( M & mutex p1, M & mutex p2 ) {}
-
 void __attribute__((noinline)) wait( M & mutex p1, M & mutex p2 ) {
-	go = 1;
 	for ( times ) {
 		waitfor( call : p1, p2 );
 	}
-	go = 0;
 }
-
 thread T {};
 void main( T & ) {
-	while( go == 0 ) { yield(); }
 	BENCH(
-		while ( go == 1 ) { call( m1, m2 ); },
+		for ( times ) {
+			call( m1, m2 );
+		},
 		result
 	)
Index: benchmark/schedext/cfa4.cfa
===================================================================
--- benchmark/schedext/cfa4.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedext/cfa4.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -4,25 +4,20 @@
 #include <stdio.h>
 
-#include "bench.h"
-
-volatile int go = 0;
+#include "../bench.h"
 
 monitor M {} m1, m2, m3, m4;
 
 void __attribute__((noinline)) call( M & mutex p1, M & mutex p2, M & mutex p3, M & mutex p4 ) {}
-
 void __attribute__((noinline)) wait( M & mutex p1, M & mutex p2, M & mutex p3, M & mutex p4 ) {
-	go = 1;
 	for ( times ) {
 		waitfor( call : p1, p2, p3, p4 );
 	}
-	go = 0;
 }
-
 thread T {};
 void main( T & ) {
-	while( go == 0 ) { yield(); }
 	BENCH(
-		while( go == 1 ) { call( m1, m2, m3, m4 ); },
+		for ( times ) {
+			call( m1, m2, m3, m4 );
+		},
 		result
 	)
Index: benchmark/schedext/goroutine.go
===================================================================
--- benchmark/schedext/goroutine.go	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ benchmark/schedext/goroutine.go	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,42 @@
+package main
+
+import (
+	"fmt"
+	"time"
+	"os"
+	"strconv"
+)
+
+func main() {
+	shake := make( chan bool )
+	ch := make( chan int )
+
+	acceptor := func(times int) {
+		var v int
+		v += 1 // need usage
+		for i := 0; i < times; i += 1 {
+			select {
+				case v = <- ch :
+			}
+		}
+		shake <- true   // indicate completion
+	}
+
+	var times int = 10000000
+	if len( os.Args ) > 2 { os.Exit( 1 ) }
+	if len( os.Args ) == 2 { times, _ = strconv.Atoi(os.Args[1]) }
+
+	go acceptor( times )
+	start := time.Now()
+	for i := 0; i < times; i += 1 {
+		ch <- 1
+	}
+	end := time.Now()
+	fmt.Printf("%d\n", end.Sub(start) / time.Duration(times))
+	<- shake
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// compile-command: "go run goroutine.go" //
+// End: //
Index: benchmark/schedext/upp.cc
===================================================================
--- benchmark/schedext/upp.cc	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedext/upp.cc	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -3,17 +3,11 @@
 #include "bench.h"
 
-volatile int go = 0;
-
 _Monitor M {
 public:
 	void __attribute__((noinline)) call() {}
-
-	int __attribute__((noinline)) wait() {
-		go = 1;
+	void __attribute__((noinline)) wait() {
 		for ( size_t i = 0; i < times; i++ ) {
 			_Accept(call);
 		}
-		go = 0;
-		return 0;
 	}
 } m;
@@ -21,7 +15,8 @@
 _Task T {
 	void main() {
-		while ( go == 0 ) { yield(); }
 		BENCH(
-			while ( go == 1 ) { m.call(); },
+			for ( size_t i = 0; i < times; i++ ) {
+				m.call();
+			},
 			result
 		)
@@ -33,5 +28,5 @@
 	BENCH_START()
 	T t;
-	return m.wait();
+	m.wait();
 }
 
Index: benchmark/schedint/JavaThread.java
===================================================================
--- benchmark/schedint/JavaThread.java	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedint/JavaThread.java	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -63,5 +63,5 @@
 		synchronized(m) {
 			s.start();
-			while( !Monitor.go ) {
+			while( ! Monitor.go ) { // waiter must start first
 				Thread.yield();
 			}
Index: benchmark/schedint/cfa1.cfa
===================================================================
--- benchmark/schedint/cfa1.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedint/cfa1.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -7,4 +7,5 @@
 
 volatile int go = 0;
+
 condition c;
 monitor M {} m1;
@@ -13,5 +14,4 @@
 	signal( c );
 }
-
 void __attribute__((noinline)) wait( M & mutex p1 ) {
 	go = 1;
@@ -19,12 +19,11 @@
 		wait( c );
 	}
-	go = 0;
 }
 
 thread T {};
 void main( T & ) {
-	while ( go == 0 ) { yield(); }
+	while ( go == 0 ) { yield(); } // waiter must start first
 	BENCH(
-		while ( go == 1 ) { call( m1 ); },
+		for ( times ) { call( m1 ); },
 		result
 	)
Index: benchmark/schedint/cfa2.cfa
===================================================================
--- benchmark/schedint/cfa2.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedint/cfa2.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -7,4 +7,5 @@
 
 volatile int go = 0;
+
 condition c;
 monitor M {} m1, m2;
@@ -13,5 +14,4 @@
 	signal( c );
 }
-
 void __attribute__((noinline)) wait( M & mutex p1, M & mutex p2 ) {
 	go = 1;
@@ -19,12 +19,11 @@
 		wait( c );
 	}
-	go = 0;
 }
 
 thread T {};
 void main( T & ) {
-	while ( go == 0 ) { yield(); }
+	while ( go == 0 ) { yield(); } // waiter must start first
 	BENCH(
-		while ( go == 1 ) { call( m1, m2 ); },
+		for ( times ) { call( m1, m2 ); },
 		result
 	)
Index: benchmark/schedint/cfa4.cfa
===================================================================
--- benchmark/schedint/cfa4.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedint/cfa4.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -4,7 +4,8 @@
 #include <stdio.h>
 
-#include "bench.h"
+#include "../bench.h"
 
 volatile int go = 0;
+
 condition c;
 monitor M {} m1, m2, m3, m4;
@@ -13,5 +14,4 @@
 	signal( c );
 }
-
 void __attribute__((noinline)) wait( M & mutex p1, M & mutex p2, M & mutex p3, M & mutex p4 ) {
 	go = 1;
@@ -19,12 +19,11 @@
 		wait( c );
 	}
-	go = 0;
 }
 
 thread T {};
 void main( T & ) {
-	while ( go == 0 ) { yield(); }
+	while ( go == 0 ) { yield(); } // waiter must start first
 	BENCH(
-		while ( go == 1 ) { call( m1, m2, m3, m4 ); },
+		for ( times ) { call( m1, m2, m3, m4 ); },
 		result
 	)
Index: benchmark/schedint/pthreads.c
===================================================================
--- benchmark/schedint/pthreads.c	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedint/pthreads.c	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -6,31 +6,31 @@
 volatile int go = 0;
 
+pthread_mutex_t m;
 pthread_cond_t c;
-pthread_mutex_t m;
 
 void __attribute__((noinline)) call() {
-	pthread_mutex_lock(&m);
-	pthread_cond_signal(&c);
-	pthread_mutex_unlock(&m);
+	pthread_mutex_lock( &m );
+	pthread_cond_signal( &c );
+	pthread_mutex_unlock( &m );
 }
 
-int  __attribute__((noinline)) wait() {
+void __attribute__((noinline)) wait() {
 	pthread_mutex_lock(&m);
 	go = 1;
+	for ( size_t i = 0; i < times; i++ ) {
+		pthread_cond_wait( &c, &m );
+	}
+	go = 0;
+	pthread_mutex_unlock( &m );
+}
+
+void * thread_main( __attribute__((unused)) void * arg ) {
+	while ( go == 0 ) { sched_yield(); } // waiter must start first
+	// barging for lock acquire => may not execute N times
 	BENCH(
-		for (size_t i = 0; i < times; i++) {
-			pthread_cond_wait(&c, &m);
-		},
+		while ( go == 1 ) { call(); },
 		result
 	)
 	printf( "%g\n", result );
-	go = 0;
-	pthread_mutex_unlock(&m);
-	return 0;
-}
-
-void* thread_main(__attribute__((unused)) void * arg ) {
-	while(go == 0) { sched_yield(); }
-	while(go == 1) { call(); }
 	return NULL;
 }
@@ -39,10 +39,10 @@
 	BENCH_START()
 	pthread_t thread;
-	if (pthread_create(&thread, NULL, thread_main, NULL) < 0) {
+	if ( pthread_create( &thread, NULL, thread_main, NULL ) < 0 ) {
 		perror( "failure" );
 		return 1;
 	}
 	wait();
-	if (pthread_join( thread, NULL) < 0) {
+	if ( pthread_join( thread, NULL ) < 0 ) {
 		perror( "failure" );
 		return 1;
Index: benchmark/schedint/rust.rs
===================================================================
--- benchmark/schedint/rust.rs	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedint/rust.rs	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -18,5 +18,5 @@
 
 	let th = thread::spawn( move || {
-		while *m2.lock().unwrap() == 0 {
+		while *m2.lock().unwrap() == 0 { // waiter must start first
 			thread::yield_now();
 		}
Index: benchmark/schedint/upp.cc
===================================================================
--- benchmark/schedint/upp.cc	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ benchmark/schedint/upp.cc	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -11,26 +11,22 @@
 		cond.signal();
 	}
+	void __attribute__((noinline)) wait() {
+		go = 1;
+		for ( size_t i = 0; i < times; i++ ) {
+			cond.wait();
+		}
+	}
+} m;
 
-	int __attribute__((noinline)) wait() {
-		go = 1;
+_Task T {
+	void main() {
+		while ( go == 0 ) { yield(); } // waiter must start first
 		BENCH(
-			for (size_t i = 0; i < times; i++) {
-				cond.wait();
+			for ( size_t i = 0; i < times; i++ ) {
+				m.call();
 			},
 			result
 		)
 		printf( "%g\n", result );
-		go = 0;
-		return 0;
-	}
-};
-
-M m;
-
-_Task T {
-	void main() {
-		while(go == 0) { yield(); }
-		while(go == 1) { m.call(); }
-
 	}
 };
@@ -39,5 +35,5 @@
 	BENCH_START()
 	T t;
-	return m.wait();
+	m.wait();
 }
 
Index: driver/cfa.cc
===================================================================
--- driver/cfa.cc	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ driver/cfa.cc	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
 // Created On       : Tue Aug 20 13:44:49 2002
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Sep 10 17:00:15 2019
-// Update Count     : 420
+// Last Modified On : Fri Jan 31 16:48:03 2020
+// Update Count     : 421
 //
 
@@ -187,4 +187,5 @@
 			} else if ( arg == "-XCFA" ) {				// CFA pass through
 				i += 1;
+				if ( i == argc ) continue;				// next argument available ?
 				Putenv( argv, argv[i] );
 
Index: libcfa/src/bits/defs.hfa
===================================================================
--- libcfa/src/bits/defs.hfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/bits/defs.hfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
 // Created On       : Thu Nov  9 13:24:10 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb  8 16:22:41 2018
-// Update Count     : 8
+// Last Modified On : Tue Jan 28 22:38:27 2020
+// Update Count     : 9
 //
 
@@ -34,5 +34,6 @@
 
 #ifdef __cforall
-void abort ( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
+void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
+void abort( bool signalAbort, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
 extern "C" {
 #endif
Index: libcfa/src/bits/signal.hfa
===================================================================
--- libcfa/src/bits/signal.hfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/bits/signal.hfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -40,7 +40,14 @@
 	sigaddset( &act.sa_mask, SIGALRM );		// disabled during signal handler
 	sigaddset( &act.sa_mask, SIGUSR1 );
+	sigaddset( &act.sa_mask, SIGSEGV );
+	sigaddset( &act.sa_mask, SIGBUS );
+	sigaddset( &act.sa_mask, SIGILL );
+	sigaddset( &act.sa_mask, SIGFPE );
+	sigaddset( &act.sa_mask, SIGHUP );		// revert to default on second delivery
+	sigaddset( &act.sa_mask, SIGTERM );
+	sigaddset( &act.sa_mask, SIGINT );
 	act.sa_flags = flags;
 
-	if ( sigaction( sig, &act, NULL ) == -1 ) {
+	if ( sigaction( sig, &act, 0p ) == -1 ) {
 		__cfaabi_dbg_print_buffer_decl(
 			" __cfaabi_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
@@ -48,21 +55,4 @@
 		);
 		_exit( EXIT_FAILURE );
-	}
+	} // if
 }
-
-// Sigaction wrapper : restore default handler
-static void __cfaabi_sigdefault( int sig ) {
-	struct sigaction act;
-
-	act.sa_handler = SIG_DFL;
-	act.sa_flags = 0;
-	sigemptyset( &act.sa_mask );
-
-	if ( sigaction( sig, &act, NULL ) == -1 ) {
-		__cfaabi_dbg_print_buffer_decl(
-			" __cfaabi_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n",
-			sig, errno, strerror( errno )
-		);
-		_exit( EXIT_FAILURE );
-	}
-}
Index: libcfa/src/concurrency/kernel.cfa
===================================================================
--- libcfa/src/concurrency/kernel.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/concurrency/kernel.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
 // Created On       : Tue Jan 17 12:27:26 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Dec  5 16:25:52 2019
-// Update Count     : 52
+// Last Modified On : Thu Jan 30 22:55:50 2020
+// Update Count     : 56
 //
 
@@ -844,6 +844,7 @@
 		sigemptyset( &mask );
 		sigaddset( &mask, SIGALRM );		// block SIGALRM signals
-		sigsuspend( &mask );			// block the processor to prevent further damage during abort
-		_exit( EXIT_FAILURE );			// if processor unblocks before it is killed, terminate it
+		sigaddset( &mask, SIGUSR1 );		// block SIGALRM signals
+		sigsuspend( &mask );				// block the processor to prevent further damage during abort
+		_exit( EXIT_FAILURE );				// if processor unblocks before it is killed, terminate it
 	}
 	else {
Index: libcfa/src/interpose.cfa
===================================================================
--- libcfa/src/interpose.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/interpose.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
 // Created On       : Wed Mar 29 16:10:31 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 13:45:21 2019
-// Update Count     : 121
+// Last Modified On : Thu Jan 30 17:47:32 2020
+// Update Count     : 156
 //
 
@@ -95,5 +95,5 @@
 	void __cfaabi_interpose_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_CORE ) ));
 	void __cfaabi_interpose_startup( void ) {
-		const char *version = NULL;
+		const char *version = 0p;
 
 		preload_libgcc();
@@ -105,12 +105,30 @@
 #pragma GCC diagnostic pop
 
+		// As a precaution (and necessity), errors that result in termination are delivered on a separate stack because
+		// task stacks might be very small (4K) and the signal delivery corrupts memory to the point that a clean
+		// shutdown is impossible. Also, when a stack overflow encounters the non-accessible sentinel page (debug only)
+		// and generates a segment fault, the signal cannot be delivered on the sentinel page. Finally, calls to abort
+		// print a stack trace that uses substantial stack space.
+
+		#define MINSTKSZ SIGSTKSZ * 8
+		static char stack[MINSTKSZ] __attribute__(( aligned (16) ));
+		static stack_t ss;
+
+		ss.ss_sp = stack;
+		ss.ss_size = MINSTKSZ;
+		ss.ss_flags = 0;
+		if ( sigaltstack( &ss, 0p ) == -1 ) {
+			abort( "__cfaabi_interpose_startup : internal error, sigaltstack error(%d) %s.", errno, strerror( errno ) );
+		} // if
+
 		// Failure handler
-		__cfaabi_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO );
-		__cfaabi_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO );
-		__cfaabi_sigaction( SIGILL , sigHandler_ill  , SA_SIGINFO );
-		__cfaabi_sigaction( SIGFPE , sigHandler_fpe  , SA_SIGINFO );
-		__cfaabi_sigaction( SIGABRT, sigHandler_abrt, SA_SIGINFO | SA_RESETHAND);
-		__cfaabi_sigaction( SIGTERM, sigHandler_term , SA_SIGINFO );
-		__cfaabi_sigaction( SIGINT , sigHandler_term , SA_SIGINFO );
+		__cfaabi_sigaction( SIGSEGV, sigHandler_segv, SA_SIGINFO | SA_ONSTACK );
+		__cfaabi_sigaction( SIGBUS , sigHandler_segv, SA_SIGINFO | SA_ONSTACK );
+		__cfaabi_sigaction( SIGILL , sigHandler_ill , SA_SIGINFO | SA_ONSTACK );
+		__cfaabi_sigaction( SIGFPE , sigHandler_fpe , SA_SIGINFO | SA_ONSTACK );
+		__cfaabi_sigaction( SIGTERM, sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND ); // one shot handler, return to default
+		__cfaabi_sigaction( SIGINT , sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND );
+		__cfaabi_sigaction( SIGABRT, sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND );
+		__cfaabi_sigaction( SIGHUP , sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND ); // terminal hangup
 	}
 }
@@ -123,8 +141,9 @@
 void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
 void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
+void abort( bool signalAbort, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
 
 extern "C" {
 	void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
-		abort( NULL );
+		abort( false, NULL ); // FIX ME: 0p does not work
 	}
 
@@ -132,5 +151,5 @@
 		va_list argp;
 		va_start( argp, fmt );
-		abort( fmt, argp );
+		abort( false, fmt, argp );
 		va_end( argp );
 	}
@@ -141,50 +160,17 @@
 }
 
-void * kernel_abort    ( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return NULL; }
-void   kernel_abort_msg( void * data, char * buffer, int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {}
+void * kernel_abort( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 0p; }
+void kernel_abort_msg( void * data, char * buffer, int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {}
+// See concurrency/kernel.cfa for strong definition used in multi-processor mode.
 int kernel_abort_lastframe( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 4; }
 
 enum { abort_text_size = 1024 };
 static char abort_text[ abort_text_size ];
-static int abort_lastframe;
-
-void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )) {
-    va_list args;
-    va_start( args, fmt );
-    vfprintf( stderr, fmt, args );
-    va_end( args );
-	__cabi_libc.exit( status );
-}
-
-void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
-	void * kernel_data = kernel_abort();			// must be done here to lock down kernel
-	int len;
-
-	abort_lastframe = kernel_abort_lastframe();
-	len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus getPid)
-	__cfaabi_dbg_write( abort_text, len );
-
-	if ( fmt ) {
-		va_list args;
-		va_start( args, fmt );
-
-		len = vsnprintf( abort_text, abort_text_size, fmt, args );
-		va_end( args );
-		__cfaabi_dbg_write( abort_text, len );
-
-		if ( fmt[strlen( fmt ) - 1] != '\n' ) {		// add optional newline if missing at the end of the format text
-			__cfaabi_dbg_write( "\n", 1 );
-		}
-	}
-
-	kernel_abort_msg( kernel_data, abort_text, abort_text_size );
-	__cabi_libc.abort();
-}
-
-static void __cfaabi_backtrace() {
+
+static void __cfaabi_backtrace( int start ) {
 	enum {
 		Frames = 50,									// maximum number of stack frames
-		Start = 8,										// skip first N stack frames
 	};
+	int last = kernel_abort_lastframe();				// skip last N stack frames
 
 	void * array[Frames];
@@ -192,14 +178,12 @@
 	char ** messages = backtrace_symbols( array, size );
 
-	// find executable name
-	*index( messages[0], '(' ) = '\0';
+	*index( messages[0], '(' ) = '\0';					// find executable name
 	__cfaabi_bits_print_nolock( STDERR_FILENO, "Stack back trace for: %s\n", messages[0]);
 
-	for ( int i = Start; i < size - abort_lastframe && messages != 0p; i += 1 ) {
+	for ( unsigned int i = start; i < size - last && messages != 0p; i += 1 ) {
 		char * name = 0p, * offset_begin = 0p, * offset_end = 0p;
 
-		for ( char * p = messages[i]; *p; ++p ) {
+		for ( char * p = messages[i]; *p; ++p ) {		// find parantheses and +offset
 			//__cfaabi_bits_print_nolock( "X %s\n", p);
-			// find parantheses and +offset
 			if ( *p == '(' ) {
 				name = p;
@@ -212,9 +196,8 @@
 		}
 
-		// if line contains symbol print it
-		int frameNo = i - Start;
+		// if line contains symbol, print it
+		int frameNo = i - start;
 		if ( name && offset_begin && offset_end && name < offset_begin ) {
-			// delimit strings
-			*name++ = '\0';
+			*name++ = '\0';								// delimit strings
 			*offset_begin++ = '\0';
 			*offset_end++ = '\0';
@@ -228,9 +211,52 @@
 }
 
+void exit( int status, const char fmt[], ... ) {
+	va_list args;
+	va_start( args, fmt );
+	vfprintf( stderr, fmt, args );
+	va_end( args );
+	__cabi_libc.exit( status );
+}
+
+void abort( bool signalAbort, const char fmt[], ... ) {
+	void * kernel_data = kernel_abort();				// must be done here to lock down kernel
+	int len;
+
+	signal( SIGABRT, SIG_DFL );							// prevent final "real" abort from recursing to handler
+
+	len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus getPid)
+	__cfaabi_bits_write( STDERR_FILENO, abort_text, len );
+
+	if ( fmt ) {
+		va_list args;
+		va_start( args, fmt );
+
+		len = vsnprintf( abort_text, abort_text_size, fmt, args );
+		va_end( args );
+		__cfaabi_bits_write( STDERR_FILENO, abort_text, len );
+
+		if ( fmt[strlen( fmt ) - 1] != '\n' ) {			// add optional newline if missing at the end of the format text
+			__cfaabi_dbg_write( "\n", 1 );
+		}
+	}
+
+	kernel_abort_msg( kernel_data, abort_text, abort_text_size );
+	__cfaabi_backtrace( signalAbort ? 4 : 3 );
+
+	__cabi_libc.abort();								// print stack trace in handler
+}
+
+void abort( const char fmt[], ... ) {
+	va_list args;
+	va_start( args, fmt );
+	abort( false, fmt, args );
+	va_end( args );
+}
+
 void sigHandler_segv( __CFA_SIGPARMS__ ) {
-		if ( sfp->si_addr == NULL ) {
-			abort( "Null pointer (0p) dereference.\n" );
+		if ( sfp->si_addr == 0p ) {
+			abort( true, "Null pointer (0p) dereference.\n" );
 		} else {
-			abort( "%s at memory location %p.\n"
+			abort( true, "%s at memory location %p.\n"
 				   "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript.\n",
 				   (sig == SIGSEGV ? "Segment fault" : "Bus error"), sfp->si_addr );
@@ -239,5 +265,5 @@
 
 void sigHandler_ill( __CFA_SIGPARMS__ ) {
-	abort( "Executing illegal instruction at location %p.\n"
+	abort( true, "Executing illegal instruction at location %p.\n"
 			"Possible cause is stack corruption.\n",
 			sfp->si_addr );
@@ -255,18 +281,9 @@
 	  default: msg = "unknown";
 	} // choose
-	abort( "Computation error %s at location %p.\n", msg, sfp->si_addr );
-}
-
-void sigHandler_abrt( __CFA_SIGPARMS__ ) {
-	__cfaabi_backtrace();
-
-	// reset default signal handler
-	__cfaabi_sigdefault( SIGABRT );
-
-	raise( SIGABRT );
+	abort( true, "Computation error %s at location %p.\n", msg, sfp->si_addr );
 }
 
 void sigHandler_term( __CFA_SIGPARMS__ ) {
-	abort( "Application stopped by %s signal.", sig == SIGINT ? "an interrupt (SIGINT)" : "a terminate (SIGTERM)" );
+	abort( true, "Application interrupted by signal: %s.\n", strsignal( sig ) );
 }
 
Index: libcfa/src/stdhdr/bfdlink.h
===================================================================
--- libcfa/src/stdhdr/bfdlink.h	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/stdhdr/bfdlink.h	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,11 +10,11 @@
 // Created On       : Tue Jul 18 07:26:04 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Jul 22 13:49:30 2018
-// Update Count     : 4
+// Last Modified On : Sat Feb  1 07:15:29 2020
+// Update Count     : 5
 // 
 
 // include file uses the CFA keyword "with".
 #if ! defined( with )									// nesting ?
-#define with `with`										// make keyword an identifier
+#define with ``with``									// make keyword an identifier
 #define __CFA_BFDLINK_H__
 #endif
Index: libcfa/src/stdhdr/hwloc.h
===================================================================
--- libcfa/src/stdhdr/hwloc.h	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/stdhdr/hwloc.h	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,11 +10,11 @@
 // Created On       : Tue Jul 18 07:45:00 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Jul 22 13:49:58 2018
-// Update Count     : 4
+// Last Modified On : Sat Feb  1 07:15:39 2020
+// Update Count     : 5
 // 
 
 // include file uses the CFA keyword "thread".
 #if ! defined( thread )									// nesting ?
-#define thread `thread`									// make keyword an identifier
+#define thread ``thread``								// make keyword an identifier
 #define __CFA_HWLOC_H__
 #endif
Index: libcfa/src/stdhdr/krb5.h
===================================================================
--- libcfa/src/stdhdr/krb5.h	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/stdhdr/krb5.h	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,11 +10,11 @@
 // Created On       : Tue Jul 18 07:55:44 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Jul 22 13:50:24 2018
-// Update Count     : 4
+// Last Modified On : Sat Feb  1 07:15:47 2020
+// Update Count     : 5
 // 
 
 // include file uses the CFA keyword "enable".
 #if ! defined( enable )									// nesting ?
-#define enable `enable`									// make keyword an identifier
+#define enable ``enable``								// make keyword an identifier
 #define __CFA_KRB5_H__
 #endif
Index: libcfa/src/stdhdr/math.h
===================================================================
--- libcfa/src/stdhdr/math.h	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/stdhdr/math.h	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,11 +10,11 @@
 // Created On       : Mon Jul  4 23:25:26 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb 22 18:16:07 2018
-// Update Count     : 13
+// Last Modified On : Sat Feb  1 07:15:58 2020
+// Update Count     : 14
 // 
 
 extern "C" {
 #if ! defined( exception )								// nesting ?
-#define exception `exception`							// make keyword an identifier
+#define exception ``exception``							// make keyword an identifier
 #define __CFA_MATH_H__
 #endif
Index: libcfa/src/stdhdr/sys/ucontext.h
===================================================================
--- libcfa/src/stdhdr/sys/ucontext.h	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ libcfa/src/stdhdr/sys/ucontext.h	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,10 +10,10 @@
 // Created On       : Thu Feb  8 23:48:16 2018
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb  8 23:50:44 2018
-// Update Count     : 4
+// Last Modified On : Sat Feb  1 07:16:05 2020
+// Update Count     : 5
 // 
 
 #if ! defined( ftype )									// nesting ?
-#define ftype `ftype`									// make keyword an identifier
+#define ftype ``ftype``									// make keyword an identifier
 #define __CFA_UCONTEXT_H__
 #endif
Index: src/ControlStruct/LabelFixer.cc
===================================================================
--- src/ControlStruct/LabelFixer.cc	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ src/ControlStruct/LabelFixer.cc	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -45,5 +45,6 @@
 	void LabelFixer::postvisit( FunctionDecl * functionDecl ) {
 		PassVisitor<MultiLevelExitMutator> mlem( resolveJumps(), generator );
-		functionDecl->acceptMutator( mlem );
+		// We start in the body so we can stop when we hit another FunctionDecl.
+		maybeMutate( functionDecl->statements, mlem );
 	}
 
Index: src/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ src/ControlStruct/MLEMutator.cc	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Jan 21 10:33:00 2020
-// Update Count     : 222
+// Last Modified On : Wed Jan 22 11:50:00 2020
+// Update Count     : 223
 //
 
@@ -60,4 +60,8 @@
 		}
 	} // namespace
+
+	void MultiLevelExitMutator::premutate( FunctionDecl * ) {
+		visit_children = false;
+	}
 
 	// break labels have to come after the statement they break out of, so mutate a statement, then if they inform us
@@ -352,4 +356,12 @@
 		});
 		enclosingControlStructures = std::list<Entry>();
+		GuardValue( inFinally );
+		inFinally = true;
+	}
+
+	void MultiLevelExitMutator::premutate( ReturnStmt *returnStmt ) {
+		if ( inFinally ) {
+			SemanticError( returnStmt->location, "'return' may not appear in a finally clause" );
+		}
 	}
 
Index: src/ControlStruct/MLEMutator.h
===================================================================
--- src/ControlStruct/MLEMutator.h	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ src/ControlStruct/MLEMutator.h	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Jan 21 10:33:00 2020
-// Update Count     : 47
+// Last Modified On : Wed Jan 22 11:50:00 2020
+// Update Count     : 48
 //
 
@@ -38,4 +38,6 @@
 		~MultiLevelExitMutator();
 
+		void premutate( FunctionDecl * );
+
 		void premutate( CompoundStmt *cmpndStmt );
 		Statement * postmutate( BranchStmt *branchStmt ) throw ( SemanticErrorException );
@@ -49,4 +51,5 @@
 		void premutate( SwitchStmt *switchStmt );
 		Statement * postmutate( SwitchStmt *switchStmt );
+		void premutate( ReturnStmt *returnStmt );
 		void premutate( TryStmt *tryStmt );
 		Statement * postmutate( TryStmt *tryStmt );
@@ -113,4 +116,5 @@
 		Label breakLabel;
 		LabelGenerator *generator;
+		bool inFinally = false;
 
 		template< typename LoopClass >
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ src/Parser/lex.ll	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
  * Created On       : Sat Sep 22 08:58:10 2001
  * Last Modified By : Peter A. Buhr
- * Last Modified On : Sun Aug  4 20:53:47 2019
- * Update Count     : 719
+ * Last Modified On : Sat Feb  1 07:16:44 2020
+ * Update Count     : 724
  */
 
@@ -330,6 +330,6 @@
 				/* identifier */
 {identifier}	{ IDENTIFIER_RETURN(); }
-"`"{identifier}"`" {									// CFA
-	yytext[yyleng - 1] = '\0'; yytext += 1;				// SKULLDUGGERY: remove backquotes (ok to shorten?)
+"``"{identifier}"``" {									// CFA
+	yytext[yyleng - 2] = '\0'; yytext += 2;				// SKULLDUGGERY: remove backquotes (ok to shorten?)
 	IDENTIFIER_RETURN();
 }
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ src/Parser/parser.yy	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jan 17 14:54:55 2020
-// Update Count     : 4426
+// Last Modified On : Sat Feb  1 10:04:40 2020
+// Update Count     : 4440
 //
 
@@ -579,14 +579,4 @@
 	| '(' compound_statement ')'						// GCC, lambda expression
 		{ $$ = new ExpressionNode( new StmtExpr( dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >($2) ) ) ); }
-	| constant '`' IDENTIFIER							// CFA, postfix call
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $3 ) ), $1 ) ); }
-	| string_literal '`' IDENTIFIER						// CFA, postfix call
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $3 ) ), new ExpressionNode( $1 ) ) ); }
-	| IDENTIFIER '`' IDENTIFIER							// CFA, postfix call
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $3 ) ), new ExpressionNode( build_varref( $1 ) ) ) ); }
-	| tuple '`' IDENTIFIER								// CFA, postfix call
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $3 ) ), $1 ) ); }
-	| '(' comma_expression ')' '`' IDENTIFIER			// CFA, postfix call
-		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $5 ) ), $2 ) ); }
 	| type_name '.' identifier							// CFA, nested type
 		{ SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
@@ -642,4 +632,10 @@
 	| postfix_expression '(' argument_expression_list ')'
 		{ $$ = new ExpressionNode( build_func( $1, $3 ) ); }
+	| postfix_expression '`' identifier					// CFA, postfix call
+		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $3 ) ), $1 ) ); }
+	| constant '`' identifier							// CFA, postfix call
+		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $3 ) ), $1 ) ); }
+	| string_literal '`' identifier						// CFA, postfix call
+		{ $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $3 ) ), new ExpressionNode( $1 ) ) ); }
 	| postfix_expression '.' identifier
 		{ $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
@@ -666,5 +662,5 @@
 	| '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal
 		{ $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
-	| '^' primary_expression '{' argument_expression_list '}' // CFA
+	| '^' primary_expression '{' argument_expression_list '}' // CFA, destructor call
 		{
 			Token fn;
Index: sts/.expect/except-finally-error.txt
===================================================================
--- tests/.expect/except-finally-error.txt	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ 	(revision )
@@ -1,12 +1,0 @@
-except-finally-error.cfa:7:1 error: 'break' outside a loop, 'switch', or labelled block
-except-finally-error.cfa:15:1 error: 'break' outside a loop, 'switch', or labelled block
-except-finally-error.cfa:23:1 error: 'break' outside a loop, 'switch', or labelled block
-except-finally-error.cfa:31:1 error: 'continue' target must be an enclosing loop: 
-except-finally-error.cfa:48:1 error: 'break' target must be an enclosing control structure: mainLoop
-except-finally-error.cfa:56:1 error: 'continue' target must be an enclosing loop: mainLoop
-except-finally-error.cfa:65:1 error: 'break' outside a loop, 'switch', or labelled block
-except-finally-error.cfa:76:1 error: 'break' outside a loop, 'switch', or labelled block
-except-finally-error.cfa:87:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
-except-finally-error.cfa:98:1 error: 'break' target must be an enclosing control structure: mainBlock
-except-finally-error.cfa:111:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
-except-finally-error.cfa:124:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
Index: sts/except-0.cfa
===================================================================
--- tests/except-0.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ 	(revision )
@@ -1,247 +1,0 @@
-// Draft of tests for exception handling.
-// Outdated: The integer constant exceptions need to be replaced with virtual
-// exceptions for the new system.
-
-// ERROR: exceptions do not interact with ^?{} properly.
-
-#include <stdio.h>
-#include <stdbool.h>
-
-#include "except-mac.hfa"
-TRIVIAL_EXCEPTION(yin)
-TRIVIAL_EXCEPTION(yang)
-TRIVIAL_EXCEPTION(zen)
-
-
-// Local type to mark exits from scopes. (see ERROR)
-struct signal_exit {
-	const char * area;
-};
-
-void ?{}(signal_exit * this, const char * area) {
-	this->area = area;
-}
-
-void ^?{}(signal_exit * this) {
-	printf("Exiting: %s\n", this->area);
-//	sout | "Exiting:" | this->area;
-}
-
-
-// Mark throws: make sure to only pass in exception types.
-forall(dtype T)
-void terminate(T * except_value) {
-	signal_exit a = {"terminate function"};
-	THROW(except_value);
-	printf("terminate returned\n");
-}
-
-forall(dtype T)
-void resume(T * except_value) {
-	signal_exit a = {"resume function"};
-	THROW_RESUME(except_value);
-	printf("resume returned\n");
-}
-
-// Termination Test: Two handlers: no catch, catch
-void bar() {
-	signal_exit a = {"bar function"};
-	try {
-		terminate(&(zen){});
-	} catch (yin * error) {
-		printf("bar caught exception yin.\n");
-	}
-}
-
-void foo() {
-	signal_exit a = {"foo function"};
-	try {
-		bar();
-	} catch (yang * error) {
-		printf("foo caught exception yang.\n");
-	} catch (zen * error) {
-		printf("foo caught exception zen.\n");
-	}
-}
-
-// Resumption Two Handler Test: no catch, catch.
-void beta() {
-	signal_exit a = {"beta function"};
-	try {
-		zen x;
-		resume(&x);
-	} catchResume (yin * error) {
-		printf("beta caught exception yin\n");
-	}
-}
-
-void alpha() {
-	signal_exit a = {"alpha function"};
-	try {
-		beta();
-	} catchResume (yang * error) {
-		printf("alpha caught exception yang\n");
-	} catchResume (zen * error) {
-		printf("alpha caught exception zen\n");
-	}
-}
-
-// Finally Test:
-void farewell(bool jump) {
-	try {
-		if (jump) {
-			printf("jump out of farewell\n");
-			goto endoffunction;
-		} else {
-			printf("walk out of farewell\n");
-		}
-	} finally {
-		printf("See you next time\n");
-	}
-	endoffunction:
-	printf("leaving farewell\n");
-}
-
-// Resume-to-Terminate Test:
-void fallback() {
-	try {
-		zen x;
-		resume(&x);
-	} catch (zen * error) {
-		printf("fallback caught termination zen\n");
-	}
-}
-
-// Terminate Throw New Exception:
-void terminate_swap() {
-	signal_exit a = {"terminate_swap"};
-	try {
-		yin x;
-		terminate(&x);
-	} catch (yin * error) {
-		yang y;
-		terminate(&y);
-	}
-}
-
-void terminate_swapped() {
-	signal_exit a = {"terminate_swapped"};
-	try {
-		terminate_swap();
-	} catch (yang * error) {
-		printf("terminate_swapped caught exception yang\n");
-	}
-}
-
-// Resume Throw New Exception:
-void resume_swap() {
-	signal_exit a = {"resume_swap"};
-	try {
-		yin x;
-		resume(&x);
-	} catchResume (yin * error) {
-		yang y;
-		resume(&y);
-	}
-}
-
-void resume_swapped() {
-	try {
-		resume_swap();
-	} catchResume (yang * error) {
-		printf("resume_swapped caught exception yang\n");
-	}
-}
-
-// Terminate Rethrow:
-void reterminate() {
-	try {
-		try {
-			zen x;
-			terminate(&x);
-		} catch (zen * error) {
-			printf("reterminate zen caught and "
-			       "will rethrow exception zen\n");
-			throw;
-		}
-	} catch (zen * error) {
-		printf("reterminate 1 caught exception zen\n");
-	}
-}
-
-// Resume Rethrow:
-void reresume() {
-	try {
-		try {
-			zen x;
-			resume(&x);
-		} catchResume (zen * error) {
-			printf("reresume zen caught and rethrows exception zen\n");
-			throwResume;
-		}
-	} catchResume (zen * error) {
-		printf("reresume 1 caught exception zen\n");
-	}
-}
-
-// Terminate-Resume interaction:
-void fum() {
-	// terminate block, call resume
-	try {
-		zen x;
-		resume(&x);
-	} catch (zen * error) {
-		printf("fum caught exception zen\n");
-	}
-}
-
-void foe() {
-	// resume block, call terminate
-	try {
-		zen y;
-		terminate(&y);
-	} catchResume (zen * error) {
-		printf("foe caught exception zen\n");
-	}
-}
-
-void fy() {
-	// terminate block calls fum, call foe
-	try {
-		foe();
-	} catch (zen * error) {
-		printf("fy caught exception zen\n");
-		fum();
-	}
-}
-
-void fee() {
-	// resume block, call fy
-	try {
-		fy();
-	} catchResume (zen * error) {
-		printf("fee caught exception zen\n");
-	}
-}
-
-
-// main: choose which tests to run
-int main(int argc, char * argv[]) {
-	signal_exit a = {"main function"};
-
-	foo(); printf("\n");
-	alpha(); printf("\n");
-	farewell(false); printf("\n");
-	farewell(true); printf("\n");
-	fallback(); printf("\n");
-	terminate_swapped(); printf("\n");
-	resume_swapped(); printf("\n");
-	reterminate(); printf("\n");
-	reresume(); printf("\n");
-	fee(); printf("\n");
-
-	// Uncaught termination test.
-	printf("Throw uncaught.\n");
-	yang z;
-	terminate(&z);
-}
Index: sts/except-1.cfa
===================================================================
--- tests/except-1.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ 	(revision )
@@ -1,81 +1,0 @@
-// Draft memory management test. (remember -fexceptions)
-// Outdated: The integer constant exceptions need to be replaced with virtual
-// exceptions for the new system.
-
-#include <stdio.h>
-
-#include "except-mac.hfa"
-TRIVIAL_EXCEPTION(yin)
-TRIVIAL_EXCEPTION(yang)
-
-int main()
-{
-	try {
-		yin a;
-		THROW(&a);
-	}
-	catch( yin * err ) {
-		printf("First Caught\n");
-		try {
-			yang b;
-			THROW(&b);
-		}
-		catch( yang * err ) {
-			printf("Both Caught\n");
-		}
-	}
-	printf("Part A Complete\n");
-
-	try {
-		try {
-			yang c;
-			THROW(&c);
-		}
-		catch( yang * err ) {
-			printf("First Catch and rethrow\n");
-			throw;
-		}
-	}
-	catch( yang * err ) {
-		printf("Second Catch\n");
-	}
-	printf("Part B Complete\n");
-
-	try {
-		try {
-			yin d;
-			THROW(&d);
-		}
-		catch( yin * err ) {
-			printf("Throw before cleanup\n");
-			yang e;
-			THROW(&e);
-		}
-	}
-	catch( yang * err ) {
-		printf("Catch after cleanup\n");
-	}
-	printf("Part C Complete\n");
-
-	try {
-		try {
-			yin f;
-			THROW(&f);
-		}
-		catch( yin * err ) {
-			printf("Caught initial throw.\n");
-			try {
-				yang g;
-				THROW(&g);
-			}
-			catch( yang * err ) {
-				printf("Caught intermediate throw.\n");
-			}
-			throw;
-		}
-	}
-	catch( yin * err ) {
-		printf("Caught final throw.\n");
-	}
-	printf("Part D Complete\n");
-}
Index: sts/except-2.cfa
===================================================================
--- tests/except-2.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ 	(revision )
@@ -1,92 +1,0 @@
-// New draft of exception tests.
-
-
-#include <stdlib.hfa>
-#include "except-mac.hfa"
-
-TRIVIAL_EXCEPTION(yin)
-TRIVIAL_EXCEPTION(yang)
-
-struct num_error;
-struct num_error_vtable {
-	struct TABLE(BASE_EXCEPT) const * parent;
-	size_t size;
-	void (*copy)(num_error *this, num_error * other);
-	void (*free)(num_error *this);
-	const char * (*msg)(num_error *this);
-	int (*code)(num_error *this);
-};
-extern num_error_vtable INSTANCE(num_error);
-
-struct num_error {
-	struct num_error_vtable const * virtual_table;
-	char * msg;
-	int num;
-};
-
-void num_error_msg(num_error * this) {
-	if ( ! this->msg ) {
-		static const char * base = "Num Error with code: X";
-		this->msg = malloc(22);
-		for (int i = 0 ; (this->msg[i] = base[i]) ; ++i);
-	}
-	this->msg[21] = '0' + this->num;
-	return this->msg;
-}
-void ?{}(num_error * this, int num) {
-	this->virtual_table = &INSTANCE(num_error);
-	this->msg = 0;
-	this->num = num;
-}
-void ?{}(num_error * this, num_error * other) {
-	this->virtual_table = other->virtual_table;
-	this->msg = 0;
-	this->num = other->num;
-}
-void ^?{}(num_error * this) {
-	if( this->msg ) free( this->msg );
-}
-int num_error_code( num_error * this ) {
-	return this->num;
-}
-num_error_vtable _num_error_vtable_instance @= {
-	&INSTANCE(BASE_EXCEPT),
-	sizeof(num_error), ?{}, ^?{},
-	num_error_msg, num_error_code
-};
-
-
-// Test simple throwing, matching and catching.
-void throw_catch() {
-	try {
-		yin black;
-		THROW(&black);
-	} catch ( yin * error ) {
-		printf("throw yin caught.\n");
-	}
-
-	try {
-		yang white;
-		THROW_RESUME(&white);
-		printf("> throwResume returned.\n");
-	} catchResume ( yang * error ) {
-		printf("throwResume yang caught <");
-	}
-
-	try {
-		num_error x = { 2 };
-		THROW(&x);
-	}
-	catch (num_error * error ; 3 == error->virtual_table->code( error ) ) {
-		printf("exception at %p\n", error );
-		printf("Should not be printed.\n");
-	}
-	catch (num_error * error ; 2 == error->virtual_table->code( error ) ) {
-		printf("Should be printed.\n");
-	}
-}
-
-int main (int argc, char * argv[]) {
-	throw_catch();
-	return 0;
-}
Index: sts/except-3.cfa
===================================================================
--- tests/except-3.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ 	(revision )
@@ -1,18 +1,0 @@
-// Test that __attribute__((cleanup(...))) is working.
-
-#include <stdio.h>
-#include "except-mac.hfa"
-TRIVIAL_EXCEPTION(myth)
-
-int main (int argc, char * argv[]) {
-	try {
-		try {
-			printf("throw [");
-			THROW(&(myth){});
-		} finally {
-			printf("] unwind <");
-		}
-	} catch (myth * error) {
-		printf("> catch\n");
-	}
-}
Index: sts/except-finally-error.cfa
===================================================================
--- tests/except-finally-error.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ 	(revision )
@@ -1,147 +1,0 @@
-// All of these should be caught as long as the check remains in the same
-// pass. (Although not even all of the checks are in place yet.)
-
-void break_in_finally() {
-	while (true) {
-		try {} finally {
-			break;
-		}
-	}
-}
-
-void for_break_in_finally() {
-	for (10) {
-		try {} finally {
-			break;
-		}
-	}
-}
-
-void do_while_break_in_finally() {
-	do {
-		try {} finally {
-			break;
-		}
-	} while (false);
-}
-
-void continue_in_finally() {
-	while (true) {
-		try {} finally {
-			continue;
-		}
-	}
-}
-
-void goto_in_finally() {
-	while (true) {
-		try {} finally {
-			goto end_of_function;
-		}
-	}
-	end_of_function: {}
-}
-
-void labelled_break_in_finally() {
-	mainLoop: while (true) {
-		try {} finally {
-			break mainLoop;
-		}
-	}
-}
-
-void labelled_continue_in_finally() {
-	mainLoop: while (true) {
-		try {} finally {
-			continue mainLoop;
-		}
-	}
-}
-
-void switch_break_in_finally() {
-	switch (1) {
-	case 1:
-		try {} finally {
-			break;
-		}
-	default:
-		break;
-	}
-}
-
-void choose_break_in_finally() {
-	choose (1) {
-	case 1:
-		try {} finally {
-			break;
-		}
-	default:
-		break;
-	}
-}
-
-void choose_fallthru_in_finally() {
-	choose (1) {
-	case 1:
-		try {} finally {
-			fallthru;
-		}
-	default:
-		break;
-	}
-}
-
-void labelled_choose_break_in_finally() {
-	mainBlock: choose (1) {
-	case 1:
-		try {} finally {
-			break mainBlock;
-		}
-	case 2:
-		break;
-	default:
-		break;
-	}
-}
-
-void labelled_choose_fallthru_in_finally() {
-	mainBlock: choose (1) {
-	case 1:
-		try {} finally {
-			fallthru mainBlock;
-		}
-	case 2:
-		break;
-	default:
-		break;
-	}
-}
-
-void choose_fallthru_default_in_finally() {
-	choose (1) {
-	case 1:
-		try {} finally {
-			fallthru default;
-		}
-	default:
-		break;
-	}
-}
-
-void void_return_in_finally() {
-	try {} finally {
-		return;
-	}
-}
-
-int value_return_in_finally() {
-	try {} finally {
-		return -7;
-	}
-
-}
-
-void main() {
-	// Should not compile.
-	return 1;
-}
Index: sts/except-mac.hfa
===================================================================
--- tests/except-mac.hfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ 	(revision )
@@ -1,78 +1,0 @@
-// Macros to try and make declaring and using exceptions easier
-// No, these are not part of the language, they replace the virtual system.
-
-// Internal use:
-#define GLUE2(left, right) left##right
-#define GLUE3(left, middle, right) left##middle##right
-
-// The fully (perhaps overly) qualified name of the base exception type:
-#define BASE_EXCEPT __cfaabi_ehm__base_exception_t
-
-// Get the name of the vtable type and vtable instance for an exception type:
-#define TABLE(name) GLUE2(name,_vtable)
-#define INSTANCE(name) GLUE3(_,name,_vtable_instance)
-
-// Throws and the bit of overhead:
-#define THROW(expr) throw ((BASE_EXCEPT *)(expr))
-#define THROW_RESUME(expr) throwResume ((BASE_EXCEPT *)(expr))
-
-
-
-// The following macros are for defining your own new exception types.
-
-// Declare vtable and forward declare the exception type and vtable instance.
-// This should start a new exception declaration.
-// ... argument is the additional vtable fields.
-#define DECLARE_EXCEPT(except_name,parent_name,...) \
-struct except_name; \
-struct TABLE(except_name) { \
-	struct TABLE(parent_name) const * parent; \
-	size_t size; \
-	void (*copy)(except_name *this, except_name * other); \
-	void (*free)(except_name &this); \
-	const char * (*msg)(except_name *this); \
-	__VA_ARGS__ \
-}; \
-extern TABLE(except_name) INSTANCE(except_name);
-
-// The first field of the exception structure should be created with this.
-#define VTABLE_FIELD(except_name) \
-struct TABLE(except_name) const * virtual_table
-
-// In each constructor the vtable must be initialized.
-#define VTABLE_INIT(this_name,except_name) \
-this_name.virtual_table = &INSTANCE(except_name)
-
-// Declare the vtable instance. This should end an exception declaration.
-// ... argument is the remaining vtable field values.
-#define VTABLE_INSTANCE(except_name,parent_name,copy,free,msg,...) \
-TABLE(except_name) INSTANCE(except_name) @= { \
-	&INSTANCE(parent_name), sizeof(except_name), \
-	copy, free, msg, ## __VA_ARGS__ \
-};
-
-// Same, but used declarators for arguments.
-#define VTABLE_INSTANCE_KEY(except_name,parent_name,copy,free,msg,...) \
-TABLE(except_name) INSTANCE(except_name) @= { \
-	.parent : &INSTANCE(parent_name), .size : sizeof(except_name), \
-	.copy : copy, .free : free, .msg : msg, ## __VA_ARGS__ \
-};
-
-
-
-// Declare a trivial exception, one that adds no features:
-#define TRIVIAL_EXCEPTION(name) \
-DECLARE_EXCEPT(name,BASE_EXCEPT,) \
-struct name { \
-	VTABLE_FIELD(name); \
-}; \
-const char * GLUE2(name,_msg)(name * this) { \
-    return #name; \
-} \
-void GLUE2(name,_copy)(name * this, name * other) { \
-    this->virtual_table = other->virtual_table; \
-} \
-void ?{}(name & this) { \
-	VTABLE_INIT(this,name); \
-} \
-VTABLE_INSTANCE(name,BASE_EXCEPT,GLUE2(name,_copy),^?{},GLUE2(name,_msg),)
Index: tests/exceptions/.expect/finally-error.txt
===================================================================
--- tests/exceptions/.expect/finally-error.txt	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ tests/exceptions/.expect/finally-error.txt	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,15 @@
+exceptions/finally-error.cfa:7:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/finally-error.cfa:15:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/finally-error.cfa:23:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/finally-error.cfa:31:1 error: 'continue' target must be an enclosing loop: 
+exceptions/finally-error.cfa:48:1 error: 'break' target must be an enclosing control structure: mainLoop
+exceptions/finally-error.cfa:56:1 error: 'continue' target must be an enclosing loop: mainLoop
+exceptions/finally-error.cfa:65:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/finally-error.cfa:76:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/finally-error.cfa:87:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
+exceptions/finally-error.cfa:98:1 error: 'break' target must be an enclosing control structure: mainBlock
+exceptions/finally-error.cfa:111:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
+exceptions/finally-error.cfa:124:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
+exceptions/finally-error.cfa:133:1 error: 'return' may not appear in a finally clause
+exceptions/finally-error.cfa:139:1 error: 'return' may not appear in a finally clause
+exceptions/finally-error.cfa:148:1 error: 'break' outside a loop, 'switch', or labelled block
Index: tests/exceptions/except-0.cfa
===================================================================
--- tests/exceptions/except-0.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ tests/exceptions/except-0.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,247 @@
+// Draft of tests for exception handling.
+// Outdated: The integer constant exceptions need to be replaced with virtual
+// exceptions for the new system.
+
+// ERROR: exceptions do not interact with ^?{} properly.
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "except-mac.hfa"
+TRIVIAL_EXCEPTION(yin)
+TRIVIAL_EXCEPTION(yang)
+TRIVIAL_EXCEPTION(zen)
+
+
+// Local type to mark exits from scopes. (see ERROR)
+struct signal_exit {
+	const char * area;
+};
+
+void ?{}(signal_exit * this, const char * area) {
+	this->area = area;
+}
+
+void ^?{}(signal_exit * this) {
+	printf("Exiting: %s\n", this->area);
+//	sout | "Exiting:" | this->area;
+}
+
+
+// Mark throws: make sure to only pass in exception types.
+forall(dtype T)
+void terminate(T * except_value) {
+	signal_exit a = {"terminate function"};
+	THROW(except_value);
+	printf("terminate returned\n");
+}
+
+forall(dtype T)
+void resume(T * except_value) {
+	signal_exit a = {"resume function"};
+	THROW_RESUME(except_value);
+	printf("resume returned\n");
+}
+
+// Termination Test: Two handlers: no catch, catch
+void bar() {
+	signal_exit a = {"bar function"};
+	try {
+		terminate(&(zen){});
+	} catch (yin * error) {
+		printf("bar caught exception yin.\n");
+	}
+}
+
+void foo() {
+	signal_exit a = {"foo function"};
+	try {
+		bar();
+	} catch (yang * error) {
+		printf("foo caught exception yang.\n");
+	} catch (zen * error) {
+		printf("foo caught exception zen.\n");
+	}
+}
+
+// Resumption Two Handler Test: no catch, catch.
+void beta() {
+	signal_exit a = {"beta function"};
+	try {
+		zen x;
+		resume(&x);
+	} catchResume (yin * error) {
+		printf("beta caught exception yin\n");
+	}
+}
+
+void alpha() {
+	signal_exit a = {"alpha function"};
+	try {
+		beta();
+	} catchResume (yang * error) {
+		printf("alpha caught exception yang\n");
+	} catchResume (zen * error) {
+		printf("alpha caught exception zen\n");
+	}
+}
+
+// Finally Test:
+void farewell(bool jump) {
+	try {
+		if (jump) {
+			printf("jump out of farewell\n");
+			goto endoffunction;
+		} else {
+			printf("walk out of farewell\n");
+		}
+	} finally {
+		printf("See you next time\n");
+	}
+	endoffunction:
+	printf("leaving farewell\n");
+}
+
+// Resume-to-Terminate Test:
+void fallback() {
+	try {
+		zen x;
+		resume(&x);
+	} catch (zen * error) {
+		printf("fallback caught termination zen\n");
+	}
+}
+
+// Terminate Throw New Exception:
+void terminate_swap() {
+	signal_exit a = {"terminate_swap"};
+	try {
+		yin x;
+		terminate(&x);
+	} catch (yin * error) {
+		yang y;
+		terminate(&y);
+	}
+}
+
+void terminate_swapped() {
+	signal_exit a = {"terminate_swapped"};
+	try {
+		terminate_swap();
+	} catch (yang * error) {
+		printf("terminate_swapped caught exception yang\n");
+	}
+}
+
+// Resume Throw New Exception:
+void resume_swap() {
+	signal_exit a = {"resume_swap"};
+	try {
+		yin x;
+		resume(&x);
+	} catchResume (yin * error) {
+		yang y;
+		resume(&y);
+	}
+}
+
+void resume_swapped() {
+	try {
+		resume_swap();
+	} catchResume (yang * error) {
+		printf("resume_swapped caught exception yang\n");
+	}
+}
+
+// Terminate Rethrow:
+void reterminate() {
+	try {
+		try {
+			zen x;
+			terminate(&x);
+		} catch (zen * error) {
+			printf("reterminate zen caught and "
+			       "will rethrow exception zen\n");
+			throw;
+		}
+	} catch (zen * error) {
+		printf("reterminate 1 caught exception zen\n");
+	}
+}
+
+// Resume Rethrow:
+void reresume() {
+	try {
+		try {
+			zen x;
+			resume(&x);
+		} catchResume (zen * error) {
+			printf("reresume zen caught and rethrows exception zen\n");
+			throwResume;
+		}
+	} catchResume (zen * error) {
+		printf("reresume 1 caught exception zen\n");
+	}
+}
+
+// Terminate-Resume interaction:
+void fum() {
+	// terminate block, call resume
+	try {
+		zen x;
+		resume(&x);
+	} catch (zen * error) {
+		printf("fum caught exception zen\n");
+	}
+}
+
+void foe() {
+	// resume block, call terminate
+	try {
+		zen y;
+		terminate(&y);
+	} catchResume (zen * error) {
+		printf("foe caught exception zen\n");
+	}
+}
+
+void fy() {
+	// terminate block calls fum, call foe
+	try {
+		foe();
+	} catch (zen * error) {
+		printf("fy caught exception zen\n");
+		fum();
+	}
+}
+
+void fee() {
+	// resume block, call fy
+	try {
+		fy();
+	} catchResume (zen * error) {
+		printf("fee caught exception zen\n");
+	}
+}
+
+
+// main: choose which tests to run
+int main(int argc, char * argv[]) {
+	signal_exit a = {"main function"};
+
+	foo(); printf("\n");
+	alpha(); printf("\n");
+	farewell(false); printf("\n");
+	farewell(true); printf("\n");
+	fallback(); printf("\n");
+	terminate_swapped(); printf("\n");
+	resume_swapped(); printf("\n");
+	reterminate(); printf("\n");
+	reresume(); printf("\n");
+	fee(); printf("\n");
+
+	// Uncaught termination test.
+	printf("Throw uncaught.\n");
+	yang z;
+	terminate(&z);
+}
Index: tests/exceptions/except-1.cfa
===================================================================
--- tests/exceptions/except-1.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ tests/exceptions/except-1.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,81 @@
+// Draft memory management test. (remember -fexceptions)
+// Outdated: The integer constant exceptions need to be replaced with virtual
+// exceptions for the new system.
+
+#include <stdio.h>
+
+#include "except-mac.hfa"
+TRIVIAL_EXCEPTION(yin)
+TRIVIAL_EXCEPTION(yang)
+
+int main()
+{
+	try {
+		yin a;
+		THROW(&a);
+	}
+	catch( yin * err ) {
+		printf("First Caught\n");
+		try {
+			yang b;
+			THROW(&b);
+		}
+		catch( yang * err ) {
+			printf("Both Caught\n");
+		}
+	}
+	printf("Part A Complete\n");
+
+	try {
+		try {
+			yang c;
+			THROW(&c);
+		}
+		catch( yang * err ) {
+			printf("First Catch and rethrow\n");
+			throw;
+		}
+	}
+	catch( yang * err ) {
+		printf("Second Catch\n");
+	}
+	printf("Part B Complete\n");
+
+	try {
+		try {
+			yin d;
+			THROW(&d);
+		}
+		catch( yin * err ) {
+			printf("Throw before cleanup\n");
+			yang e;
+			THROW(&e);
+		}
+	}
+	catch( yang * err ) {
+		printf("Catch after cleanup\n");
+	}
+	printf("Part C Complete\n");
+
+	try {
+		try {
+			yin f;
+			THROW(&f);
+		}
+		catch( yin * err ) {
+			printf("Caught initial throw.\n");
+			try {
+				yang g;
+				THROW(&g);
+			}
+			catch( yang * err ) {
+				printf("Caught intermediate throw.\n");
+			}
+			throw;
+		}
+	}
+	catch( yin * err ) {
+		printf("Caught final throw.\n");
+	}
+	printf("Part D Complete\n");
+}
Index: tests/exceptions/except-2.cfa
===================================================================
--- tests/exceptions/except-2.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ tests/exceptions/except-2.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,92 @@
+// New draft of exception tests.
+
+
+#include <stdlib.hfa>
+#include "except-mac.hfa"
+
+TRIVIAL_EXCEPTION(yin)
+TRIVIAL_EXCEPTION(yang)
+
+struct num_error;
+struct num_error_vtable {
+	struct TABLE(BASE_EXCEPT) const * parent;
+	size_t size;
+	void (*copy)(num_error *this, num_error * other);
+	void (*free)(num_error *this);
+	const char * (*msg)(num_error *this);
+	int (*code)(num_error *this);
+};
+extern num_error_vtable INSTANCE(num_error);
+
+struct num_error {
+	struct num_error_vtable const * virtual_table;
+	char * msg;
+	int num;
+};
+
+void num_error_msg(num_error * this) {
+	if ( ! this->msg ) {
+		static const char * base = "Num Error with code: X";
+		this->msg = malloc(22);
+		for (int i = 0 ; (this->msg[i] = base[i]) ; ++i);
+	}
+	this->msg[21] = '0' + this->num;
+	return this->msg;
+}
+void ?{}(num_error * this, int num) {
+	this->virtual_table = &INSTANCE(num_error);
+	this->msg = 0;
+	this->num = num;
+}
+void ?{}(num_error * this, num_error * other) {
+	this->virtual_table = other->virtual_table;
+	this->msg = 0;
+	this->num = other->num;
+}
+void ^?{}(num_error * this) {
+	if( this->msg ) free( this->msg );
+}
+int num_error_code( num_error * this ) {
+	return this->num;
+}
+num_error_vtable _num_error_vtable_instance @= {
+	&INSTANCE(BASE_EXCEPT),
+	sizeof(num_error), ?{}, ^?{},
+	num_error_msg, num_error_code
+};
+
+
+// Test simple throwing, matching and catching.
+void throw_catch() {
+	try {
+		yin black;
+		THROW(&black);
+	} catch ( yin * error ) {
+		printf("throw yin caught.\n");
+	}
+
+	try {
+		yang white;
+		THROW_RESUME(&white);
+		printf("> throwResume returned.\n");
+	} catchResume ( yang * error ) {
+		printf("throwResume yang caught <");
+	}
+
+	try {
+		num_error x = { 2 };
+		THROW(&x);
+	}
+	catch (num_error * error ; 3 == error->virtual_table->code( error ) ) {
+		printf("exception at %p\n", error );
+		printf("Should not be printed.\n");
+	}
+	catch (num_error * error ; 2 == error->virtual_table->code( error ) ) {
+		printf("Should be printed.\n");
+	}
+}
+
+int main (int argc, char * argv[]) {
+	throw_catch();
+	return 0;
+}
Index: tests/exceptions/except-3.cfa
===================================================================
--- tests/exceptions/except-3.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ tests/exceptions/except-3.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,18 @@
+// Test that __attribute__((cleanup(...))) is working.
+
+#include <stdio.h>
+#include "except-mac.hfa"
+TRIVIAL_EXCEPTION(myth)
+
+int main (int argc, char * argv[]) {
+	try {
+		try {
+			printf("throw [");
+			THROW(&(myth){});
+		} finally {
+			printf("] unwind <");
+		}
+	} catch (myth * error) {
+		printf("> catch\n");
+	}
+}
Index: tests/exceptions/except-mac.hfa
===================================================================
--- tests/exceptions/except-mac.hfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ tests/exceptions/except-mac.hfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,78 @@
+// Macros to try and make declaring and using exceptions easier
+// No, these are not part of the language, they replace the virtual system.
+
+// Internal use:
+#define GLUE2(left, right) left##right
+#define GLUE3(left, middle, right) left##middle##right
+
+// The fully (perhaps overly) qualified name of the base exception type:
+#define BASE_EXCEPT __cfaabi_ehm__base_exception_t
+
+// Get the name of the vtable type and vtable instance for an exception type:
+#define TABLE(name) GLUE2(name,_vtable)
+#define INSTANCE(name) GLUE3(_,name,_vtable_instance)
+
+// Throws and the bit of overhead:
+#define THROW(expr) throw ((BASE_EXCEPT *)(expr))
+#define THROW_RESUME(expr) throwResume ((BASE_EXCEPT *)(expr))
+
+
+
+// The following macros are for defining your own new exception types.
+
+// Declare vtable and forward declare the exception type and vtable instance.
+// This should start a new exception declaration.
+// ... argument is the additional vtable fields.
+#define DECLARE_EXCEPT(except_name,parent_name,...) \
+struct except_name; \
+struct TABLE(except_name) { \
+	struct TABLE(parent_name) const * parent; \
+	size_t size; \
+	void (*copy)(except_name *this, except_name * other); \
+	void (*free)(except_name &this); \
+	const char * (*msg)(except_name *this); \
+	__VA_ARGS__ \
+}; \
+extern TABLE(except_name) INSTANCE(except_name);
+
+// The first field of the exception structure should be created with this.
+#define VTABLE_FIELD(except_name) \
+struct TABLE(except_name) const * virtual_table
+
+// In each constructor the vtable must be initialized.
+#define VTABLE_INIT(this_name,except_name) \
+this_name.virtual_table = &INSTANCE(except_name)
+
+// Declare the vtable instance. This should end an exception declaration.
+// ... argument is the remaining vtable field values.
+#define VTABLE_INSTANCE(except_name,parent_name,copy,free,msg,...) \
+TABLE(except_name) INSTANCE(except_name) @= { \
+	&INSTANCE(parent_name), sizeof(except_name), \
+	copy, free, msg, ## __VA_ARGS__ \
+};
+
+// Same, but used declarators for arguments.
+#define VTABLE_INSTANCE_KEY(except_name,parent_name,copy,free,msg,...) \
+TABLE(except_name) INSTANCE(except_name) @= { \
+	.parent : &INSTANCE(parent_name), .size : sizeof(except_name), \
+	.copy : copy, .free : free, .msg : msg, ## __VA_ARGS__ \
+};
+
+
+
+// Declare a trivial exception, one that adds no features:
+#define TRIVIAL_EXCEPTION(name) \
+DECLARE_EXCEPT(name,BASE_EXCEPT,) \
+struct name { \
+	VTABLE_FIELD(name); \
+}; \
+const char * GLUE2(name,_msg)(name * this) { \
+    return #name; \
+} \
+void GLUE2(name,_copy)(name * this, name * other) { \
+    this->virtual_table = other->virtual_table; \
+} \
+void ?{}(name & this) { \
+	VTABLE_INIT(this,name); \
+} \
+VTABLE_INSTANCE(name,BASE_EXCEPT,GLUE2(name,_copy),^?{},GLUE2(name,_msg),)
Index: tests/exceptions/finally-error.cfa
===================================================================
--- tests/exceptions/finally-error.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
+++ tests/exceptions/finally-error.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -0,0 +1,156 @@
+// All of these should be caught as long as the check remains in the same
+// pass. (Although not even all of the checks are in place yet.)
+
+void break_in_finally() {
+	while (true) {
+		try {} finally {
+			break;
+		}
+	}
+}
+
+void for_break_in_finally() {
+	for (10) {
+		try {} finally {
+			break;
+		}
+	}
+}
+
+void do_while_break_in_finally() {
+	do {
+		try {} finally {
+			break;
+		}
+	} while (false);
+}
+
+void continue_in_finally() {
+	while (true) {
+		try {} finally {
+			continue;
+		}
+	}
+}
+
+void goto_in_finally() {
+	while (true) {
+		try {} finally {
+			goto end_of_function;
+		}
+	}
+	end_of_function: {}
+}
+
+void labelled_break_in_finally() {
+	mainLoop: while (true) {
+		try {} finally {
+			break mainLoop;
+		}
+	}
+}
+
+void labelled_continue_in_finally() {
+	mainLoop: while (true) {
+		try {} finally {
+			continue mainLoop;
+		}
+	}
+}
+
+void switch_break_in_finally() {
+	switch (1) {
+	case 1:
+		try {} finally {
+			break;
+		}
+	default:
+		break;
+	}
+}
+
+void choose_break_in_finally() {
+	choose (1) {
+	case 1:
+		try {} finally {
+			break;
+		}
+	default:
+		break;
+	}
+}
+
+void choose_fallthru_in_finally() {
+	choose (1) {
+	case 1:
+		try {} finally {
+			fallthru;
+		}
+	default:
+		break;
+	}
+}
+
+void labelled_choose_break_in_finally() {
+	mainBlock: choose (1) {
+	case 1:
+		try {} finally {
+			break mainBlock;
+		}
+	case 2:
+		break;
+	default:
+		break;
+	}
+}
+
+void labelled_choose_fallthru_in_finally() {
+	mainBlock: choose (1) {
+	case 1:
+		try {} finally {
+			fallthru mainBlock;
+		}
+	case 2:
+		break;
+	default:
+		break;
+	}
+}
+
+void choose_fallthru_default_in_finally() {
+	choose (1) {
+	case 1:
+		try {} finally {
+			fallthru default;
+		}
+	default:
+		break;
+	}
+}
+
+void void_return_in_finally() {
+	try {} finally {
+		return;
+	}
+}
+
+int value_return_in_finally() {
+	try {} finally {
+		return -7;
+	}
+
+}
+
+// Checked in the same place, make sure it does't break.
+void break_in_function() {
+	while (true) {
+		void inner() {
+			break;
+		}
+	}
+}
+
+void main() {
+	// Should not compile.
+	return 1;
+}
Index: tests/expression.cfa
===================================================================
--- tests/expression.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ tests/expression.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -1,51 +1,85 @@
+struct S { int i; };
+void ?{}( S & s, int i ) { s.i = i; }
+int ?`mary( int );
+int ?`mary( S );
+[int] ?`mary( [int, int] );
+int & ?`jane( int & );
+int jack( int );
+
 int main() {
-    struct s { int i; } x, *p = &x;
-    int i = 3;
+    int a[3] = { 0, 0, 0 };
+    S s = { 3 }, * ps = &s;
+    [int] t = { 3 };
+    * [int] pt = &t;
+    int i = 1, j = 2;
 
     // operators
 
-    ! i;
+    !i;
     ~i;
     +i;
     -i;
-    *p;
-    ++p;
-    --p;
-    p++;
-    p--;
+    *ps;
+    ++ps;
+    --ps;
+    ps++;
+    ps--;
 
-    i+i;
-    i-i;
-    i*i;
+    i + j;
+    i - j;
+    i * j;
 
-    i/i;
-    i%i;
-    i^i;
-    i&i;
-    i|i;
-    i<i;
-    i>i;
-    i=i;
+    i / j;
+    i % j;
+    i ^ j;
+    i & j;
+    i | j;
+    i < j;
+    i > j;
+    i = j;
 
-    i==i;
-    i!=i;
-    i<<i;
-    i>>i;
-    i<=i;
-    i>=i;
-    i&&i;
-    i||i;
-    p->i;
-    i*=i;
-    i/=i;
-    i%=i;
-    i+=i;
-    i-=i;
-    i&=i;
-    i|=i;
-    i^=i;
-    i<<=i;
-    i>>=i;
+    i == j;
+    i != j;
+    i << j;
+    i >> j;
+    i <= j;
+    i >= j;
+    i && j;
+    i || j;
+    ps->i;
 
-    i?i:i;
+    i *= j;
+    i /= j;
+    i %= j;
+    i += j;
+    i -= j;
+    i &= j;
+    i |= j;
+    i ^= j;
+    i <<= j;
+    i >>= j;
+
+    i ? i : j;
+
+    // postfix function call
+
+    (3 + 4)`mary;
+    ({3 + 4;})`mary;
+    [3, 4]`mary;
+    3`mary;
+    a[0]`mary;
+    a[0]`mary`mary;
+    s{0}`mary;
+    a[3]`jane++;
+    jack(3)`mary;
+    s.i`mary;
+    t.0`mary;
+    s.[i]`mary;
+    ps->i`mary;
+    pt->0`mary;
+    ps->[i]`mary;
+    i++`mary;
+    i--`mary;
+    (S){2}`mary;
+    (S)@{2}`mary;
 } // main
Index: tests/quotedKeyword.cfa
===================================================================
--- tests/quotedKeyword.cfa	(revision 09f357ec00aefca93e05dd3cc0f865d2b3fe0881)
+++ tests/quotedKeyword.cfa	(revision 4f7b418b1407ea6b3c3af7a736618baceddcbbc1)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Dec  4 21:45:53 2018
-// Update Count     : 23
+// Last Modified On : Sat Feb  1 00:02:22 2020
+// Update Count     : 24
 //
 
@@ -17,29 +17,29 @@
 
 struct {
-	int `otype`;
-	int `struct`;
+	int ``otype``;
+	int ``struct``;
 } st = { 10, 10 };
 
-typedef int `forall`;
-`forall` xxx = 10;
+typedef int ``forall``;
+``forall`` xxx = 10;
 
-int `_Alignas`, `_Alignof`, `__alignof`, `__alignof__`, `asm`, `__asm`, `__asm__`, `_At`, `_Atomic`, `__attribute`,
-	`__attribute__`, `auto`, `_Bool`, `break`, `case`, `catch`, `catchResume`, `char`, `choose`, `_Complex`, `__complex`,
-	`__complex__`, `const`, `__const`, `__const__`, `continue`, `default`, `disable`, `do`, `double`, `dtype`, `else`,
-	`enable`, `enum`, `__extension__`, `extern`, `fallthru`, `finally`, `float`, `__float128`, `for`, `forall`, `fortran`,
-	`ftype`, `_Generic`, `goto`, `if`, `_Imaginary`, `__imag`, `__imag__`, `inline`, `__inline`, `__inline__`, `int`,
-	`__int128`, `__label__`, `long`, `lvalue`, `_Noreturn`, `__builtin_offsetof`, `otype`, `register`, `restrict`,
-	`__restrict`, `__restrict__`, `return`, `short`, `signed`, `__signed`, `__signed__`, `sizeof`, `static`,
-	`_Static_assert`, `struct`, `switch`, `_Thread_local`, `throw`, `throwResume`, `trait`, `try`, `typedef`,
-	`typeof`, `__typeof`, `__typeof__`, `union`, `unsigned`, `__builtin_va_list`, `void`, `volatile`, `__volatile`,
-	`__volatile__`, `while`;
+int ``_Alignas``, ``_Alignof``, ``__alignof``, ``__alignof__``, ``asm``, ``__asm``, ``__asm__``, ``_At``, ``_Atomic``, ``__attribute``,
+	``__attribute__``, ``auto``, ``_Bool``, ``break``, ``case``, ``catch``, ``catchResume``, ``char``, ``choose``, ``_Complex``, ``__complex``,
+	``__complex__``, ``const``, ``__const``, ``__const__``, ``continue``, ``default``, ``disable``, ``do``, ``double``, ``dtype``, ``else``,
+	``enable``, ``enum``, ``__extension__``, ``extern``, ``fallthru``, ``finally``, ``float``, ``__float128``, ``for``, ``forall``, ``fortran``,
+	``ftype``, ``_Generic``, ``goto``, ``if``, ``_Imaginary``, ``__imag``, ``__imag__``, ``inline``, ``__inline``, ``__inline__``, ``int``,
+	``__int128``, ``__label__``, ``long``, ``lvalue``, ``_Noreturn``, ``__builtin_offsetof``, ``otype``, ``register``, ``restrict``,
+	``__restrict``, ``__restrict__``, ``return``, ``short``, ``signed``, ``__signed``, ``__signed__``, ``sizeof``, ``static``,
+	``_Static_assert``, ``struct``, ``switch``, ``_Thread_local``, ``throw``, ``throwResume``, ``trait``, ``try``, ``typedef``,
+	``typeof``, ``__typeof``, ``__typeof__``, ``union``, ``unsigned``, ``__builtin_va_list``, ``void``, ``volatile``, ``__volatile``,
+	``__volatile__``, ``while``;
 
 int main() {
-	int `if` = 0;
-	`catch` = 1;
-	st.`otype` = 2;
-	st.`struct` = 3;
-	`throw` = 4;
-	sout | `catch` + st.`otype` + st.`struct` + `throw`;
+	int ``if`` = 0;
+	``catch`` = 1;
+	st.``otype`` = 2;
+	st.``struct`` = 3;
+	``throw`` = 4;
+	sout | ``catch`` + st.``otype`` + st.``struct`` + ``throw``;
 }
 
