diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2011-11-17 11:18:42 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2011-11-17 11:18:42 -0800 |
commit | 68ca87bc780e25dea1418019161d99727225d1ce (patch) | |
tree | 7e4651a1e61db5c2205c518257e9c5bd9355037a /match.c | |
parent | 2668e984caf88abb2bd8d20d50573f23e73aa695 (diff) | |
download | txr-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.c | 43 |
1 files changed, 31 insertions, 12 deletions
@@ -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); |