diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 7f8fc28..7d3f7bd 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -60,15 +60,18 @@ sw buf_parse_call (s_buf *buf, s_call *dest)
sw r;
sw result = 0;
s_buf_save save;
+ s_call tmp;
assert(buf);
assert(dest);
buf_save_init(buf, &save);
- if ((r = buf_parse_ident(buf, &dest->ident)) <= 0)
+ call_init(&tmp);
+ if ((r = buf_parse_ident(buf, &tmp.ident)) <= 0)
goto clean;
result += r;
- if ((r = buf_parse_call_args_paren(buf, dest)) <= 0)
+ if ((r = buf_parse_call_args_paren(buf, &tmp)) <= 0)
goto restore;
result += r;
+ *dest = tmp;
r = result;
goto clean;
restore:
diff --git a/libc3/call.c b/libc3/call.c
index 6ec7833..f47c006 100644
--- a/libc3/call.c
+++ b/libc3/call.c
@@ -32,14 +32,15 @@ s_call * call_copy (const s_call *src, s_call *dest)
assert(dest);
ident_copy(&src->ident, &dest->ident);
list_copy(src->arguments, &dest->arguments);
+ dest->cfn = src->cfn;
+ dest->fn = src->fn;
return dest;
}
s_call * call_init (s_call *call)
{
assert(call);
- call->cfn = NULL;
- call->fn = NULL;
+ bzero(call, sizeof(s_call));
return call;
}
@@ -47,7 +48,8 @@ s_call * call_init_1 (s_call *call, const s8 *p)
{
s_buf buf;
buf_init_1(&buf, p);
- buf_parse_call(&buf, call);
+ if (buf_parse_call(&buf, call) != (sw) strlen(p))
+ errx(1, "invalid call: %s", p);
buf_clean(&buf);
return call;
}
diff --git a/libc3/env.c b/libc3/env.c
index 88eb1d0..4533c74 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -90,7 +90,7 @@ bool env_eval_call (s_env *env, const s_call *call, s_tag *dest)
assert(env);
assert(call);
assert(dest);
- c = *call;
+ call_copy(call, &c);
ident_resolve_module(&c.ident, env);
tag_init_1( &tag_cfn, ":cfn");
tag_init_1( &tag_fn, ":fn");
@@ -141,6 +141,7 @@ bool env_eval_call (s_env *env, const s_call *call, s_tag *dest)
else
result = env_eval_call_fn(env, &c, dest);
facts_with_cursor_clean(&cursor);
+ call_clean(&c);
return result;
}
diff --git a/test/buf_parse_test.c b/test/buf_parse_test.c
index 9e00090..07a8d3e 100644
--- a/test/buf_parse_test.c
+++ b/test/buf_parse_test.c
@@ -18,6 +18,7 @@
#include "../libc3/buf.h"
#include "../libc3/buf_parse.h"
#include "../libc3/call.h"
+#include "../libc3/cfn.h"
#include "../libc3/fn.h"
#include "../libc3/list.h"
#include "../libc3/str.h"
@@ -50,6 +51,18 @@
test_context(NULL); \
} while (0)
+#define BUF_PARSE_TEST_CFN(test) \
+ do { \
+ s_buf buf; \
+ s_cfn dest; \
+ test_context("buf_parse_cfn(" # test ")"); \
+ buf_init_1(&buf, (test)); \
+ TEST_EQ(buf_parse_cfn(&buf, &dest), strlen(test)); \
+ cfn_clean(&dest); \
+ buf_clean(&buf); \
+ test_context(NULL); \
+ } while (0)
+
#define BUF_PARSE_TEST_CHARACTER(test, expected) \
do { \
s_buf buf; \
@@ -284,6 +297,19 @@
test_context(NULL); \
} while (0)
+#define BUF_PARSE_TEST_NOT_CFN(test) \
+ do { \
+ s_buf buf; \
+ s_cfn dest; \
+ bzero(&dest, sizeof(dest)); \
+ test_context("buf_parse_cfn(" # test ") -> 0"); \
+ buf_init_1(&buf, (test)); \
+ TEST_EQ(buf_parse_cfn(&buf, &dest), 0); \
+ TEST_EQ(buf.rpos, 0); \
+ buf_clean(&buf); \
+ test_context(NULL); \
+ } while (0)
+
#define BUF_PARSE_TEST_NOT_CHARACTER(test) \
do { \
s_buf buf; \
@@ -588,6 +614,7 @@
void buf_parse_test_bool ();
void buf_parse_test_call ();
+void buf_parse_test_cfn ();
void buf_parse_test_character ();
void buf_parse_test_digit_bin ();
void buf_parse_test_digit_hex ();
@@ -635,6 +662,7 @@ void buf_parse_test ()
buf_parse_test_tag();
buf_parse_test_tuple();
buf_parse_test_ident();
+ buf_parse_test_cfn();
}
void buf_parse_test_bool ()
@@ -682,6 +710,20 @@ void buf_parse_test_call ()
BUF_PARSE_TEST_CALL("a(B.c(D.e(f, g), H.i(j, k)))");
}
+void buf_parse_test_cfn ()
+{
+ BUF_PARSE_TEST_NOT_CFN("0");
+ BUF_PARSE_TEST_NOT_CFN("9");
+ BUF_PARSE_TEST_NOT_CFN("A");
+ BUF_PARSE_TEST_NOT_CFN("Z");
+ BUF_PARSE_TEST_NOT_CFN("a");
+ BUF_PARSE_TEST_NOT_CFN("z");
+ BUF_PARSE_TEST_NOT_CFN("cfn 0 1 (2)");
+ BUF_PARSE_TEST_CFN("cfn :tag \"test\" (:tag)");
+ BUF_PARSE_TEST_CFN("cfn :tag \"test\" (:tag, :tag)");
+ BUF_PARSE_TEST_CFN("cfn :tag \"test\" (:tag, :tag, :tag)");
+}
+
void buf_parse_test_character ()
{
BUF_PARSE_TEST_NOT_CHARACTER("\x01");