summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--eval.c2
-rw-r--r--eval.h1
-rw-r--r--txr.110
-rw-r--r--txr.c47
5 files changed, 55 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 90619035..671e8ddd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2014-01-22 Kaz Kylheku <kaz@kylheku.com>
+
+ * eval.c (eval_instrinsic): Changed to external linkage.
+
+ * eval.h (eval_intrinsic): Declared.
+
+ * txr.c (spec_file): Global variable removed.
+ (txr_main): Support for -e and -p options. Minor code cleanup.
+
+ * txr.1: Documented new options.
+
2014-01-21 Kaz Kylheku <kaz@kylheku.com>
* eval.c (mapcarv, mappendv): Convert output to type of leftmost
diff --git a/eval.c b/eval.c
index 8ac48da8..1562d1be 100644
--- a/eval.c
+++ b/eval.c
@@ -429,7 +429,7 @@ val interp_fun(val env, val fun, val args)
return eval_progn(body, fun_env, body);
}
-static val eval_intrinsic(val form, val env)
+val eval_intrinsic(val form, val env)
{
uses_or2;
form = expand(form);
diff --git a/eval.h b/eval.h
index e7fd6c39..163d352f 100644
--- a/eval.h
+++ b/eval.h
@@ -37,6 +37,7 @@ val interp_fun(val env, val fun, val args);
val apply(val fun, val arglist, val ctx_form);
val eval_progn(val forms, val env, val ctx_form);
val eval(val form, val env, val ctx_form);
+val eval_intrinsic(val form, val env);
val expand(val form);
val bindable(val obj);
val mapcarv(val fun, val list_of_lists);
diff --git a/txr.1 b/txr.1
index 49333855..b43630fa 100644
--- a/txr.1
+++ b/txr.1
@@ -182,6 +182,16 @@ Specifies the file from which the query is to be read, instead of the
query-file argument. This is useful in #! scripts. (See Hash Bang Support
below).
+.IP "-e expression"
+Evaluates a TXR Lisp expression for its side effects, without printing
+its value. Can be specified more than once. The query-file argument becomes
+optional if -e is used at least once.
+
+.IP "-p expression"
+Evaluates a TXR Lisp expression and prints its value. Can be specified more
+than once. The query-file argument becomes optional if -p is used at least
+once.
+
.IP --help
Prints usage summary on standard output, and terminates successfully.
diff --git a/txr.c b/txr.c
index fc1bb32b..452893dd 100644
--- a/txr.c
+++ b/txr.c
@@ -44,11 +44,11 @@
#include "utf8.h"
#include "debug.h"
#include "syslog.h"
+#include "eval.h"
#include "txr.h"
const wchli_t *version = wli("75");
const wchar_t *progname = L"txr";
-const wchar_t *spec_file = L"stdin";
val self_path;
/*
@@ -175,7 +175,9 @@ int txr_main(int argc, char **argv)
{
val specstring = nil;
val spec = nil;
+ val spec_file = nil;
val bindings = nil;
+ val evaled = nil;
int match_loglevel = opt_loglevel;
prot1(&spec_file_str);
@@ -253,7 +255,9 @@ int txr_main(int argc, char **argv)
return 0;
}
- if (!strcmp(*argv, "-a") || !strcmp(*argv, "-c") || !strcmp(*argv, "-f")) {
+ if (!strcmp(*argv, "-a") || !strcmp(*argv, "-c") || !strcmp(*argv, "-f") ||
+ !strcmp(*argv, "-e") || !strcmp(*argv, "-p"))
+ {
long optval;
char *errp;
char opt = (*argv)[1];
@@ -283,7 +287,17 @@ int txr_main(int argc, char **argv)
specstring = string_utf8(*argv);
break;
case 'f':
- spec_file_str = string_utf8(*argv);
+ spec_file = string_utf8(*argv);
+ break;
+ case 'e':
+ eval_intrinsic(lisp_parse(string_utf8(*argv), std_error), nil);
+ evaled = t;
+ break;
+ case 'p':
+ obj_print(eval_intrinsic(lisp_parse(string_utf8(*argv), std_error),
+ nil), std_output);
+ put_char(chr('\n'), std_output);
+ evaled = t;
break;
}
@@ -359,6 +373,8 @@ int txr_main(int argc, char **argv)
break;
case 'a':
case 'c':
+ case 'e':
+ case 'p':
case 'D':
format(std_error, lit("~a: option -~a does not clump\n"),
prog_string, chr(*popt), nao);
@@ -378,30 +394,32 @@ int txr_main(int argc, char **argv)
}
}
- if (specstring && spec_file_str) {
+ if (specstring && spec_file) {
format(std_error, lit("~a: cannot specify both -f and -c\n"),
prog_string, nao);
return EXIT_FAILURE;
}
if (specstring) {
- spec_file = L"cmdline";
- spec_file_str = string(spec_file);
+ spec_file_str = lit("cmdline");
if (gt(length_str(specstring), zero) &&
chr_str(specstring, minus(length_str(specstring), one)) != chr('\n'))
specstring = cat_str(list(specstring, string(L"\n"), nao), nil);
yyin_stream = make_string_byte_input_stream(specstring);
- } else if (spec_file_str) {
- if (wcscmp(c_str(spec_file_str), L"-") != 0) {
- FILE *in = w_fopen(c_str(spec_file_str), L"r");
+ } else if (spec_file) {
+ if (wcscmp(c_str(spec_file), L"-") != 0) {
+ FILE *in = w_fopen(c_str(spec_file), L"r");
if (in == 0)
- uw_throwf(file_error_s, lit("unable to open ~a"), spec_file_str, nao);
- yyin_stream = make_stdio_stream(in, spec_file_str);
+ uw_throwf(file_error_s, lit("unable to open ~a"), spec_file, nao);
+ yyin_stream = make_stdio_stream(in, spec_file);
+ spec_file_str = spec_file;
} else {
- spec_file = L"stdin";
+ spec_file_str = lit("stdin");
}
} else {
if (argc < 1) {
+ if (evaled)
+ return EXIT_SUCCESS;
hint();
return EXIT_FAILURE;
}
@@ -412,12 +430,11 @@ int txr_main(int argc, char **argv)
if (in == 0)
uw_throwf(file_error_s, lit("unable to open ~a"), name, nao);
yyin_stream = make_stdio_stream(in, name);
- spec_file = utf8_dup_from(*argv);
+ spec_file_str = string_utf8(*argv);
} else {
- spec_file = L"stdin";
+ spec_file_str = lit("stdin");
}
argc--, argv++;
- spec_file_str = string(spec_file);
}