summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-06-09 20:41:48 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-06-09 20:41:48 -0700
commit4e3816c640f19128e6700b8ed14cfbc01bf3a4fe (patch)
treebe9ab46e8dabd26186d7e13ecd5378eb52ed775c /match.c
parentafe4d4202c53f58975f1784356e8ff5bbc7b9818 (diff)
downloadtxr-4e3816c640f19128e6700b8ed14cfbc01bf3a4fe.tar.gz
txr-4e3816c640f19128e6700b8ed14cfbc01bf3a4fe.tar.bz2
txr-4e3816c640f19128e6700b8ed14cfbc01bf3a4fe.zip
Implement :counter in collect/coll.
* match.c (h_coll, v_collect): Parse out :collect keyword specification, using code borrowed from do_output. Implement binding in collect loop. * txr.1: Documented.
Diffstat (limited to 'match.c')
-rw-r--r--match.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/match.c b/match.c
index b4306d4a..a46ff145 100644
--- a/match.c
+++ b/match.c
@@ -814,6 +814,16 @@ static val h_coll(match_line_ctx *c)
val mintimes = txeval(elem, getplist(args, mintimes_k), c->bindings);
val maxtimes = txeval(elem, getplist(args, maxtimes_k), c->bindings);
val chars = txeval(elem, getplist(args, chars_k), c->bindings);
+ val counter_spec = getplist(args, counter_k);
+ val consp_counter = consp(counter_spec);
+ val counter = if3(consp_counter, first(counter_spec), counter_spec);
+ val counter_base = if3(consp_counter,
+ eval_with_bindings(second(counter_spec),
+ elem,
+ c->bindings,
+ counter_spec), zero);
+ val counter_binding = if2(counter, cons(counter, nil));
+ val bindings_with_counter = if2(counter, cons(counter_binding, nil));
val have_vars;
val vars = getplist_f(args, vars_k, mkcloc(have_vars));
cnum cmax = fixnump(gap) ? c_num(gap) : (fixnump(max) ? c_num(max) : 0);
@@ -834,6 +844,11 @@ static val h_coll(match_line_ctx *c)
have_vars = t;
}
+ if (counter && !bindable(counter))
+ sem_error(elem, lit("~s: ~s specified as :counter isn't a bindable symbol"),
+ op_sym, counter, nao);
+
+
vars = vars_to_bindings(elem, vars, c->bindings);
if (((times || maxtimes) && ctimax == 0) || (chars && cchars == 0))
@@ -849,8 +864,20 @@ static val h_coll(match_line_ctx *c)
break;
{
- cons_set (new_bindings, new_pos,
- match_line(ml_specline(*c, coll_specline)));
+ if (counter) {
+ rplacd(counter_binding, plus(num(timescounter), counter_base));
+ rplacd(bindings_with_counter, c->bindings);
+ cons_set (new_bindings, new_pos,
+ match_line(ml_bindings_specline(*c, bindings_with_counter, coll_specline)));
+
+ if (!new_bindings) {
+ rplacd(counter_binding, nil);
+ new_bindings = bindings_with_counter;
+ }
+ } else {
+ cons_set (new_bindings, new_pos,
+ match_line(ml_specline(*c, coll_specline)));
+ }
if (until_last_specline) {
uses_or2;
@@ -2840,6 +2867,16 @@ static val v_collect(match_files_ctx *c)
val mintimes = txeval(specline, getplist(args, mintimes_k), c->bindings);
val maxtimes = txeval(specline, getplist(args, maxtimes_k), c->bindings);
val lines = txeval(specline, getplist(args, lines_k), c->bindings);
+ val counter_spec = getplist(args, counter_k);
+ val consp_counter = consp(counter_spec);
+ val counter = if3(consp_counter, first(counter_spec), counter_spec);
+ val counter_base = if3(consp_counter,
+ eval_with_bindings(second(counter_spec),
+ specline,
+ c->bindings,
+ counter_spec), zero);
+ val counter_binding = if2(counter, cons(counter, nil));
+ val bindings_with_counter = if2(counter, cons(counter_binding, nil));
val have_vars;
volatile val vars = getplist_f(args, vars_k, mkcloc(have_vars));
cnum cmax = fixnump(gap) ? c_num(gap) : (fixnump(max) ? c_num(max) : 0);
@@ -2867,6 +2904,10 @@ static val v_collect(match_files_ctx *c)
have_vars = t;
}
+ if (counter && !bindable(counter))
+ sem_error(specline, lit("~s: ~s specified as :counter isn't a bindable symbol"),
+ op_sym, counter, nao);
+
vars = vars_to_bindings(specline, vars, c->bindings);
if ((times && ctimes == 0) || (lines && clines == 0))
@@ -2884,8 +2925,20 @@ static val v_collect(match_files_ctx *c)
break;
{
- cons_set (new_bindings, success,
- match_files(mf_spec(*c, coll_spec)));
+ if (counter) {
+ rplacd(counter_binding, plus(num(timescounter), counter_base));
+ rplacd(bindings_with_counter, c->bindings);
+ cons_set (new_bindings, success,
+ match_files(mf_spec_bindings(*c, coll_spec, bindings_with_counter)));
+
+ if (!new_bindings) {
+ rplacd(counter_binding, nil);
+ new_bindings = bindings_with_counter;
+ }
+ } else {
+ cons_set (new_bindings, success,
+ match_files(mf_spec(*c, coll_spec)));
+ }
/* Until/last clause sees un-collated bindings from collect. */
if (until_last_spec)