summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
Diffstat (limited to 'match.c')
-rw-r--r--match.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/match.c b/match.c
index 0756ea8c..0bc40838 100644
--- a/match.c
+++ b/match.c
@@ -74,7 +74,9 @@ val noval_s;
static val h_directive_table, v_directive_table;
static val non_matching_directive_table, binding_directive_table;
-static val v_next_keys, v_output_keys;
+static val v_next_keys;
+
+val v_output_keys;
static void debuglf(val form, val fmt, ...)
{
@@ -3172,7 +3174,7 @@ static val v_parallel(match_files_ctx *c)
val sym = first(first_spec);
val all_match = t;
val some_match = nil;
- val max_line = zero;
+ val max_line = nil;
val max_data = nil;
val specs = second(first_spec);
val plist = third(first_spec);
@@ -3254,7 +3256,7 @@ static val v_parallel(match_files_ctx *c)
max_data = t;
} else if (consp(success) && max_data != t) {
cons_bind (new_data, new_line, success);
- if (gt(new_line, max_line)) {
+ if (max_line == nil || gt(new_line, max_line)) {
max_line = new_line;
max_data = new_data;
}
@@ -3737,7 +3739,13 @@ static val v_collect(match_files_ctx *c)
if (consp(success)) {
cons_bind (new_data, new_line, success);
- bug_unless (ge(new_line, c->data_lineno));
+ /* The following assertion was in the code for the longest time.
+ * It doesn't hold because of @(push).
+ * In h_collect, the corresponding assertion that the
+ * character position advances is still there.
+ *
+ * bug_unless (ge(new_line, c->data_lineno));
+ */
if (new_line == c->data_lineno) {
new_data = cdr(new_data);
@@ -4151,6 +4159,52 @@ out:
return ret;
}
+static val v_push(match_files_ctx *c)
+{
+ spec_bind (specline, first_spec, c->spec);
+ val specs = second(first_spec);
+ val dest_spec = third(first_spec);
+ val filter = nil;
+ val alist;
+ val stream = make_strlist_output_stream();
+
+ uw_match_env_begin;
+
+ val saved_de = set_dyn_env(make_env(c->bindings, nil, nil));
+
+ uw_set_match_context(cons(c->spec, c->spec));
+
+ alist = improper_plist_to_alist(dest_spec, v_output_keys);
+
+ {
+ val filter_sym = cdr(assoc(filter_k, alist));
+
+ if (filter_sym) {
+ filter = get_filter(filter_sym);
+
+ if (!filter)
+ sem_error(specline, lit("~s specifies unknown filter"), filter_sym, nao);
+ }
+ }
+
+ do_output(c->bindings, specs, filter, stream);
+
+ {
+ val list_out = get_list_from_stream(stream);
+ val len = length(list_out);
+
+ if (c->data_lineno)
+ c->data_lineno = minus(c->data_lineno, len);
+ c->data = append2(list_out, c->data);
+
+ debuglf(specs, lit("prepended ~s lines of output: adjusted lineno is ~s"),
+ len, c->data_lineno, nao);
+ }
+
+ set_dyn_env(saved_de);
+ uw_match_env_end;
+ return next_spec_k;
+}
static val v_try(match_files_ctx *c)
{
spec_bind (specline, first_spec, c->spec);
@@ -5246,6 +5300,7 @@ static void dir_tables_init(void)
sethash(v_directive_table, set_s, cptr(coerce(mem_t *, v_set)));
sethash(v_directive_table, cat_s, cptr(coerce(mem_t *, v_cat)));
sethash(v_directive_table, output_s, cptr(coerce(mem_t *, v_output)));
+ sethash(v_directive_table, push_s, cptr(coerce(mem_t *, v_push)));
sethash(v_directive_table, define_s, cptr(coerce(mem_t *, v_define)));
sethash(v_directive_table, try_s, cptr(coerce(mem_t *, v_try)));
sethash(v_directive_table, defex_s, cptr(coerce(mem_t *, v_defex)));