summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-10-15 19:05:43 -0700
committerKaz Kylheku <kaz@kylheku.com>2014-10-15 19:05:43 -0700
commit8eb4688b095bbdadfa05d0b853df662ac653e3d5 (patch)
treecfd3e5f2be60de09793cea305ad4a68f1a4e5866 /match.c
parent8807a16fe3115e19ce4d65f1c8beb476494ccaec (diff)
downloadtxr-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.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/match.c b/match.c
index 2aee0df9..aad77c91 100644
--- a/match.c
+++ b/match.c
@@ -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;