summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sysif.c2
-rw-r--r--sysif.h1
-rw-r--r--tests/019/load-ret.tl10
-rw-r--r--tests/019/load-ret/bad.tl1
-rw-r--r--tests/019/load-ret/script.tl1
-rw-r--r--txr.122
-rw-r--r--txr.c15
7 files changed, 41 insertions, 11 deletions
diff --git a/sysif.c b/sysif.c
index b02ec607..6eedb011 100644
--- a/sysif.c
+++ b/sysif.c
@@ -220,7 +220,7 @@ static val daemon_wrap(val nochdir, val noclose)
}
#endif
-static val exit_wrap(val status)
+val exit_wrap(val status)
{
val self = lit("exit");
int stat;
diff --git a/sysif.h b/sysif.h
index 891cc091..13788c91 100644
--- a/sysif.h
+++ b/sysif.h
@@ -44,6 +44,7 @@ val env(void);
val replace_env(val env_list);
val getenv_wrap(val name);
val errno_to_str(int err);
+val exit_wrap(val status);
val at_exit_call(val func);
val at_exit_do_not_call(val func);
val usleep_wrap(val usec);
diff --git a/tests/019/load-ret.tl b/tests/019/load-ret.tl
index a79f7da9..1c99281f 100644
--- a/tests/019/load-ret.tl
+++ b/tests/019/load-ret.tl
@@ -11,3 +11,13 @@
(load-for (var abc "load-ret/module2" 'abc)) nil
(load-for (var abc "load-ret/module2" 'abc)
(var ghi "load-ret/module2" 'ghi 2 3 4)) 9)
+
+(defvarl here (dir-name self-path))
+
+(mtest
+ (sh `@{txr-exe-path} @here/load-ret/script.tl 0`) 0
+ (sh `@{txr-exe-path} @here/load-ret/script.tl 1`) 1
+ (sh `@{txr-exe-path} @here/load-ret/script.tl 7`) 7)
+
+(test
+ (sh `@{txr-exe-path} @here/load-ret/bad.tl 1 2> /dev/null`) 1)
diff --git a/tests/019/load-ret/bad.tl b/tests/019/load-ret/bad.tl
new file mode 100644
index 00000000..2d06f376
--- /dev/null
+++ b/tests/019/load-ret/bad.tl
@@ -0,0 +1 @@
+(
diff --git a/tests/019/load-ret/script.tl b/tests/019/load-ret/script.tl
new file mode 100644
index 00000000..8e13dabf
--- /dev/null
+++ b/tests/019/load-ret/script.tl
@@ -0,0 +1 @@
+(return-from load (toint [*args* 0]))
diff --git a/txr.1 b/txr.1
index 2cc3f8bf..4a83e358 100644
--- a/txr.1
+++ b/txr.1
@@ -82112,11 +82112,29 @@ expression. In this situation, the value of
.meta expr
will appear as the return value of the
.code load
-function. A block named
+function.
+
+When a \*(TL file, or compiled file, is executed from the \*(TX command line
+in such a way that \*(TX will terminate when that file's last form
+has been evaluated, then if that file performs a
+.code return-from
+the
+.code load
+block, the value of
+.meta expr
+will turn into the termination status in exactly the same way as if
+that value were used as an argument to the
+.code exit
+function. However, if \*(TX has been instructed to enter into the
+Listener after executing the file, then the value of
+.meta expr
+is discarded.
+
+A block named
.code load
is also established by the
.code @(load)
-directive in the pattern language, that that directive provides
+directive in the pattern language. That directive provides
no access to the returned value. The block is also visible to the
file processed from the command line. When a such a file aborts
the load via
diff --git a/txr.c b/txr.c
index 40e11ceb..78ea05b9 100644
--- a/txr.c
+++ b/txr.c
@@ -1261,26 +1261,25 @@ int txr_main(int argc, char **argv)
{
if (txr_lisp_p == chr('o')) {
- val result = nil;
uw_block_begin (load_s, ret);
- result = read_compiled_file_noerr(self, parse_stream, spec_file_str,
- std_error);
+ ret = read_compiled_file_noerr(self, parse_stream,
+ spec_file_str, std_error);
uw_block_end;
if (!enter_repl)
- return result ? 0 : EXIT_FAILURE;
+ exit_wrap(ret);
} else if (enter_repl) {
uw_block_begin (load_s, ret);
- read_eval_stream_noerr(self, parse_stream, spec_file_str, std_error);
+ ret = read_eval_stream_noerr(self, parse_stream,
+ spec_file_str, std_error);
uw_block_end;
close_stream(parse_stream, nil);
run_load_hooks(dyn_env);
uw_release_deferred_warnings();
} else {
- val result = nil;
uw_block_begin (load_s, ret);
- result = read_eval_stream(self, parse_stream, std_error);
+ ret = read_eval_stream(self, parse_stream, std_error);
uw_block_end;
- return result ? 0 : EXIT_FAILURE;
+ exit_wrap(ret);
}
}