diff --git a/libc3/array.c b/libc3/array.c
index 87702c3..c0ce6e5 100644
--- a/libc3/array.c
+++ b/libc3/array.c
@@ -53,6 +53,7 @@ s_array * array_copy (const s_array *src, s_array *dest)
dest->dimensions = calloc(src->dimension, sizeof(s_array_dimension));
memcpy(dest->dimensions, src->dimensions,
src->dimension * sizeof(s_array_dimension));
+ dest->count = src->count;
dest->size = src->size;
dest->type = src->type;
if (src->data) {
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index d54b96a..b7c2861 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -50,7 +50,7 @@ sw buf_parse_array (s_buf *buf, s_array *dest)
assert(buf);
assert(dest);
buf_save_init(buf, &save);
- tmp = *dest;
+ bzero(&tmp, sizeof(tmp));
if ((r = buf_parse_paren_sym(buf, &tmp.type)) <= 0)
goto clean;
result += r;
@@ -86,10 +86,18 @@ sw buf_parse_array_data (s_buf *buf, s_array *dest)
assert(buf);
assert(dest);
tmp = *dest;
- address = calloc(tmp.dimension, sizeof(sw));
+ if (! (address = calloc(tmp.dimension, sizeof(sw)))) {
+ warnx("buf_parse_array_data: out of memory: address");
+ return -1;
+ }
tmp.size = tmp.dimensions[0].count * tmp.dimensions[0].item_size;
tmp.count = tmp.size / tmp.dimensions[tmp.dimension - 1].item_size;
- tmp.tags = calloc(tmp.count, sizeof(s_tag));
+ assert(tmp.count);
+ if (! (tmp.tags = calloc(tmp.count, sizeof(s_tag)))) {
+ free(address);
+ warnx("buf_parse_array_data: out of memory: tags");
+ return -1;
+ }
tag = tmp.tags;
if ((r = buf_parse_array_data_rec(buf, &tmp, address, &tag,
0)) <= 0) {
diff --git a/libc3/call.c b/libc3/call.c
index 798404a..6835db1 100644
--- a/libc3/call.c
+++ b/libc3/call.c
@@ -140,7 +140,8 @@ s_call * call_init_1 (s_call *call, const s8 *p)
return call;
}
-s_call * call_init_cast (s_call *call, const s_sym *type, s_tag *tag)
+s_call * call_init_cast (s_call *call, const s_sym *type,
+ const s_tag *tag)
{
assert(call);
bzero(call, sizeof(s_call));
diff --git a/libc3/call.h b/libc3/call.h
index 11c1ca9..0dadb06 100644
--- a/libc3/call.h
+++ b/libc3/call.h
@@ -19,7 +19,8 @@
void call_clean (s_call *call);
s_call * call_init (s_call *call);
s_call * call_init_1 (s_call *call, const s8 *p);
-s_call * call_init_cast (s_call *call, const s_sym *type, s_tag *tag);
+s_call * call_init_cast (s_call *call, const s_sym *type,
+ const s_tag *tag);
s_call * call_init_op (s_call *call);
s_call * call_init_op_unary (s_call *call);
diff --git a/libc3/env.c b/libc3/env.c
index b8e6e82..3967ca7 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -45,7 +45,7 @@
s_env g_c3_env;
-bool env_eval_array_cast (s_env *env, s_array *tmp, s_tag *tag,
+bool env_eval_array_cast (s_env *env, s_array *tmp, const s_tag *tag,
u8 *data, uw size);
void env_clean (s_env *env)
@@ -99,26 +99,30 @@ void env_error_tag (s_env *env, const s_tag *tag)
bool env_eval_array (s_env *env, const s_array *array, s_tag *dest)
{
u8 *data;
- uw i = 0;
- uw size;
+ uw i;
+ uw item_size;
s_tag *tag;
s_array tmp;
assert(env);
assert(array);
assert(dest);
array_copy(array, &tmp);
- size = tmp.dimensions[tmp.dimension - 1].item_size;
+ item_size = tmp.dimensions[tmp.dimension - 1].item_size;
if (! tmp.data &&
! (tmp.data = calloc(tmp.dimensions[0].count,
tmp.dimensions[0].item_size))) {
- assert(! "env_eval_array: out of memory");
- errx(1, "env_eval_array: out of memory");
+ assert(! "env_eval_array: out of memory: data");
+ errx(1, "env_eval_array: out of memory: data");
}
data = tmp.data;
tag = tmp.tags;
+ i = 0;
while (i < tmp.count) {
- env_eval_array_cast(env, &tmp, tag, data, size);
- data += size;
+ if (! env_eval_array_cast(env, &tmp, tag, data, item_size)) {
+ array_clean(&tmp);
+ return false;
+ }
+ data += item_size;
tag++;
i++;
}
@@ -127,11 +131,12 @@ bool env_eval_array (s_env *env, const s_array *array, s_tag *dest)
return true;
}
-bool env_eval_array_cast (s_env *env, s_array *tmp, s_tag *tag,
+bool env_eval_array_cast (s_env *env, s_array *tmp, const s_tag *tag,
u8 *data, uw size)
{
s_call call;
s_tag tag_eval;
+ e_tag_type tag_type;
void *data_eval;
assert(env);
assert(tmp);
@@ -142,8 +147,8 @@ bool env_eval_array_cast (s_env *env, s_array *tmp, s_tag *tag,
return false;
if (! env_eval_call(env, &call, &tag_eval))
return false;
- data_eval = tag_to_pointer(&tag_eval,
- array_type_to_tag_type(tmp->type));
+ tag_type = array_type_to_tag_type(tmp->type);
+ data_eval = tag_to_pointer(&tag_eval, tag_type);
memcpy(data, data_eval, size);
return true;
}
@@ -598,8 +603,8 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
tag_copy(tag, dest);
return true;
}
- assert(! "env_eval_tag: invalid tag");
- errx(1, "env_eval_tag: invalid tag");
+ assert(! "env_eval_tag: unknown tag type");
+ errx(1, "env_eval_tag: unknown tag type: %d", tag->type);
return false;
}