diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-10-07 21:47:34 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-10-07 21:47:34 -0700 |
commit | 2b249216eba72f0ea9700b7eede3711ff45a1327 (patch) | |
tree | 19a29b5dbada43ec938ee79f310aa4f3810d2c0e /struct.c | |
parent | 7881029601e0be941431f19f5c309455e84b551a (diff) | |
download | txr-2b249216eba72f0ea9700b7eede3711ff45a1327.tar.gz txr-2b249216eba72f0ea9700b7eede3711ff45a1327.tar.bz2 txr-2b249216eba72f0ea9700b7eede3711ff45a1327.zip |
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.
Diffstat (limited to 'struct.c')
-rw-r--r-- | struct.c | 28 |
1 files changed, 16 insertions, 12 deletions
@@ -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; } |