summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--lib.c178
2 files changed, 98 insertions, 87 deletions
diff --git a/ChangeLog b/ChangeLog
index 28bd6199..f57a7269 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2014-12-31 Kaz Kylheku <kaz@kylheku.com>
+ * lib.c (replace_str, replace_vec): Bugfix. The replacement item
+ sequence may be an infinite list in the case that the from argument
+ specifies a list of indices. We must avoid trying to calculate its
+ length before we have detected this case.
+
+2014-12-31 Kaz Kylheku <kaz@kylheku.com>
+
* txr.1: Fix error. (set [seq index-list] new) corresponds to
replace not to refset.
diff --git a/lib.c b/lib.c
index dd038866..a6f01a66 100644
--- a/lib.c
+++ b/lib.c
@@ -2607,8 +2607,6 @@ val replace_str(val str_in, val items, val from, val to)
{
val itseq = toseq(items);
val len = length_str(str_in);
- val len_it = length(itseq);
- val len_rep;
if (type(str_in) != STR) {
uw_throwf(error_s, lit("replace-str: ~s of type ~s is not "
@@ -2651,53 +2649,57 @@ val replace_str(val str_in, val items, val from, val to)
from = max2(zero, min2(from, len));
to = max2(zero, min2(to, len));
- len_rep = minus(to, from);
- if (gt(len_rep, len_it)) {
- val len_diff = minus(len_rep, len_it);
- cnum t = c_num(to);
- cnum l = c_num(len);
-
- wmemmove(str_in->st.str + t - c_num(len_diff),
- str_in->st.str + t, (l - t) + 1);
- set(mkloc(str_in->st.len, str_in), minus(len, len_diff));
- to = plus(from, len_it);
- } else if (lt(len_rep, len_it)) {
- val len_diff = minus(len_it, len_rep);
- cnum t = c_num(to);
- cnum l = c_num(len);
-
- string_extend(str_in, plus(len, len_diff));
- wmemmove(str_in->st.str + t + c_num(len_diff),
- str_in->st.str + t, (l - t) + 1);
- to = plus(from, len_it);
- }
+ {
+ val len_rep = minus(to, from);
+ val len_it = length(itseq);
+
+ if (gt(len_rep, len_it)) {
+ val len_diff = minus(len_rep, len_it);
+ cnum t = c_num(to);
+ cnum l = c_num(len);
+
+ wmemmove(str_in->st.str + t - c_num(len_diff),
+ str_in->st.str + t, (l - t) + 1);
+ set(mkloc(str_in->st.len, str_in), minus(len, len_diff));
+ to = plus(from, len_it);
+ } else if (lt(len_rep, len_it)) {
+ val len_diff = minus(len_it, len_rep);
+ cnum t = c_num(to);
+ cnum l = c_num(len);
+
+ string_extend(str_in, plus(len, len_diff));
+ wmemmove(str_in->st.str + t + c_num(len_diff),
+ str_in->st.str + t, (l - t) + 1);
+ to = plus(from, len_it);
+ }
- if (zerop(len_it))
- return str_in;
- if (stringp(itseq)) {
- wmemcpy(str_in->st.str + c_num(from), c_str(itseq), c_num(len_it));
- } else {
- val iter;
- cnum f = c_num(from);
- cnum t = c_num(to);
- cnum s;
-
- if (listp(itseq)) {
- for (iter = itseq; iter && f != t; iter = cdr(iter), f++)
- str_in->st.str[f] = c_chr(car(iter));
- } else if (vectorp(itseq)) {
- for (s = 0; f != t; f++, s++)
- str_in->st.str[f] = c_chr(vecref(itseq, num(s)));
+ if (zerop(len_it))
+ return str_in;
+ if (stringp(itseq)) {
+ wmemcpy(str_in->st.str + c_num(from), c_str(itseq), c_num(len_it));
} else {
- uw_throwf(error_s, lit("replace-str: source object ~s not supported"),
- itseq, nao);
+ val iter;
+ cnum f = c_num(from);
+ cnum t = c_num(to);
+ cnum s;
+
+ if (listp(itseq)) {
+ for (iter = itseq; iter && f != t; iter = cdr(iter), f++)
+ str_in->st.str[f] = c_chr(car(iter));
+ } else if (vectorp(itseq)) {
+ for (s = 0; f != t; f++, s++)
+ str_in->st.str[f] = c_chr(vecref(itseq, num(s)));
+ } else {
+ uw_throwf(error_s, lit("replace-str: source object ~s not supported"),
+ itseq, nao);
+ }
}
}
+
return str_in;
}
-
val cat_str(val list, val sep)
{
cnum total = 0;
@@ -4950,8 +4952,6 @@ val replace_vec(val vec_in, val items, val from, val to)
{
val it_seq = toseq(items);
val len = length_vec(vec_in);
- val len_it = length(it_seq);
- val len_rep;
if (consp(from)) {
val where = from;
@@ -4988,55 +4988,59 @@ val replace_vec(val vec_in, val items, val from, val to)
from = max2(zero, min2(from, len));
to = max2(zero, min2(to, len));
- len_rep = minus(to, from);
-
- if (gt(len_rep, len_it)) {
- val len_diff = minus(len_rep, len_it);
- cnum t = c_num(to);
- cnum l = c_num(len);
-
- memmove(vec_in->v.vec + t - c_num(len_diff),
- vec_in->v.vec + t,
- (l - t) * sizeof vec_in->v.vec);
+ {
+ val len_rep = minus(to, from);
+ val len_it = length(it_seq);
+
+ if (gt(len_rep, len_it)) {
+ val len_diff = minus(len_rep, len_it);
+ cnum t = c_num(to);
+ cnum l = c_num(len);
+
+ memmove(vec_in->v.vec + t - c_num(len_diff),
+ vec_in->v.vec + t,
+ (l - t) * sizeof vec_in->v.vec);
+
+ vec_in->v.vec[vec_length] = minus(len, len_diff);
+ to = plus(from, len_it);
+ } else if (lt(len_rep, len_it)) {
+ val len_diff = minus(len_it, len_rep);
+ cnum t = c_num(to);
+ cnum l = c_num(len);
+
+ vec_set_length(vec_in, plus(len, len_diff));
+
+ memmove(vec_in->v.vec + t + c_num(len_diff),
+ vec_in->v.vec + t,
+ (l - t) * sizeof vec_in->v.vec);
+ to = plus(from, len_it);
+ }
- vec_in->v.vec[vec_length] = minus(len, len_diff);
- to = plus(from, len_it);
- } else if (lt(len_rep, len_it)) {
- val len_diff = minus(len_it, len_rep);
- cnum t = c_num(to);
- cnum l = c_num(len);
+ if (zerop(len_it))
+ return vec_in;
+ if (vectorp(it_seq)) {
+ memcpy(vec_in->v.vec + c_num(from), it_seq->v.vec,
+ sizeof *vec_in->v.vec * c_num(len_it));
+ mut(vec_in);
+ } else if (stringp(it_seq)) {
+ cnum f = c_num(from);
+ cnum t = c_num(to);
+ cnum s;
+ const wchar_t *str = c_str(it_seq);
- vec_set_length(vec_in, plus(len, len_diff));
+ for (s = 0; f != t; f++, s++)
+ vec_in->v.vec[f] = chr(str[s]);
+ } else {
+ val iter;
+ cnum f = c_num(from);
+ cnum t = c_num(to);
- memmove(vec_in->v.vec + t + c_num(len_diff),
- vec_in->v.vec + t,
- (l - t) * sizeof vec_in->v.vec);
- to = plus(from, len_it);
+ for (iter = it_seq; iter && f != t; iter = cdr(iter), f++)
+ vec_in->v.vec[f] = car(iter);
+ mut(vec_in);
+ }
}
- if (zerop(len_it))
- return vec_in;
- if (vectorp(it_seq)) {
- memcpy(vec_in->v.vec + c_num(from), it_seq->v.vec,
- sizeof *vec_in->v.vec * c_num(len_it));
- mut(vec_in);
- } else if (stringp(it_seq)) {
- cnum f = c_num(from);
- cnum t = c_num(to);
- cnum s;
- const wchar_t *str = c_str(it_seq);
-
- for (s = 0; f != t; f++, s++)
- vec_in->v.vec[f] = chr(str[s]);
- } else {
- val iter;
- cnum f = c_num(from);
- cnum t = c_num(to);
-
- for (iter = it_seq; iter && f != t; iter = cdr(iter), f++)
- vec_in->v.vec[f] = car(iter);
- mut(vec_in);
- }
return vec_in;
}