diff --git a/README.md b/README.md
index 83dfd47..376f3db 100644
--- a/README.md
+++ b/README.md
@@ -297,8 +297,9 @@ Script interpreter. Works the same as ic3 but is not interactive.
- negative facts : 4 + 2n = not 3 + 2n
- with ignore variables
- math
- - fractions
+ - ratios
- floating point numbers (decimals)
+ - floating point numbers (ieee854)
- maps
- get (get key value)
- put (return a new map)
diff --git a/libc3/buf.c b/libc3/buf.c
index 3b02fe6..96527d5 100644
--- a/libc3/buf.c
+++ b/libc3/buf.c
@@ -829,6 +829,7 @@ sw buf_refill_compact (s_buf *buf)
s_str * buf_slice_to_str (const s_buf *buf, uw start, uw end,
s_str *dest)
{
+ s_str tmp;
assert(buf);
assert(dest);
if (start > buf->wpos) {
@@ -846,7 +847,8 @@ s_str * buf_slice_to_str (const s_buf *buf, uw start, uw end,
assert(! "buf_slice_to_str: end > wpos");
return NULL;
}
- return str_init(dest, NULL, end - start, buf->ptr.ps8 + start);
+ str_init(&tmp, NULL, end - start, buf->ptr.pchar + start);
+ return str_init_copy(dest, &tmp);
}
sw buf_str_to_hex (s_buf *buf, const s_str *src)
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index c95772c..cef3618 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -2566,21 +2566,24 @@ sw buf_parse_str_eval (s_buf *buf, s_tag *dest)
uw end;
s_str in;
s_buf in_buf = {0};
- s_list *list;
+ s_list *list;
s_list **list_end;
+ s_list *list_start;
s_buf out_buf;
sw r;
sw result;
s_buf_save save;
uw start;
+ s_tag tmp;
+ s_tag tmp1;
buf_save_init(buf, &save);
r = buf_parse_str(buf, &in);
if (r <= 0)
goto clean;
result = r;
buf_init_str(&in_buf, false, &in);
- list = NULL;
- list_end = &list;
+ list_start = NULL;
+ list_end = &list_start;
start = 0;
while (1) {
end = in_buf.rpos;
@@ -2588,10 +2591,12 @@ sw buf_parse_str_eval (s_buf *buf, s_tag *dest)
if (r < 0)
goto restore;
if (r > 0) {
- *list_end = list_new(NULL);
- (*list_end)->tag.type = TAG_STR;
- buf_slice_to_str(&in_buf, start, end, &(*list_end)->tag.data.str);
- list_end = &(*list_end)->next.data.list;
+ if (end > 0) {
+ *list_end = list_new(NULL);
+ (*list_end)->tag.type = TAG_STR;
+ buf_slice_to_str(&in_buf, start, end, &(*list_end)->tag.data.str);
+ list_end = &(*list_end)->next.data.list;
+ }
*list_end = list_new(NULL);
buf_parse_tag(&out_buf, &(*list_end)->tag);
list_end = &(*list_end)->next.data.list;
@@ -2605,14 +2610,35 @@ sw buf_parse_str_eval (s_buf *buf, s_tag *dest)
if (r <= 0)
goto restore;
start = in_buf.rpos;
+ continue;
}
r = buf_read_character_utf8(&in_buf, &c);
+ if (r < 0)
+ goto restore;
+ if (! r)
+ break;
}
+ if (! list_start)
+ tag_init_str_empty(&tmp);
+ else {
+ list = list_start;
+ if (list->tag.type == TAG_STR) {
+ tmp = list->tag;
+ }
+ while (list) {
+ if (list->tag.type == TAG_STR)
+
r = result;
goto clean;
restore:
buf_save_restore_rpos(buf, &save);
clean:
+ while (list_start) {
+ list = list_next(list_start);
+ free(list_start);
+ list_start = list;
+ }
+ str_clean(&in);
buf_save_clean(buf, &save);
return r;
}
diff --git a/libc3/list_init.c b/libc3/list_init.c
index 3d18caa..d3b52aa 100644
--- a/libc3/list_init.c
+++ b/libc3/list_init.c
@@ -298,6 +298,17 @@ s_list * list_init_str_cat (s_list *list, const s_str *a,
return list;
}
+s_list * list_init_str_empty (s_list *list, s_list *next)
+{
+ s_list tmp;
+ assert(list);
+ list_init(&tmp, next);
+ if (! tag_init_str_empty(&tmp.tag))
+ return NULL;
+ *list = tmp;
+ return list;
+}
+
s_list * list_init_struct (s_list *list, const s_sym *module,
s_list *next)
{
@@ -746,6 +757,19 @@ s_list * list_new_str_cat (const s_str *a, const s_str *b, s_list *next)
return list;
}
+s_list * list_new_str_empty (s_list *next)
+{
+ s_list *list;
+ list = list_new(next);
+ if (! list)
+ return NULL;
+ if (! tag_init_str_empty(&list->tag)) {
+ free(list);
+ return NULL;
+ }
+ return list;
+}
+
s_list * list_new_struct (const s_sym *module, s_list *next)
{
s_list *list;
diff --git a/libc3/list_init.h b/libc3/list_init.h
index 418120b..9a2b0fe 100644
--- a/libc3/list_init.h
+++ b/libc3/list_init.h
@@ -49,6 +49,7 @@ s_list * list_init_str_1 (s_list *list, char *p_free, const char *p,
s_list *next);
s_list * list_init_str_cat (s_list *list, const s_str *a,
const s_str *b, s_list *next);
+s_list * list_init_str_empty (s_list *list, s_list *next);
s_list * list_init_struct (s_list *list, const s_sym *module,
s_list *next);
s_list * list_init_struct_with_data (s_list *list, const s_sym *module,
@@ -97,6 +98,7 @@ s_list * list_new_str (char *p_free, uw size, const char *p,
s_list * list_new_str_1 (char *p_free, const char *p, s_list *next);
s_list * list_new_str_cat (const s_str *a, const s_str *b,
s_list *next);
+s_list * list_new_str_empty (s_list *next);
s_list * list_new_struct (const s_sym *module, s_list *next);
s_list * list_new_struct_with_data (const s_sym *module,
bool free_data, void *data,
@@ -142,6 +144,7 @@ s_list * list_s64 (s_list *list, s64 i);
s_list * list_str (s_list *list, char *p_free, uw size, const char *p);
s_list * list_str_1 (s_list *list, char *p_free, const char *p);
s_list * list_str_cat (s_list *list, const s_str *a, const s_str *b);
+s_list * list_str_empty (s_list *list);
s_list * list_struct (s_list *list, const s_sym *module);
s_list * list_struct_with_data (s_list *list, const s_sym *module,
bool free_data, void *data);
diff --git a/libc3/tag_init.c b/libc3/tag_init.c
index d12c67b..acba8d6 100644
--- a/libc3/tag_init.c
+++ b/libc3/tag_init.c
@@ -292,6 +292,17 @@ s_tag * tag_init_str_cat (s_tag *tag, const s_str *a, const s_str *b)
return tag;
}
+s_tag * tag_init_str_empty (s_tag *tag)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tmp.type = TAG_STR;
+ if (! str_init_empty(&tmp.data.str))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_init_struct (s_tag *tag, const s_sym *module)
{
s_tag tmp = {0};
@@ -754,6 +765,21 @@ s_tag * tag_new_str_cat (const s_str *a, const s_str *b)
return tag;
}
+s_tag * tag_new_str_empty (void)
+{
+ s_tag *tag;
+ if (! (tag = calloc(1, sizeof(s_tag)))) {
+ warn("tag_new_str_empty: calloc");
+ return NULL;
+ }
+ tag->type = TAG_STR;
+ if (! str_init_empty(&tag->data.str)) {
+ free(tag);
+ return NULL;
+ }
+ return tag;
+}
+
s_tag * tag_new_struct (const s_sym *module)
{
s_tag *tag;
@@ -1200,6 +1226,18 @@ s_tag * tag_str_cat (s_tag *tag, const s_str *a, const s_str *b)
return tag;
}
+s_tag * tag_str_empty (s_tag *tag)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tag_clean(tag);
+ tmp.type = TAG_STR;
+ if (! str_init_empty(&tmp.data.str))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_struct (s_tag *tag, const s_sym *module)
{
s_tag tmp = {0};
diff --git a/libc3/tag_init.h b/libc3/tag_init.h
index e4662af..652d230 100644
--- a/libc3/tag_init.h
+++ b/libc3/tag_init.h
@@ -42,6 +42,7 @@ s_tag * tag_init_s64 (s_tag *tag, s64 i);
s_tag * tag_init_str (s_tag *tag, char *p_free, uw size, const char *p);
s_tag * tag_init_str_1 (s_tag *tag, char *p_free, const char *p);
s_tag * tag_init_str_cat (s_tag *tag, const s_str *a, const s_str *b);
+s_tag * tag_init_str_empty (s_tag *tag);
s_tag * tag_init_struct (s_tag *tag, const s_sym *module);
s_tag * tag_init_struct_with_data (s_tag *tag, const s_sym *module,
bool free_data, void *data);
@@ -85,6 +86,7 @@ s_tag * tag_new_s64 (s64 i);
s_tag * tag_new_str (char *p_free, uw size, const char *p);
s_tag * tag_new_str_1 (char *p_free, const char *p);
s_tag * tag_new_str_cat (const s_str *a, const s_str *b);
+s_tag * tag_new_str_empty (void);
s_tag * tag_new_struct (const s_sym *module);
s_tag * tag_new_struct_with_data (const s_sym *module, bool free_data,
void *data);
@@ -128,6 +130,7 @@ s_tag * tag_s64 (s_tag *tag, s64 i);
s_tag * tag_str (s_tag *tag, char *p_free, uw size, const char *p);
s_tag * tag_str_1 (s_tag *tag, char *p_free, const char *p);
s_tag * tag_str_cat (s_tag *tag, const s_str *a, const s_str *b);
+s_tag * tag_str_empty (s_tag *tag);
s_tag * tag_struct (s_tag *tag, const s_sym *module);
s_tag * tag_struct_with_data (s_tag *tag, const s_sym *module,
bool free_data, void *data);
diff --git a/libc3/tag_init.rb b/libc3/tag_init.rb
index a37224c..a5372c7 100644
--- a/libc3/tag_init.rb
+++ b/libc3/tag_init.rb
@@ -356,6 +356,7 @@ class TagInitList
TagInit.new("str", "cat", "TAG_STR", :init_mode_init,
[Arg.new("const s_str *", "a"),
Arg.new("const s_str *", "b")]),
+ TagInit.new("str", "empty", "TAG_STR", :init_mode_init, []),
TagInit.new("struct", "TAG_STRUCT", :init_mode_init,
[Arg.new("const s_sym *", "module")]),
TagInit.new("struct", "with_data", "TAG_STRUCT", :init_mode_init,