summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-11-17 11:18:42 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-11-17 11:18:42 -0800
commit68ca87bc780e25dea1418019161d99727225d1ce (patch)
tree7e4651a1e61db5c2205c518257e9c5bd9355037a /match.c
parent2668e984caf88abb2bd8d20d50573f23e73aa695 (diff)
downloadtxr-68ca87bc780e25dea1418019161d99727225d1ce.tar.gz
txr-68ca87bc780e25dea1418019161d99727225d1ce.tar.bz2
txr-68ca87bc780e25dea1418019161d99727225d1ce.zip
* match.c (h_fun, v_fun): Bugfix! copy_list should be used for copying
the bindings, not copy_alist. Otherwise functions cannot destructively update a binding, which is useless. We want a function not to manipulate the binding list, but to be able to manipulate the contents of bindings. (match_files_ctx): Declaration moved ahead of match_line. (v_fun): Forward declaration added. (match_line): Allow vertical functions to be called from a horizontal context, in a limited way. * txr.1: Mention the possibility of a call from a horizontal context falling back on a vertical function.
Diffstat (limited to 'match.c')
-rw-r--r--match.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/match.c b/match.c
index 3e10b9bb..a4efdf4b 100644
--- a/match.c
+++ b/match.c
@@ -941,7 +941,7 @@ static val h_fun(match_line_ctx c, match_line_ctx *cout)
val ub_p_a_pairs = nil;
val body = cdr(func);
val piter, aiter;
- val bindings_cp = copy_alist(c.bindings);
+ val bindings_cp = copy_list(c.bindings);
if (!equal(length(args), length(params)))
sem_error(elem, lit("function ~a takes ~a argument(s)"),
@@ -1031,6 +1031,15 @@ static val h_eol(match_line_ctx c, match_line_ctx *cout)
return nil;
}
+typedef struct {
+ val spec, files, bindings, data, data_lineno;
+} match_files_ctx;
+
+static match_files_ctx mf_all(val spec, val files, val bindings,
+ val data, val data_lineno);
+
+static val v_fun(match_files_ctx *c);
+
static val match_line(match_line_ctx c)
{
for (;;) {
@@ -1095,12 +1104,26 @@ static val match_line(match_line_ctx c)
c = nc;
continue;
} else if (result == decline_k) {
- if (gethash(v_directive_table, directive))
- sem_error(elem, lit("~a only exists as a vertical directive"),
- directive, nao);
- else
- sem_error(elem, lit("no such function or directive: ~a"),
- directive, nao);
+ val spec = rlcp(cons(cons(elem, nil), nil), elem);
+ match_files_ctx vc = mf_all(spec, nil, c.bindings, nil, num(0));
+ val vresult = v_fun(&vc);
+
+ if (vresult == next_spec_k) {
+ c.bindings = vc.bindings;
+ break;
+ } else if (vresult == repeat_spec_k) {
+ c.bindings = vc.bindings;
+ continue;
+ } else if (vresult == decline_k) {
+ if (gethash(v_directive_table, directive))
+ sem_error(elem, lit("~a only exists as a vertical directive"),
+ directive, nao);
+ else
+ sem_error(elem, lit("no such function or directive: ~a"),
+ directive, nao);
+ } else {
+ return vresult;
+ }
} else {
return result;
}
@@ -1539,10 +1562,6 @@ static void do_output(val bindings, val specs, val filter, val out)
}
}
-typedef struct {
- val spec, files, bindings, data, data_lineno;
-} match_files_ctx;
-
static match_files_ctx mf_all(val spec, val files, val bindings,
val data, val data_lineno)
{
@@ -2889,7 +2908,7 @@ static val v_fun(match_files_ctx *c)
val ub_p_a_pairs = nil;
val body = cdr(func);
val piter, aiter;
- val bindings_cp = copy_alist(c->bindings);
+ val bindings_cp = copy_list(c->bindings);
debug_check(specline, c->bindings, if2(consp(c->data), car(c->data)), c->data_lineno, nil);