diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-10-15 19:05:43 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-10-15 19:05:43 -0700 |
commit | 8eb4688b095bbdadfa05d0b853df662ac653e3d5 (patch) | |
tree | cfd3e5f2be60de09793cea305ad4a68f1a4e5866 /match.c | |
parent | 8807a16fe3115e19ce4d65f1c8beb476494ccaec (diff) | |
download | txr-8eb4688b095bbdadfa05d0b853df662ac653e3d5.tar.gz txr-8eb4688b095bbdadfa05d0b853df662ac653e3d5.tar.bz2 txr-8eb4688b095bbdadfa05d0b853df662ac653e3d5.zip |
* match.c (subst_vars): Fix buggy rendering of TXR Lisp expressions
that evaluate to lists. For instance `@(list)` renders to the
string "nil", and `@(list 1 2)` renders as "(1 2)". The desired
behavior is "" and "1 2", respectively.
(do_output_line): In output directives, there is a similar problem.
A @(list) in the middle of an output block turns to nil, and
a @(list 1 2) renders in parentheses as (1 2). Furthermore,
there is the additional problem that no filtering is applied
to the interpolated value. These behaviors are subject to the
compatibility option, since they change the externally visible
behavior of TXR programs.
* txr.1: Document that empty lists in @(output) variable substitutions
turn into nothing. Document value of 100 for -C option, describing
the above issue.
Diffstat (limited to 'match.c')
-rw-r--r-- | match.c | 29 |
1 files changed, 24 insertions, 5 deletions
@@ -1422,9 +1422,19 @@ static val subst_vars(val spec, val bindings, val filter) spec = cdr(spec); continue; } else if (sym == expr_s) { - val result = eval(rest(elem), make_env(bindings, nil, nil), elem); - spec = cons(filter_string_tree(filter, tostringp(result)), rest(spec)); - continue; + if (opt_compat && opt_compat < 100) { + val result = eval(rest(elem), make_env(bindings, nil, nil), elem); + spec = cons(filter_string_tree(filter, tostringp(result)), rest(spec)); + continue; + } else { + val str = eval(rest(elem), make_env(bindings, nil, nil), elem); + if (listp(str)) + str = cat_str(mapcar(func_n1(tostringp), str), lit(" ")); + else if (!stringp(str)) + str = tostringp(str); + spec = cons(filter_string_tree(filter, tostringp(str)), rest(spec)); + continue; + } } else { val nested = subst_vars(elem, bindings, filter); iter = list_collect_append(iter, nested); @@ -1774,8 +1784,17 @@ static void do_output_line(val bindings, val specline, val filter, val out) } } else if (directive == expr_s) { - format(out, lit("~a"), - eval(rest(elem), make_env(bindings, nil, nil), elem), nao); + if (opt_compat && opt_compat < 100) { + format(out, lit("~a"), + eval(rest(elem), make_env(bindings, nil, nil), elem), nao); + } else { + val str = cat_str(subst_vars(cons(elem, nil), + bindings, filter), nil); + if (str == nil) + sem_error(specline, lit("bad substitution: ~a"), + second(elem), nao); + put_string(str, out); + } } } break; |