summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-03-14 22:00:51 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-03-14 22:00:51 -0700
commit56da0c3895ae502a6e17064a8e3ad588694ae910 (patch)
tree590143197eb2c2d1f73cf700389047cec2bd358a
parent60ac365c8dbfce9f481fbfe58d4baae70df889b4 (diff)
downloadtxr-56da0c3895ae502a6e17064a8e3ad588694ae910.tar.gz
txr-56da0c3895ae502a6e17064a8e3ad588694ae910.tar.bz2
txr-56da0c3895ae502a6e17064a8e3ad588694ae910.zip
@(output)_destination can be a stream.
* match.c (complex_open): If name is a stream object, just return it. (v_output): Do not close the output stream if it came from a destination expression specifying an existing stream, and thus wasn't created inside complex_open. * txr.1: Document stream destination in output directive.
-rw-r--r--match.c46
-rw-r--r--txr.118
2 files changed, 37 insertions, 27 deletions
diff --git a/match.c b/match.c
index b3684180..4fbac813 100644
--- a/match.c
+++ b/match.c
@@ -1538,33 +1538,37 @@ static val txeval_allow_ub(val spec, val form, val bindings)
static val complex_open(val name, val output, val append, val nothrow)
{
- val fc = car(name);
- val result = nil;
+ if (streamp(name)) {
+ return name;
+ } else {
+ val fc = car(name);
+ val result = nil;
- if (fc == chr('$') && output)
- uw_throwf(query_error_s, lit("cannot output to directory: ~a"),
- name, nao);
+ if (fc == chr('$') && output)
+ uw_throwf(query_error_s, lit("cannot output to directory: ~a"),
+ name, nao);
- uw_catch_begin (if2(nothrow, cons(error_s, nil)), exc_sym, exc);
+ uw_catch_begin (if2(nothrow, cons(error_s, nil)), exc_sym, exc);
- if (fc == chr('-')) {
- result = output ? std_output : std_input;
- } else if (fc == chr('!')) {
- result = open_command(cdr(name), output ? lit("w") : lit("r"));
- } else if (fc == chr('$')) {
- result = open_directory(cdr(name));
- } else {
- result = open_file(name,
- output ? append ? lit("a") : lit("w") : lit("r"));
- }
+ if (fc == chr('-')) {
+ result = output ? std_output : std_input;
+ } else if (fc == chr('!')) {
+ result = open_command(cdr(name), output ? lit("w") : lit("r"));
+ } else if (fc == chr('$')) {
+ result = open_directory(cdr(name));
+ } else {
+ result = open_file(name,
+ output ? append ? lit("a") : lit("w") : lit("r"));
+ }
- uw_catch (exc_sym, exc) { (void) exc; }
+ uw_catch (exc_sym, exc) { (void) exc; }
- uw_unwind { }
+ uw_unwind { }
- uw_catch_end;
+ uw_catch_end;
- return result;
+ return result;
+ }
}
static val robust_length(val obj)
@@ -3245,7 +3249,7 @@ static val v_output(match_files_ctx *c)
if (named_var)
c->bindings = acons(named_var, stream, c->bindings);
- else
+ else if (!streamp(dest))
close_stream(stream, t);
}
diff --git a/txr.1 b/txr.1
index a6dc6d76..5508d7e5 100644
--- a/txr.1
+++ b/txr.1
@@ -7231,18 +7231,24 @@ directive is:
@(end)
.cble
-The optional
-.meta destination
-is a string which gives the path name of
+If the directive has arguments, then the first one is evaluated.
+If it is an object other than a keyword symbol, then it specifies
+the optional
+.metn destination .
+Any remaining arguments after the optional destination are
+the keyword list. If the destination is missing, then the
+entire argument list is a keyword list.
+
+The destination may be a string which gives the path name of
a file to open for output. If the name is
.code -
it instead denotes standard output, and if it begins with
.code !
then the rest of the shell is treated as a shell command
-to which the output is piped.
+to which the output is piped. The destination string may be specified as a
+variable which holds text, as a string literal or as a quasiliteral
-The destination may be specified as a variable
-which holds text, as a string literal or as a quasiliteral
+Alternatively, the destination may be a stream object.
The keyword list consists of a mixture of boolean keywords which
do not have an argument, or keywords with arguments.