summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2013-10-11 21:21:28 -0700
committerKaz Kylheku <kaz@kylheku.com>2013-10-11 21:21:28 -0700
commit5d7d623bbcbda34354972af2ce608b8e110b1d3e (patch)
tree97a39fbbd79e5f6c8693e60f9127b6bf4110f2eb /match.c
parenteab83b3a45281d15a7c03d395ba8d4b5e19732b1 (diff)
downloadtxr-5d7d623bbcbda34354972af2ce608b8e110b1d3e.tar.gz
txr-5d7d623bbcbda34354972af2ce608b8e110b1d3e.tar.bz2
txr-5d7d623bbcbda34354972af2ce608b8e110b1d3e.zip
Task #11433. Implement continuation of multiple
output blocks across the same stream. * match.c (close_s, named_k, continue_k, finish_k): New symbol variables. (v_output): Implement :named, :finish and :continue. (v_close): New static function. (syms_init): New symbols interned. (dir_tables_init): New entry associating v_close function with symbol stored in close_s. * match.h (close_s): Declared. * txr.1: New features documented.
Diffstat (limited to 'match.c')
-rw-r--r--match.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/match.c b/match.c
index c692dbf8..0cd4da50 100644
--- a/match.c
+++ b/match.c
@@ -55,10 +55,11 @@ val decline_k, next_spec_k, repeat_spec_k;
val mingap_k, maxgap_k, gap_k, mintimes_k, maxtimes_k, times_k;
val lines_k, chars_k;
val text_s, choose_s, gather_s, do_s, mod_s, modlast_s, fuzz_s, load_s;
-val require_s;
+val close_s, require_s;
val longest_k, shortest_k, greedy_k;
val vars_k, resolve_k;
val append_k, into_k, var_k, list_k, string_k, env_k, counter_k;
+val named_k, continue_k, finish_k;
val filter_s;
@@ -3019,6 +3020,7 @@ static val v_output(match_files_ctx *c)
val append = nil;
val dest = lit("-");
val filter = nil;
+ val named_var = nil, continue_expr = nil, finish_expr = nil;
val alist;
fpip_t fp;
@@ -3037,6 +3039,18 @@ static val v_output(match_files_ctx *c)
nothrow = cdr(assoc(nothrow_k, alist));
append = cdr(assoc(append_k, alist));
+ named_var = cdr(assoc(named_k, alist));
+ continue_expr = cdr(assoc(continue_k, alist));
+ finish_expr = cdr(assoc(finish_k, alist));
+
+ if (named_var && continue_expr)
+ sem_error(specline, lit(":continue and :named are mutually exclusive"), nao);
+
+ if (named_var && finish_expr)
+ sem_error(specline, lit(":named and :finish are mutually exclusive"), nao);
+
+ if (continue_expr && finish_expr)
+ sem_error(specline, lit(":continue and :finish are mutually exclusive"), nao);
{
val filter_sym = cdr(assoc(filter_k, alist));
@@ -3058,6 +3072,12 @@ static val v_output(match_files_ctx *c)
if (!symbolp(into_var))
sem_error(specline, lit(":into requires a variable, not ~s"), into_var, nao);
+ if (named_var)
+ sem_error(specline, lit(":into incompatible with :named"), nao);
+
+ if (continue_expr)
+ sem_error(specline, lit(":into incompatible with :continue"), nao);
+
debuglf(specline, lit("opening string list stream"), nao);
uw_env_begin;
uw_set_match_context(cons(c->spec, c->bindings));
@@ -3083,6 +3103,25 @@ static val v_output(match_files_ctx *c)
}
}
+ if (continue_expr || finish_expr) {
+ uses_or2;
+ val which = or2(continue_expr, finish_expr);
+ val stream = txeval(specline, which, c->bindings);
+
+
+ if (!streamp(stream))
+ sem_error(specline, lit("~s evaluated to ~s which is not a stream"), which, stream, nao);
+
+ uw_env_begin;
+ uw_set_match_context(cons(c->spec, c->bindings));
+ do_output(c->bindings, specs, filter, stream);
+ flush_stream(stream);
+ uw_env_end;
+ if (finish_expr)
+ close_stream(stream, t);
+ return next_spec_k;
+ }
+
fp = (errno = 0, complex_open(dest, t, append));
debuglf(specline, lit("opening data sink ~a"), dest, nao);
@@ -3105,7 +3144,11 @@ static val v_output(match_files_ctx *c)
do_output(c->bindings, specs, filter, stream);
flush_stream(stream);
uw_env_end;
- close_stream(stream, t);
+
+ if (named_var)
+ c->bindings = acons(named_var, stream, c->bindings);
+ else
+ close_stream(stream, t);
}
return next_spec_k;
@@ -3558,6 +3601,23 @@ static val v_load(match_files_ctx *c)
}
}
+static val v_close(match_files_ctx *c)
+{
+ spec_bind (specline, first_spec, c->spec);
+ val args = rest(first_spec);
+ val stream = txeval(specline, first(args), c->bindings);
+
+ if (rest(specline))
+ sem_error(specline, lit("unexpected material after close"), nao);
+
+ if (!streamp(stream))
+ sem_error(specline, lit("close: ~s is not a stream"), stream, nao);
+
+ close_stream(stream, t);
+ return next_spec_k;
+}
+
+
static val h_do(match_line_ctx *c)
{
val elem = first(c->specline);
@@ -3778,6 +3838,7 @@ static void syms_init(void)
gather_s = intern(lit("gather"), user_package);
do_s = intern(lit("do"), user_package);
load_s = intern(lit("load"), user_package);
+ close_s = intern(lit("close"), user_package);
require_s = intern(lit("require"), user_package);
longest_k = intern(lit("longest"), keyword_package);
shortest_k = intern(lit("shortest"), keyword_package);
@@ -3790,6 +3851,9 @@ static void syms_init(void)
list_k = intern(lit("list"), keyword_package);
string_k = intern(lit("string"), keyword_package);
env_k = intern(lit("env"), keyword_package);
+ named_k = intern(lit("named"), keyword_package);
+ continue_k = intern(lit("continue"), keyword_package);
+ finish_k = intern(lit("finish"), keyword_package);
filter_s = intern(lit("filter"), user_package);
noval_s = intern(lit("noval"), system_package);
@@ -3843,6 +3907,7 @@ static void dir_tables_init(void)
sethash(v_directive_table, do_s, cptr((mem_t *) v_do));
sethash(v_directive_table, require_s, cptr((mem_t *) v_require));
sethash(v_directive_table, load_s, cptr((mem_t *) v_load));
+ sethash(v_directive_table, close_s, cptr((mem_t *) v_close));
sethash(h_directive_table, text_s, cptr((mem_t *) h_text));
sethash(h_directive_table, var_s, cptr((mem_t *) h_var));