hush: make "exit" in trap use pre-trap exitcode

function                                             old     new   delta
check_and_run_traps                                  259     276     +17
builtin_exit                                          42      53     +11
hush_main                                           1086    1096     +10
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 38/0)               Total: 38 bytes

Fixes exitcode_trap2.tests.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/shell/hush.c b/shell/hush.c
index 6172f22..b881b00 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -988,6 +988,7 @@
 # define G_fatal_sig_mask 0
 #endif
 #if ENABLE_HUSH_TRAP
+	int pre_trap_exitcode;
 # if ENABLE_HUSH_FUNCTIONS
 	int return_exitcode;
 # endif
@@ -2111,10 +2112,11 @@
 				argv[1] = xstrdup(G_traps[sig]);
 				/* why strdup? trap can modify itself: trap 'trap "echo oops" INT' INT */
 				argv[2] = NULL;
-				save_rcode = G.last_exitcode;
+				G.pre_trap_exitcode = save_rcode = G.last_exitcode;
 				builtin_eval(argv);
 				free(argv[1]);
 				G.last_exitcode = save_rcode;
+				G.pre_trap_exitcode = -1;
 # if ENABLE_HUSH_FUNCTIONS
 				if (G.return_exitcode >= 0) {
 					debug_printf_exec("trap exitcode:%d\n", G.return_exitcode);
@@ -9927,8 +9929,11 @@
 	INIT_G();
 	if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
 		G.last_exitcode = EXIT_SUCCESS;
-#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
+#if ENABLE_HUSH_TRAP
+# if ENABLE_HUSH_FUNCTIONS
 	G.return_exitcode = -1;
+# endif
+	G.pre_trap_exitcode = -1;
 #endif
 
 #if ENABLE_HUSH_FAST
@@ -10575,8 +10580,13 @@
 
 	/* note: EXIT trap is run by hush_exit */
 	argv = skip_dash_dash(argv);
-	if (argv[0] == NULL)
+	if (argv[0] == NULL) {
+#if ENABLE_HUSH_TRAP
+		if (G.pre_trap_exitcode >= 0) /* "exit" in trap uses $? from before the trap */
+			hush_exit(G.pre_trap_exitcode);
+#endif
 		hush_exit(G.last_exitcode);
+	}
 	/* mimic bash: exit 123abc == exit 255 + error msg */
 	xfunc_error_retval = 255;
 	/* bash: exit -2 == exit 254, no error msg */