diff --git a/libkc3/buf_parse.c b/libkc3/buf_parse.c
index 9b7755c..8ece04a 100644
--- a/libkc3/buf_parse.c
+++ b/libkc3/buf_parse.c
@@ -4032,6 +4032,7 @@ sw buf_parse_tag_primary_2 (s_buf *buf, s_tag *dest)
(r = buf_parse_tag_tuple(buf, dest)) != 0 ||
(r = buf_parse_tag_cfn(buf, dest)) != 0 ||
(r = buf_parse_tag_fn(buf, dest)) != 0 ||
+ (r = buf_parse_tag_time(buf, dest)) != 0 ||
(r = buf_parse_tag_struct(buf, dest)) != 0 ||
(r = buf_parse_tag_list(buf, dest)) != 0 ||
(r = buf_parse_tag_ident(buf, dest)) != 0 ||
@@ -4112,6 +4113,16 @@ sw buf_parse_tag_sym (s_buf *buf, s_tag *dest)
return r;
}
+sw buf_parse_tag_time (s_buf *buf, s_tag *dest)
+{
+ sw r;
+ assert(buf);
+ assert(dest);
+ if ((r = buf_parse_time(buf, &dest->data.time)) > 0)
+ dest->type = TAG_TIME;
+ return r;
+}
+
sw buf_parse_tag_tuple (s_buf *buf, s_tag *dest)
{
sw r;
@@ -4152,6 +4163,30 @@ sw buf_parse_tag_void (s_buf *buf, s_tag *dest)
return r;
}
+sw buf_parse_time (s_buf *buf, s_time *time)
+{
+ sw r;
+ sw result = 0;
+ s_sym keys[2] = {0};
+ s_time tmp = {0};
+ if ((r = buf_read_1(buf, "%Time{")) <= 0)
+ goto clean;
+ result += r;
+ if ((r = buf_parse_comments(buf)) < 0)
+ goto restore;
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) < 0)
+ goto restore;
+ result += r;
+ if ((r = buf_read_1(buf, "}")) < 0)
+ goto restore;
+ if (r > 0) {
+ result += r;
+ *dest = tmp;
+ return result;
+ }
+}
+
sw buf_parse_tuple (s_buf *buf, s_tuple *tuple)
{
s_list **i;
diff --git a/libkc3/buf_parse.h b/libkc3/buf_parse.h
index 1b55cfb..a380eb5 100644
--- a/libkc3/buf_parse.h
+++ b/libkc3/buf_parse.h
@@ -133,10 +133,12 @@ sw buf_parse_tag_special_operator (s_buf *buf, s_tag *dest);
sw buf_parse_tag_str (s_buf *buf, s_tag *dest);
sw buf_parse_tag_struct (s_buf *buf, s_tag *dest);
sw buf_parse_tag_sym (s_buf *buf, s_tag *dest);
+sw buf_parse_tag_time (s_buf *buf, s_tag *dest);
sw buf_parse_tag_tuple (s_buf *buf, s_tag *dest);
sw buf_parse_tag_unquote (s_buf *buf, s_tag *dest);
sw buf_parse_tag_var (s_buf *buf, s_tag *dest);
sw buf_parse_tag_void (s_buf *buf, s_tag *dest);
+sw buf_parse_time (s_buf *buf, s_time *dest);
sw buf_parse_tuple (s_buf *buf, s_tuple *dest);
sw buf_parse_u64_hex (s_buf *buf, u64 *dest);
sw buf_parse_unquote (s_buf *buf, s_unquote *dest);
diff --git a/libkc3/env.c b/libkc3/env.c
index ff0ac71..9269c4e 100644
--- a/libkc3/env.c
+++ b/libkc3/env.c
@@ -1102,6 +1102,10 @@ bool env_eval_equal_tag (s_env *env, bool macro, const s_tag *a,
return env_eval_equal_struct(env, macro, &a->data.struct_,
&b->data.struct_, &dest->data.struct_);
*/
+ case TAG_TIME:
+ dest->type = TAG_TIME;
+ return env_eval_equal_time(env, macro, &a->data.time,
+ &b->data.time, &dest->data.time);
case TAG_TUPLE:
dest->type = TAG_TUPLE;
return env_eval_equal_tuple(env, macro, &a->data.tuple,
@@ -1154,6 +1158,71 @@ bool env_eval_equal_tag (s_env *env, bool macro, const s_tag *a,
return false;
}
+bool env_eval_equal_time (s_env *env, bool macro, const s_time *a,
+ const s_time *b, s_time *dest)
+{
+ s_tag *a2;
+ s_tag a_tag[2] = {0};
+ s_tag *b2;
+ s_tag b_tag[2] = {0};
+ s_time tmp = {0};
+ s_tag tmp_tag[2] = {0};
+ assert(env);
+ assert(a);
+ assert(b);
+ assert(dest);
+ if (! (a2 = a->tag)) {
+ a2 = a_tag;
+ a2[0].type = TAG_SW;
+ a2[0].data.sw = a->tv_sec;
+ a2[1].type = TAG_SW;
+ a2[1].data.sw = a->tv_nsec;
+ }
+ if (! (b2 = b->tag)) {
+ b2 = b_tag;
+ b2[0].type = TAG_SW;
+ b2[0].data.sw = b->tv_sec;
+ b2[1].type = TAG_SW;
+ b2[1].data.sw = b->tv_nsec;
+ }
+ if (a->tag || b->tag)
+ tmp.tag = alloc(2 * sizeof(s_tag));
+ else
+ tmp.tag = tmp_tag;
+ if (! env_eval_equal_tag(env, macro, a2, b2, tmp.tag)) {
+ free(tmp.tag);
+ return false;
+ }
+ if (! env_eval_equal_tag(env, macro, a2 + 1, b2 + 1, tmp.tag + 1)) {
+ tag_clean(tmp.tag);
+ free(tmp.tag);
+ return false;
+ }
+ if (! (a->tag || b->tag)) {
+ if (tmp_tag[0].type != TAG_SW) {
+ err_puts("env_eval_equal_time: tv_sec is not a Sw");
+ assert(! "env_eval_equal_time: tv_sec is not a Sw");
+ tag_clean(tmp.tag + 1);
+ tag_clean(tmp.tag);
+ free(tmp.tag);
+ return false;
+ }
+ tmp.tv_sec = tmp_tag[0].data.sw;
+ if (tmp_tag[1].type != TAG_SW) {
+ err_puts("env_eval_equal_time: tv_nsec is not a Sw");
+ assert(! "env_eval_equal_time: tv_nsec is not a Sw");
+ tag_clean(tmp.tag + 1);
+ tag_clean(tmp.tag);
+ free(tmp.tag);
+ return false;
+ }
+ tmp.tv_nsec = tmp_tag[1].data.sw;
+ tmp.tag = NULL;
+ }
+ *dest = tmp;
+ return true;
+}
+
bool env_eval_equal_tuple (s_env *env, bool macro, const s_tuple *a,
const s_tuple *b, s_tuple *dest)
{
@@ -1561,6 +1630,8 @@ bool env_eval_quote_tag (s_env *env, const s_tag *tag, s_tag *dest)
return env_eval_quote_quote(env, &tag->data.quote, dest);
case TAG_STRUCT:
return env_eval_quote_struct(env, &tag->data.struct_, dest);
+ case TAG_TIME:
+ return env_eval_quote_time(env, &tag->data.time, dest);
case TAG_TUPLE:
return env_eval_quote_tuple(env, &tag->data.tuple, dest);
case TAG_UNQUOTE:
@@ -1603,6 +1674,38 @@ bool env_eval_quote_tag (s_env *env, const s_tag *tag, s_tag *dest)
return false;
}
+bool env_eval_quote_time (s_env *env, const s_time *time, s_tag *dest)
+{
+ s_time tmp = {0};
+ assert(env);
+ assert(time);
+ assert(dest);
+ if (time->tag) {
+ tmp.tag = alloc(2 * sizeof(s_tag));
+ if (! env_eval_quote_tag(env, time->tag, tmp.tag)) {
+ err_puts("env_eval_quote_time: env_eval_quote_tag: tv_sec");
+ assert(! "env_eval_quote_time: env_eval_quote_tag: tv_sec");
+ free(tmp.tag);
+ return false;
+ }
+ if (! env_eval_quote_tag(env, time->tag + 1, tmp.tag + 1)) {
+ err_puts("env_eval_quote_time: env_eval_quote_tag: tv_nsec");
+ assert(! "env_eval_quote_time: env_eval_quote_tag: tv_nsec");
+ tag_clean(tmp.tag);
+ free(tmp.tag);
+ return false;
+ }
+ dest->type = TAG_TIME;
+ dest->data.time = tmp;
+ return true;
+ }
+ tmp.tv_sec = time->tv_sec;
+ tmp.tv_nsec = time->tv_nsec;
+ dest->type = TAG_TIME;
+ dest->data.time = tmp;
+ return true;
+}
+
bool env_eval_quote_tuple (s_env *env, const s_tuple *tuple, s_tag *dest)
{
uw i = 0;
@@ -1760,6 +1863,8 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
return env_eval_quote(env, &tag->data.quote, dest);
case TAG_STRUCT:
return env_eval_struct(env, &tag->data.struct_, dest);
+ case TAG_TIME:
+ return env_eval_time(env, &tag->data.time, dest);
case TAG_TUPLE:
return env_eval_tuple(env, &tag->data.tuple, dest);
case TAG_BOOL:
@@ -1797,6 +1902,43 @@ bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest)
return false;
}
+bool env_eval_time (s_env *env, const s_time *time, s_tag *dest)
+{
+ s_tag tag[2] = {0};
+ s_tag tmp = {0};
+ tmp.type = TAG_TIME;
+ if (time->tag) {
+ if (! env_eval_tag(env, time->tag, tag))
+ return false;
+ if (! env_eval_tag(env, time->tag + 1, tag + 1)) {
+ tag_clean(tag);
+ return false;
+ }
+ if (tag[0].type != TAG_SW) {
+ err_write_1("env_eval_time: tv_sec is not a Sw: ");
+ err_inspect_tag(tag);
+ err_write_1("\n");
+ assert(! "env_eval_time: tv_sec is not a Sw");
+ tag_clean(tag + 1);
+ tag_clean(tag);
+ return false;
+ }
+ if (tag[1].type != TAG_SW) {
+ err_write_1("env_eval_time: tv_nsec is not a Sw: ");
+ err_inspect_tag(tag + 1);
+ err_write_1("\n");
+ assert(! "env_eval_time: tv_nsec is not a Sw");
+ tag_clean(tag + 1);
+ tag_clean(tag);
+ return false;
+ }
+ tmp.data.time.tv_sec = tag[0].data.sw;
+ tmp.data.time.tv_nsec = tag[1].data.sw;
+ }
+ *dest = tmp;
+ return true;
+}
+
bool env_eval_tuple (s_env *env, const s_tuple *tuple, s_tag *dest)
{
uw i = 0;
diff --git a/libkc3/env.h b/libkc3/env.h
index cb7a821..d6a0e90 100644
--- a/libkc3/env.h
+++ b/libkc3/env.h
@@ -89,6 +89,9 @@ bool env_eval_equal_struct (s_env *env, bool macro,
bool env_eval_equal_tag (s_env *env, bool macro,
const s_tag *a, const s_tag *b,
s_tag *dest);
+bool env_eval_equal_time (s_env *env, bool macro,
+ const s_time *a, const s_time *b,
+ s_time *dest);
bool env_eval_equal_tuple (s_env *env, bool macro,
const s_tuple *a, const s_tuple *b,
s_tuple *dest);
@@ -156,6 +159,8 @@ bool env_eval_quote_struct (s_env *env, const s_struct *s,
s_tag *dest);
bool env_eval_quote_tag (s_env *env, const s_tag *tag,
s_tag *dest);
+bool env_eval_quote_time (s_env *env, const s_time *time,
+ s_tag *dest);
bool env_eval_quote_tuple (s_env *env, const s_tuple *tuple,
s_tag *dest);
bool env_eval_quote_unquote (s_env *env,
@@ -165,6 +170,8 @@ bool env_eval_struct (s_env *env, const s_struct *s,
s_tag *dest);
bool env_eval_tag (s_env *env, const s_tag *tag,
s_tag *dest);
+bool env_eval_time (s_env *env, const s_time *time,
+ s_tag *dest);
bool env_eval_tuple (s_env *env, const s_tuple *tuple,
s_tag *dest);
bool env_eval_void (s_env *env, const void *_, s_tag *dest);
diff --git a/libkc3/hash.c b/libkc3/hash.c
index 507e596..cd51cec 100644
--- a/libkc3/hash.c
+++ b/libkc3/hash.c
@@ -505,6 +505,7 @@ bool hash_update_tag (t_hash *hash, const s_tag *tag)
case TAG_STRUCT_TYPE:
return hash_update_struct_type(hash, &tag->data.struct_type);
case TAG_SYM: return hash_update_sym(hash, &tag->data.sym);
+ case TAG_TIME: return hash_update_time(hash, &tag->data.time);
case TAG_TUPLE: return hash_update_tuple(hash, &tag->data.tuple);
case TAG_U8: return hash_update_u8(hash, &tag->data.u8);
case TAG_U16: return hash_update_u16(hash, &tag->data.u16);
@@ -521,6 +522,28 @@ bool hash_update_tag (t_hash *hash, const s_tag *tag)
return false;
}
+bool hash_update_time (t_hash *hash, const s_time *time)
+{
+ bool b;
+ char type[] = "time";
+ assert(time);
+ assert(hash);
+ b = time->tag ? true : false;
+ if (! hash_update(hash, type, sizeof(type)) ||
+ ! hash_update_bool(hash, &b))
+ return false;
+ if (time->tag) {
+ if (! hash_update_tag(hash, time->tag) ||
+ ! hash_update_tag(hash, time->tag + 1))
+ return false;
+ return true;
+ }
+ if (! hash_update_sw(hash, &time->tv_sec) ||
+ ! hash_update_sw(hash, &time->tv_nsec))
+ return false;
+ return true;
+}
+
bool hash_update_tuple (t_hash *hash, const s_tuple *tuple)
{
uw i = 0;
diff --git a/libkc3/hash.h b/libkc3/hash.h
index 13c7ca4..cbf6d40 100644
--- a/libkc3/hash.h
+++ b/libkc3/hash.h
@@ -57,6 +57,7 @@ bool hash_update_struct (t_hash *hash, const s_struct *s);
bool hash_update_struct_type (t_hash *hash, const s_struct_type *st);
bool hash_update_sym (t_hash *hash, const s_sym * const *sym);
bool hash_update_tag (t_hash *hash, const s_tag *tag);
+bool hash_update_time (t_hash *hash, const s_time *time);
bool hash_update_tuple (t_hash *hash, const s_tuple *tuple);
HASH_UPDATE_PROTOTYPE(u8);
HASH_UPDATE_PROTOTYPE(u16);
diff --git a/libkc3/sym.c b/libkc3/sym.c
index 6d1c4ea..a44f71f 100644
--- a/libkc3/sym.c
+++ b/libkc3/sym.c
@@ -995,6 +995,10 @@ bool sym_to_tag_type (const s_sym *sym, e_tag_type *dest)
*dest = TAG_VOID;
return true;
}
+ if (sym == &g_sym_Time) {
+ *dest = TAG_TIME;
+ return true;
+ }
if (sym == &g_sym_Tuple) {
*dest = TAG_TUPLE;
return true;
@@ -1168,6 +1172,10 @@ uw * sym_type_size (const s_sym * const *type, uw *dest)
*dest = sizeof(s_tag);
return dest;
}
+ if (*type == &g_sym_Time) {
+ *dest = sizeof(s_time);
+ return dest;
+ }
if (*type == &g_sym_Tuple) {
*dest = sizeof(s_tuple);
return dest;
diff --git a/libkc3/tag.c b/libkc3/tag.c
index 9b714da..5709f45 100644
--- a/libkc3/tag.c
+++ b/libkc3/tag.c
@@ -171,6 +171,7 @@ void tag_clean (s_tag *tag)
case TAG_STRUCT: struct_clean(&tag->data.struct_); break;
case TAG_STRUCT_TYPE: struct_type_clean(&tag->data.struct_type);
break;
+ case TAG_TIME: time_clean(&tag->data.time); break;
case TAG_TUPLE: tuple_clean(&tag->data.tuple); break;
case TAG_UNQUOTE: unquote_clean(&tag->data.unquote); break;
case TAG_BOOL:
@@ -488,6 +489,11 @@ s_tag * tag_init_copy (s_tag *tag, const s_tag *src)
tag->type = src->type;
tag->data.sym = src->data.sym;
return tag;
+ case TAG_TIME:
+ tag->type = src->type;
+ if (! time_init_copy(&tag->data.time, &src->data.time))
+ return NULL;
+ return tag;
case TAG_TUPLE:
tag->type = src->type;
if (! tuple_init_copy(&tag->data.tuple, &src->data.tuple))
@@ -731,6 +737,7 @@ bool tag_is_number (const s_tag *tag)
case TAG_STRUCT:
case TAG_STRUCT_TYPE:
case TAG_SYM:
+ case TAG_TIME:
case TAG_TUPLE:
case TAG_UNQUOTE:
case TAG_VAR:
@@ -1021,6 +1028,7 @@ bool tag_to_const_pointer (const s_tag *tag, const s_sym *type,
return false;
case TAG_STRUCT_TYPE: *dest = &tag->data.struct_type; return true;
case TAG_SYM: *dest = &tag->data.sym; return true;
+ case TAG_TIME: *dest = &tag->data.time; return true;
case TAG_TUPLE: *dest = &tag->data.tuple; return true;
case TAG_UNQUOTE: *dest = &tag->data.unquote; return true;
case TAG_VAR: *dest = tag; return true;
@@ -1246,6 +1254,12 @@ bool tag_to_ffi_pointer (s_tag *tag, const s_sym *type, void **dest)
return true;
}
goto invalid_cast;
+ case TAG_TIME:
+ if (type == &g_sym_Time) {
+ *dest = &tag->data.time;
+ return true;
+ }
+ goto invalid_cast;
case TAG_TUPLE:
if (type == &g_sym_Tuple) {
*dest = &tag->data.tuple;
@@ -1372,6 +1386,7 @@ bool tag_to_pointer (s_tag *tag, const s_sym *type, void **dest)
goto invalid_cast;
case TAG_STRUCT_TYPE: *dest = &tag->data.struct_type; return true;
case TAG_SYM: *dest = &tag->data.sym; return true;
+ case TAG_TIME: *dest = &tag->data.time; return true;
case TAG_TUPLE: *dest = &tag->data.tuple; return true;
case TAG_UNQUOTE: *dest = &tag->data.unquote; return true;
case TAG_VAR: *dest = tag; return true;
@@ -1438,6 +1453,7 @@ const s_sym ** tag_type (const s_tag *tag, const s_sym **dest)
return dest;
case TAG_STRUCT_TYPE: *dest = &g_sym_StructType; return dest;
case TAG_SYM: *dest = &g_sym_Sym; return dest;
+ case TAG_TIME: *dest = &g_sym_Time; return dest;
case TAG_TUPLE: *dest = &g_sym_Tuple; return dest;
case TAG_UNQUOTE: *dest = &g_sym_Unquote; return dest;
case TAG_VAR: *dest = &g_sym_Var; return dest;
diff --git a/libkc3/tag_type.c b/libkc3/tag_type.c
index f20a1ec..681e075 100644
--- a/libkc3/tag_type.c
+++ b/libkc3/tag_type.c
@@ -57,6 +57,7 @@ bool tag_type_size (e_tag_type type, uw *dest)
case TAG_STRUCT: *dest = sizeof(s_struct); return true;
case TAG_STRUCT_TYPE: *dest = sizeof(s_struct_type); return true;
case TAG_SYM: *dest = sizeof(s_sym *); return true;
+ case TAG_TIME: *dest = sizeof(s_time); return true;
case TAG_TUPLE: *dest = sizeof(s_tuple); return true;
case TAG_UNQUOTE: *dest = sizeof(s_unquote); return true;
case TAG_VAR: *dest = sizeof(s_tag); return true;
@@ -100,6 +101,7 @@ bool tag_type_to_ffi_type (e_tag_type type, ffi_type **dest)
case TAG_STRUCT: *dest = &ffi_type_pointer; return true;
case TAG_STRUCT_TYPE: *dest = &ffi_type_pointer; return true;
case TAG_SYM: *dest = &ffi_type_pointer; return true;
+ case TAG_TIME : *dest = &ffi_type_pointer; return true;
case TAG_TUPLE: *dest = &ffi_type_pointer; return true;
case TAG_U8: *dest = &ffi_type_uint8; return true;
case TAG_U16: *dest = &ffi_type_uint16; return true;
@@ -155,6 +157,7 @@ const char * tag_type_to_string (e_tag_type tag_type)
case TAG_STRUCT: return "Struct";
case TAG_STRUCT_TYPE: return "StructType";
case TAG_SYM: return "Sym";
+ case TAG_TIME: return "Time";
case TAG_TUPLE: return "Tuple";
case TAG_UNQUOTE: return "Unquote";
case TAG_VAR: return "Var";
diff --git a/libkc3/time.c b/libkc3/time.c
index 79293dd..8ca4d68 100644
--- a/libkc3/time.c
+++ b/libkc3/time.c
@@ -10,10 +10,58 @@
* AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
* THIS SOFTWARE.
*/
-#include <assert.h>
+#include <stdlib.h>
+#include "alloc.h"
+#include "assert.h"
#include "tag.h"
#include "time.h"
+void time_clean (s_time *time)
+{
+ if (time->tag) {
+ tag_clean(time->tag);
+ tag_clean(time->tag + 1);
+ free(time->tag);
+ }
+}
+
+s_time * time_init (s_time *time, bool allocate)
+{
+ s_time tmp = {0};
+ if (allocate) {
+ tmp.tag = alloc(2 * sizeof(s_tag));
+ if (! tmp.tag)
+ return NULL;
+ }
+ *time = tmp;
+ return time;
+}
+
+s_time * time_init_copy (s_time *time, const s_time *src)
+{
+ s_time tmp = {0};
+ if (src->tag) {
+ tmp.tag = alloc(2 * sizeof(s_tag));
+ if (! tmp.tag)
+ return NULL;
+ if (! tag_init_copy(tmp.tag, src->tag)) {
+ free(tmp.tag);
+ return NULL;
+ }
+ if (! tag_init_copy(tmp.tag + 1, src->tag + 1)) {
+ tag_clean(tmp.tag);
+ free(tmp.tag);
+ return NULL;
+ }
+ *time = tmp;
+ return time;
+ }
+ tmp.tv_sec = src->tv_sec;
+ tmp.tv_nsec = src->tv_nsec;
+ *time = tmp;
+ return time;
+}
+
s_timespec * time_sub (const s_timespec *a, const s_timespec *b, s_timespec *dest)
{
if ((a->tv_nsec - b->tv_nsec) < 0) {
diff --git a/libkc3/time.h b/libkc3/time.h
index 3318471..08ab498 100644
--- a/libkc3/time.h
+++ b/libkc3/time.h
@@ -20,6 +20,12 @@
#include "types.h"
+/* Stack-allocation compatible functions. Call time_clean if
+ time_init argument allocate was true. */
+void time_clean (s_time *time);
+s_time * time_init (s_time *time, bool allocate);
+s_time * time_init_copy (s_time *time, const s_time *src);
+
/* Observers */
f64 * time_to_f64 (const s_timespec *time, f64 *dest);
s_tag * time_to_tag (const s_timespec *time, s_tag *dest);
diff --git a/libkc3/types.h b/libkc3/types.h
index b74b14b..b3f87f6 100644
--- a/libkc3/types.h
+++ b/libkc3/types.h
@@ -322,9 +322,9 @@ struct tag_type_list {
};
struct time {
- s_tag *tag;
sw tv_sec;
sw tv_nsec;
+ s_tag *tag;
};
struct tuple {