summaryrefslogtreecommitdiffstats
path: root/struct.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-10-07 21:47:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-10-07 21:47:34 -0700
commit2b249216eba72f0ea9700b7eede3711ff45a1327 (patch)
tree19a29b5dbada43ec938ee79f310aa4f3810d2c0e /struct.c
parent7881029601e0be941431f19f5c309455e84b551a (diff)
downloadtxr-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.c28
1 files changed, 16 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;
}