From 56da0c3895ae502a6e17064a8e3ad588694ae910 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 14 Mar 2016 22:00:51 -0700 Subject: @(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. --- match.c | 46 +++++++++++++++++++++++++--------------------- txr.1 | 18 ++++++++++++------ 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. -- cgit v1.2.3