From 2b249216eba72f0ea9700b7eede3711ff45a1327 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 7 Oct 2016 21:47:34 -0700 Subject: Check for self-assignment in replace_struct. * struct.c (replace_struct): If target and source are the same object, just do nothing and return target. * txr.1: Document self-assignment and return value of replace-struct. --- struct.c | 28 ++++++++++++++++------------ txr.1 | 11 +++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/struct.c b/struct.c index 066b6f44..f42c685b 100644 --- a/struct.c +++ b/struct.c @@ -605,20 +605,24 @@ val clear_struct(val strct, val value) val replace_struct(val target, val source) { const val self = lit("replace-struct"); - struct struct_inst *tsi = struct_handle(target, self); - struct struct_inst *ssi = struct_handle(source, self); - struct struct_type *sst = ssi->type; - cnum nslots = sst->nslots; - size_t size = offsetof(struct struct_inst, slot) + sizeof (val) * nslots; - struct struct_inst *ssi_copy = coerce(struct struct_inst *, chk_malloc(size)); - check_init_lazy_struct(source, ssi); - check_init_lazy_struct(target, tsi); + if (target != source) { + struct struct_inst *tsi = struct_handle(target, self); + struct struct_inst *ssi = struct_handle(source, self); + struct struct_type *sst = ssi->type; + cnum nslots = sst->nslots; + size_t size = offsetof(struct struct_inst, slot) + sizeof (val) * nslots; + struct struct_inst *ssi_copy = coerce(struct struct_inst *, chk_malloc(size)); + + check_init_lazy_struct(source, ssi); + check_init_lazy_struct(target, tsi); + + memcpy(ssi_copy, ssi, size); + free(tsi); + target->co.handle = coerce(mem_t *, ssi_copy); + target->co.cls = source->co.cls; + } - memcpy(ssi_copy, ssi, size); - free(tsi); - target->co.handle = coerce(mem_t *, ssi_copy); - target->co.cls = source->co.cls; return target; } diff --git a/txr.1 b/txr.1 index c1fc78ce..c7fde830 100644 --- a/txr.1 +++ b/txr.1 @@ -21521,6 +21521,17 @@ prior to using .codn replace-struct , or to take other measures to handle the situation. +If the +.meta target-obj +and +.meta source-obj +arguments are the same object, +.code replace-struct +has no effect. + +The return value is +.metn target-obj . + .coNP Function @ method .synb .mets (method < struct-obj << slot-name ) -- cgit v1.2.3