diff --git a/.ikc3_history b/.ikc3_history
index 9126fd6..4081fd6 100644
--- a/.ikc3_history
+++ b/.ikc3_history
@@ -1,4 +1,3 @@
-(Ptr) 0xf24fc9ce000
(Tag) (Ptr) 0xf24fc9ce000
?
Facts.with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { puts(fact.object); 1 })
@@ -97,3 +96,4 @@ a = ?
b = ?
a = ? ; void
Facts.with_tags(Facts.env_facts(), KC3, :operator, ?, fn (fact) { puts(fact.object); 1 })
+EKC3.html_escape("plop <1>")
diff --git a/ekc3/ekc3.h b/ekc3/ekc3.h
index 35f1375..a0cd749 100644
--- a/ekc3/ekc3.h
+++ b/ekc3/ekc3.h
@@ -16,7 +16,7 @@
#include "types.h"
/* Stack-allocation compatible functions, call ekc3_clean after use. */
-void ekc3_clean (p_ekc3 *ekc3);
+void ekc3_clean (p_ekc3 *ekc3);
p_ekc3 * ekc3_init (p_ekc3 *ekc3);
/* Operators. */
@@ -31,10 +31,11 @@ sw ekc3_buf_parse_kc3_silent_block (s_buf *buf, s_block *dest);
sw ekc3_buf_peek_kc3_silent_block (s_buf *buf);
/* Observers. */
-sw ekc3_render (const p_ekc3 *ekc3);
-sw ekc3_render_block_to_str (const s_block *block, s_str *dest);
-sw ekc3_render_buf (s_buf *in);
-sw ekc3_render_file (const s_str *path);
-sw ekc3_render_tag (const s_tag *tag);
+s_str * ekc3_escape_html (const s_str *html, s_str *dest);
+sw ekc3_render (const p_ekc3 *ekc3);
+sw ekc3_render_block_to_str (const s_block *block, s_str *dest);
+sw ekc3_render_buf (s_buf *in);
+sw ekc3_render_file (const s_str *path);
+sw ekc3_render_tag (const s_tag *tag);
#endif /* EKC3_H */
diff --git a/ekc3/html.c b/ekc3/html.c
index b0391d5..3421352 100644
--- a/ekc3/html.c
+++ b/ekc3/html.c
@@ -27,7 +27,7 @@ s_str * html_escape (const s_str *str, s_str *dest)
s_tag tag;
assert(str);
assert(dest);
- ident_init(&escape_ident, sym_1("EKC3"), sym_1("html_escape"));
+ ident_init(&escape_ident, sym_1("HTML"), sym_1("escapes"));
if (! ident_get(&escape_ident, &escape_tag)) {
err_puts("html_escape: ident_get");
assert(! "html_escape: ident_get");
diff --git a/lib/kc3/0.1/ekc3.kc3 b/lib/kc3/0.1/ekc3.kc3
index feafe48..5e69e2e 100644
--- a/lib/kc3/0.1/ekc3.kc3
+++ b/lib/kc3/0.1/ekc3.kc3
@@ -2,12 +2,6 @@ defmodule EKC3 do
dlopen(__DIR__ + "ekc3.so")
- def html_escape = [{"&", "&"},
- {"<", "<"},
- {">", ">"},
- {"\"", """},
- {"'", "'"}]
-
- def render_file = cfn Str "ekc3_render_file" (Str)
+ def render_file = cfn Sw "ekc3_render_file" (Str)
end
diff --git a/lib/kc3/0.1/html.kc3 b/lib/kc3/0.1/html.kc3
new file mode 100644
index 0000000..1b94724
--- /dev/null
+++ b/lib/kc3/0.1/html.kc3
@@ -0,0 +1,13 @@
+defmodule HTML do
+
+ dlopen(__DIR__ + "ekc3.so")
+
+ def escape = cfn Str "html_escape" (Str, Result)
+
+ def escapes = [{"&", "&"},
+ {"<", "<"},
+ {">", ">"},
+ {"\"", """},
+ {"'", "'"}]
+
+end
diff --git a/lib/kc3/0.1/markdown.kc3 b/lib/kc3/0.1/markdown.kc3
index e2f004c..d88a658 100644
--- a/lib/kc3/0.1/markdown.kc3
+++ b/lib/kc3/0.1/markdown.kc3
@@ -2,6 +2,8 @@ defmodule Markdown do
dlopen(__DIR__ + "markdown.so")
+ def titles = cfn List "markdown_titles" (Str, Result)
+
def to_html_str = cfn Str "markdown_to_html_str" (Str, Result)
end
diff --git a/libkc3/list.c b/libkc3/list.c
index 75a10a3..5752aa4 100644
--- a/libkc3/list.c
+++ b/libkc3/list.c
@@ -286,6 +286,16 @@ s_list ** list_remove_void (s_list **list)
return list;
}
+s_list ** list_tail (s_list **list)
+{
+ s_list **tail;
+ tail = list;
+ while (tail && *tail) {
+ tail = &(*tail)->next.data.list;
+ }
+ return tail;
+}
+
s_array * list_to_array (const s_list *list, const s_sym *array_type,
s_array *dest)
{
diff --git a/libkc3/list.h b/libkc3/list.h
index 25394d4..f18d7dc 100644
--- a/libkc3/list.h
+++ b/libkc3/list.h
@@ -54,6 +54,7 @@ bool list_is_alist (const s_list * const *list);
bool list_is_plist (const s_list *list);
sw list_length (const s_list *list);
s_list * list_next (const s_list *list);
+s_list ** list_tail (s_list **list);
s_array * list_to_array (const s_list *list, const s_sym *type,
s_array *dest);
s_tuple * list_to_tuple_reverse (const s_list *list, s_tuple *dest);
diff --git a/libkc3/list_init.c b/libkc3/list_init.c
index b84a6e1..a8c241b 100644
--- a/libkc3/list_init.c
+++ b/libkc3/list_init.c
@@ -413,6 +413,18 @@ s_list * list_init_str_alloc_copy (s_list *list, uw size,
return list;
}
+s_list * list_init_str_cast (s_list *list, const s_sym * const *type,
+ const s_tag *src, s_list *next)
+{
+ s_list tmp = {0};
+ assert(list);
+ list_init(&tmp, next);
+ if (! tag_init_str_cast(&tmp.tag, type, src))
+ return NULL;
+ *list = tmp;
+ return list;
+}
+
s_list * list_init_str_concatenate (s_list *list, const s_str *a,
const s_str *b, s_list *next)
{
@@ -426,7 +438,7 @@ s_list * list_init_str_concatenate (s_list *list, const s_str *a,
}
s_list * list_init_str_concatenate_list (s_list *list,
- const s_list **src,
+ const s_list * const *src,
s_list *next)
{
s_list tmp = {0};
@@ -438,6 +450,18 @@ s_list * list_init_str_concatenate_list (s_list *list,
return list;
}
+s_list * list_init_str_copy (s_list *list, const s_str *src,
+ s_list *next)
+{
+ s_list tmp = {0};
+ assert(list);
+ list_init(&tmp, next);
+ if (! tag_init_str_copy(&tmp.tag, src))
+ return NULL;
+ *list = tmp;
+ return list;
+}
+
s_list * list_init_str_empty (s_list *list, s_list *next)
{
s_list tmp = {0};
@@ -1079,6 +1103,20 @@ s_list * list_new_str_alloc_copy (uw size, const char *p, s_list *next)
return list;
}
+s_list * list_new_str_cast (const s_sym * const *type,
+ const s_tag *src, s_list *next)
+{
+ s_list *list;
+ list = list_new(next);
+ if (! list)
+ return NULL;
+ if (! tag_init_str_cast(&list->tag, type, src)) {
+ free(list);
+ return NULL;
+ }
+ return list;
+}
+
s_list * list_new_str_concatenate (const s_str *a, const s_str *b,
s_list *next)
{
@@ -1093,7 +1131,7 @@ s_list * list_new_str_concatenate (const s_str *a, const s_str *b,
return list;
}
-s_list * list_new_str_concatenate_list (const s_list **src,
+s_list * list_new_str_concatenate_list (const s_list * const *src,
s_list *next)
{
s_list *list;
@@ -1107,6 +1145,19 @@ s_list * list_new_str_concatenate_list (const s_list **src,
return list;
}
+s_list * list_new_str_copy (const s_str *src, s_list *next)
+{
+ s_list *list;
+ list = list_new(next);
+ if (! list)
+ return NULL;
+ if (! tag_init_str_copy(&list->tag, src)) {
+ free(list);
+ return NULL;
+ }
+ return list;
+}
+
s_list * list_new_str_empty (s_list *next)
{
s_list *list;
diff --git a/libkc3/list_init.h b/libkc3/list_init.h
index fa7c587..3501666 100644
--- a/libkc3/list_init.h
+++ b/libkc3/list_init.h
@@ -64,11 +64,15 @@ s_list * list_init_str_1_alloc (s_list *list, const char *p,
s_list *next);
s_list * list_init_str_alloc_copy (s_list *list, uw size,
const char *p, s_list *next);
+s_list * list_init_str_cast (s_list *list, const s_sym * const *type,
+ const s_tag *src, s_list *next);
s_list * list_init_str_concatenate (s_list *list, const s_str *a,
const s_str *b, s_list *next);
s_list * list_init_str_concatenate_list (s_list *list,
- const s_list **src,
+ const s_list * const *src,
s_list *next);
+s_list * list_init_str_copy (s_list *list, const s_str *src,
+ 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);
@@ -142,10 +146,13 @@ 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_1_alloc (const char *p, s_list *next);
s_list * list_new_str_alloc_copy (uw size, const char *p, s_list *next);
+s_list * list_new_str_cast (const s_sym * const *type,
+ const s_tag *src, s_list *next);
s_list * list_new_str_concatenate (const s_str *a, const s_str *b,
s_list *next);
-s_list * list_new_str_concatenate_list (const s_list **src,
+s_list * list_new_str_concatenate_list (const s_list * const *src,
s_list *next);
+s_list * list_new_str_copy (const s_str *src, 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_copy (const s_struct *src, s_list *next);
@@ -212,9 +219,13 @@ 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_1_alloc (s_list *list, const char *p);
s_list * list_str_alloc_copy (s_list *list, uw size, const char *p);
+s_list * list_str_cast (s_list *list, const s_sym * const *type,
+ const s_tag *src);
s_list * list_str_concatenate (s_list *list, const s_str *a,
const s_str *b);
-s_list * list_str_concatenate_list (s_list *list, const s_list **src);
+s_list * list_str_concatenate_list (s_list *list,
+ const s_list * const *src);
+s_list * list_str_copy (s_list *list, const s_str *src);
s_list * list_str_empty (s_list *list);
s_list * list_struct (s_list *list, const s_sym *module);
s_list * list_struct_copy (s_list *list, const s_struct *src);
diff --git a/libkc3/tag_init.c b/libkc3/tag_init.c
index c6cdaa8..3a47dd6 100644
--- a/libkc3/tag_init.c
+++ b/libkc3/tag_init.c
@@ -405,6 +405,18 @@ s_tag * tag_init_str_alloc_copy (s_tag *tag, uw size, const char *p)
return tag;
}
+s_tag * tag_init_str_cast (s_tag *tag, const s_sym * const *type,
+ const s_tag *src)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tmp.type = TAG_STR;
+ if (! str_init_cast(&tmp.data.str, type, src))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_init_str_concatenate (s_tag *tag, const s_str *a,
const s_str *b)
{
@@ -417,7 +429,8 @@ s_tag * tag_init_str_concatenate (s_tag *tag, const s_str *a,
return tag;
}
-s_tag * tag_init_str_concatenate_list (s_tag *tag, const s_list **src)
+s_tag * tag_init_str_concatenate_list (s_tag *tag,
+ const s_list * const *src)
{
s_tag tmp = {0};
assert(tag);
@@ -428,6 +441,17 @@ s_tag * tag_init_str_concatenate_list (s_tag *tag, const s_list **src)
return tag;
}
+s_tag * tag_init_str_copy (s_tag *tag, const s_str *src)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tmp.type = TAG_STR;
+ if (! str_init_copy(&tmp.data.str, src))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_init_str_empty (s_tag *tag)
{
s_tag tmp = {0};
@@ -1066,6 +1090,20 @@ s_tag * tag_new_str_alloc_copy (uw size, const char *p)
return tag;
}
+s_tag * tag_new_str_cast (const s_sym * const *type, const s_tag *src)
+{
+ s_tag *tag;
+ tag = alloc(sizeof(s_tag));
+ if (! tag)
+ return NULL;
+ tag->type = TAG_STR;
+ if (! str_init_cast(&tag->data.str, type, src)) {
+ free(tag);
+ return NULL;
+ }
+ return tag;
+}
+
s_tag * tag_new_str_concatenate (const s_str *a, const s_str *b)
{
s_tag *tag;
@@ -1080,7 +1118,7 @@ s_tag * tag_new_str_concatenate (const s_str *a, const s_str *b)
return tag;
}
-s_tag * tag_new_str_concatenate_list (const s_list **src)
+s_tag * tag_new_str_concatenate_list (const s_list * const *src)
{
s_tag *tag;
tag = alloc(sizeof(s_tag));
@@ -1094,6 +1132,20 @@ s_tag * tag_new_str_concatenate_list (const s_list **src)
return tag;
}
+s_tag * tag_new_str_copy (const s_str *src)
+{
+ s_tag *tag;
+ tag = alloc(sizeof(s_tag));
+ if (! tag)
+ return NULL;
+ tag->type = TAG_STR;
+ if (! str_init_copy(&tag->data.str, src)) {
+ free(tag);
+ return NULL;
+ }
+ return tag;
+}
+
s_tag * tag_new_str_empty (void)
{
s_tag *tag;
@@ -1727,6 +1779,19 @@ s_tag * tag_str_alloc_copy (s_tag *tag, uw size, const char *p)
return tag;
}
+s_tag * tag_str_cast (s_tag *tag, const s_sym * const *type,
+ const s_tag *src)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tag_clean(tag);
+ tmp.type = TAG_STR;
+ if (! str_init_cast(&tmp.data.str, type, src))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_str_concatenate (s_tag *tag, const s_str *a, const s_str *b)
{
s_tag tmp = {0};
@@ -1739,7 +1804,7 @@ s_tag * tag_str_concatenate (s_tag *tag, const s_str *a, const s_str *b)
return tag;
}
-s_tag * tag_str_concatenate_list (s_tag *tag, const s_list **src)
+s_tag * tag_str_concatenate_list (s_tag *tag, const s_list * const *src)
{
s_tag tmp = {0};
assert(tag);
@@ -1751,6 +1816,18 @@ s_tag * tag_str_concatenate_list (s_tag *tag, const s_list **src)
return tag;
}
+s_tag * tag_str_copy (s_tag *tag, const s_str *src)
+{
+ s_tag tmp = {0};
+ assert(tag);
+ tag_clean(tag);
+ tmp.type = TAG_STR;
+ if (! str_init_copy(&tmp.data.str, src))
+ return NULL;
+ *tag = tmp;
+ return tag;
+}
+
s_tag * tag_str_empty (s_tag *tag)
{
s_tag tmp = {0};
diff --git a/libkc3/tag_init.h b/libkc3/tag_init.h
index 7ff3bbf..76c81d4 100644
--- a/libkc3/tag_init.h
+++ b/libkc3/tag_init.h
@@ -53,9 +53,13 @@ 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_1_alloc (s_tag *tag, const char *p);
s_tag * tag_init_str_alloc_copy (s_tag *tag, uw size, const char *p);
+s_tag * tag_init_str_cast (s_tag *tag, const s_sym * const *type,
+ const s_tag *src);
s_tag * tag_init_str_concatenate (s_tag *tag, const s_str *a,
const s_str *b);
-s_tag * tag_init_str_concatenate_list (s_tag *tag, const s_list **src);
+s_tag * tag_init_str_concatenate_list (s_tag *tag,
+ const s_list * const *src);
+s_tag * tag_init_str_copy (s_tag *tag, const s_str *src);
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_copy (s_tag *tag, const s_struct *src);
@@ -121,8 +125,10 @@ 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_1_alloc (const char *p);
s_tag * tag_new_str_alloc_copy (uw size, const char *p);
+s_tag * tag_new_str_cast (const s_sym * const *type, const s_tag *src);
s_tag * tag_new_str_concatenate (const s_str *a, const s_str *b);
-s_tag * tag_new_str_concatenate_list (const s_list **src);
+s_tag * tag_new_str_concatenate_list (const s_list * const *src);
+s_tag * tag_new_str_copy (const s_str *src);
s_tag * tag_new_str_empty (void);
s_tag * tag_new_struct (const s_sym *module);
s_tag * tag_new_struct_copy (const s_struct *src);
@@ -185,9 +191,13 @@ 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_1_alloc (s_tag *tag, const char *p);
s_tag * tag_str_alloc_copy (s_tag *tag, uw size, const char *p);
+s_tag * tag_str_cast (s_tag *tag, const s_sym * const *type,
+ const s_tag *src);
s_tag * tag_str_concatenate (s_tag *tag, const s_str *a,
const s_str *b);
-s_tag * tag_str_concatenate_list (s_tag *tag, const s_list **src);
+s_tag * tag_str_concatenate_list (s_tag *tag,
+ const s_list * const *src);
+s_tag * tag_str_copy (s_tag *tag, const s_str *src);
s_tag * tag_str_empty (s_tag *tag);
s_tag * tag_struct (s_tag *tag, const s_sym *module);
s_tag * tag_struct_copy (s_tag *tag, const s_struct *src);
diff --git a/libkc3/tag_init.rb b/libkc3/tag_init.rb
index 1f1e262..d9e9231 100644
--- a/libkc3/tag_init.rb
+++ b/libkc3/tag_init.rb
@@ -375,11 +375,16 @@ class TagInitList
TagInit.new("str", "alloc_copy", "TAG_STR", :init_mode_init,
[Arg.new("uw", "size"),
Arg.new("const char *", "p")]),
+ TagInit.new("str", "cast", "TAG_STR", :init_mode_init,
+ [Arg.new("const s_sym * const *", "type"),
+ Arg.new("const s_tag *", "src")]),
TagInit.new("str", "concatenate", "TAG_STR", :init_mode_init,
[Arg.new("const s_str *", "a"),
Arg.new("const s_str *", "b")]),
TagInit.new("str", "concatenate_list", "TAG_STR", :init_mode_init,
- [Arg.new("const s_list **", "src")]),
+ [Arg.new("const s_list * const *", "src")]),
+ TagInit.new("str", "copy", "TAG_STR", :init_mode_init,
+ [Arg.new("const s_str *", "src")]),
TagInit.new("str", "empty", "TAG_STR", :init_mode_init, []),
TagInit.new("struct", "TAG_STRUCT", :init_mode_init,
[Arg.new("const s_sym *", "module")]),
diff --git a/markdown/markdown.c b/markdown/markdown.c
index 490fd6f..cb12e5f 100644
--- a/markdown/markdown.c
+++ b/markdown/markdown.c
@@ -15,6 +15,16 @@
#include <libkc3/kc3.h>
#include "markdown.h"
+s32 markdown_titles_enter_block (MD_BLOCKTYPE type, void *detail,
+ void *data);
+s32 markdown_titles_leave_block (MD_BLOCKTYPE type, void *detail,
+ void *data);
+s32 markdown_titles_enter_span (MD_SPANTYPE type, void *detail,
+ void *data);
+s32 markdown_titles_leave_span (MD_SPANTYPE type, void *detail,
+ void *data);
+s32 markdown_titles_text (MD_TEXTTYPE type, const MD_CHAR *text,
+ MD_SIZE size, void *data);
void markdown_to_html_str_callback (const MD_CHAR *, MD_SIZE, void *);
s_str * markdown_to_html_str (const s_str *markdown, s_str *dest)
@@ -52,3 +62,187 @@ void markdown_to_html_str_callback (const MD_CHAR *p, MD_SIZE size,
l = &(*l)->next.data.list;
*(s_list ***) data = l;
}
+
+s_list ** markdown_titles (const s_str *markdown, s_list **dest)
+{
+ MD_PARSER parser = {0};
+ s_tuple tuple;
+ s_tag *tuple_count;
+ s_tag *tuple_last;
+ s_tag *tuple_list;
+ s_tag *tuple_str;
+ assert(markdown);
+ assert(dest);
+ tuple_init(&tuple, 9);
+ tuple_last = tuple.tag;
+ tuple_list = tuple.tag + 1;
+ tuple_str = tuple.tag + 2;
+ tuple_count = tuple.tag + 3;
+ tag_init_u8(tuple_last, 0);
+ tag_init_list(tuple_list, NULL);
+ tag_init_str_empty(tuple_str);
+ tag_init_u8(tuple_count, 0);
+ tag_init_u8(tuple_count + 1, 0);
+ tag_init_u8(tuple_count + 2, 0);
+ tag_init_u8(tuple_count + 3, 0);
+ tag_init_u8(tuple_count + 4, 0);
+ tag_init_u8(tuple_count + 5, 0);
+ parser.enter_block = markdown_titles_enter_block;
+ parser.leave_block = markdown_titles_leave_block;
+ parser.enter_span = markdown_titles_enter_span;
+ parser.leave_span = markdown_titles_leave_span;
+ parser.text = markdown_titles_text;
+ md_parse(markdown->ptr.pchar, markdown->size,
+ &parser, &tuple);
+ *dest = tuple_list->data.list;
+ return dest;
+}
+
+s32 markdown_titles_enter_block (MD_BLOCKTYPE type, void *detail,
+ void *data)
+{
+ s_tuple *tuple;
+ s_tag *tuple_str;
+ (void) detail;
+ assert(data);
+ tuple = data;
+ if (tuple->count != 9) {
+ err_puts("markdown_titles_enter_block: invalid tuple");
+ assert(! "markdown_titles_enter_block: invalid tuple");
+ return -1;
+ }
+ tuple_str = tuple->tag + 2;
+ if (type == MD_BLOCK_H)
+ tag_init_void(tuple_str);
+ return 0;
+}
+
+s32 markdown_titles_leave_block (MD_BLOCKTYPE type, void *detail,
+ void *data)
+{
+ MD_BLOCK_H_DETAIL *detail_h;
+ u8 i;
+ u8 level;
+ s_list *str_list;
+ s_list **str_list_tail;
+ const s_sym *sym_Str;
+ s_tuple *tuple;
+ s_tag *tuple_count;
+ s_tag *tuple_count_level;
+ s_tag *tuple_last;
+ s_tag *tuple_list;
+ s_list **tuple_list_tail;
+ s_tag *tuple_str;
+ assert(data);
+ sym_Str = &g_sym_Str;
+ tuple = data;
+ if (tuple->count != 9) {
+ err_puts("markdown_titles_leave_block: invalid tuple");
+ assert(! "markdown_titles_leave_block: invalid tuple");
+ return -1;
+ }
+ tuple_last = tuple->tag;
+ tuple_list = tuple->tag + 1;
+ tuple_str = tuple->tag + 2;
+ tuple_count = tuple->tag + 3;
+ if (type == MD_BLOCK_H) {
+ assert(detail);
+ detail_h = detail;
+ if (detail_h->level < 1 || detail_h->level > 6) {
+ err_puts("markdown_titles_leave_block: invalid level");
+ assert(! "markdown_titles_leave_block: invalid level");
+ return -1;
+ }
+ level = detail_h->level - 1;
+ tuple_count_level = tuple_count + level;
+ if (tuple_count_level->type != TAG_U8) {
+ err_puts("markdown_titles_leave_block: tuple_count_level"
+ " is not a U8");
+ assert(!("markdown_titles_leave_block: tuple_count_level"
+ " is not a U8"));
+ return -1;
+ }
+ tuple_count_level->data.u8++;
+ if (tuple_last->type != TAG_U8) {
+ err_puts("markdown_titles_leave_block: tuple_last is not a U8");
+ assert(! "markdown_titles_leave_block: tuple_last is not a U8");
+ return -1;
+ }
+ tuple_last->data.u8 = level;
+ str_list = NULL;
+ str_list_tail = &str_list;
+ i = 0;
+ while (i < level) {
+ *str_list_tail = list_new_str_cast(&sym_Str, tuple_count + i,
+ NULL);
+ str_list_tail = &(*str_list_tail)->next.data.list;
+ *str_list_tail = list_new_str_1(NULL, ".", NULL);
+ str_list_tail = &(*str_list_tail)->next.data.list;
+ i++;
+ }
+ // i = level
+ while (i < 6) {
+ tag_init_u8(tuple_count + i, 0);
+ i++;
+ }
+ *str_list_tail = list_new_str_1(NULL, " ", NULL);
+ str_list_tail = &(*str_list_tail)->next.data.list;
+ if (tuple_str->type != TAG_STR) {
+ err_puts("markdown_titles_leave_block: tuple_str is not a Str");
+ assert(! "markdown_titles_leave_block: tuple_str is not a Str");
+ return -1;
+ }
+ *str_list_tail = list_new_str_copy(&tuple_str->data.str, NULL);
+ str_list_tail = &(*str_list_tail)->next.data.list;
+ tuple_list_tail = list_tail(&tuple_list->data.list);
+ *tuple_list_tail = list_new(NULL);
+ if (! tag_init_str_concatenate_list(&(*tuple_list_tail)->tag,
+ (const s_list * const *)
+ &str_list))
+ return -1;
+ if (tuple_list->type != TAG_LIST) {
+ err_puts("markdown_titles_leave_block: tuple_list is not a List");
+ assert(! "markdown_titles_leave_block: tuple_list is not a List");
+ return -1;
+ }
+ tag_init_void(tuple_str);
+ }
+ return 0;
+}
+
+s32 markdown_titles_enter_span (MD_SPANTYPE type, void *detail,
+ void *data)
+{
+ (void) type;
+ (void) detail;
+ (void) data;
+ return 0;
+}
+
+s32 markdown_titles_leave_span (MD_SPANTYPE type, void *detail,
+ void *data)
+{
+ (void) type;
+ (void) detail;
+ (void) data;
+ return 0;
+}
+
+s32 markdown_titles_text (MD_TEXTTYPE type, const MD_CHAR *text,
+ MD_SIZE size, void *data)
+{
+ s_tuple *tuple;
+ s_tag *tuple_str;
+ (void) type;
+ tuple = data;
+ if (tuple->count != 9) {
+ err_puts("markdown_titles_text: invalid tuple");
+ assert(! "markdown_titles_text: invalid tuple");
+ return -1;
+ }
+ tuple_str = tuple->tag + 2;
+ if (tuple_str->type == TAG_VOID)
+ if (! tag_init_str_alloc_copy(tuple_str, size, text))
+ return -1;
+ return 0;
+}
diff --git a/test/Makefile b/test/Makefile
index 19790d5..bfb4160 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -114,24 +114,32 @@ test: libkc3_test
time ./libkc3_test
IKC3=${SRC_TOP}/ikc3/ikc3 time ./ikc3_test
KC3S=${SRC_TOP}/kc3s/kc3s time ./ekc3_test
+ IKC3=${SRC_TOP}/ikc3/ikc3 time ./json_test
+ IKC3=${SRC_TOP}/ikc3/ikc3 time ./markdown_test
KC3S=${SRC_TOP}/kc3s/kc3s time ./http_test
test_asan: libkc3_test_asan
time ./libkc3_test_asan
IKC3=${SRC_TOP}/ikc3/ikc3_asan time ./ikc3_test
KC3S=${SRC_TOP}/kc3s/kc3s_asan time ./ekc3_test
+ IKC3=${SRC_TOP}/ikc3/ikc3_asan time ./json_test
+ IKC3=${SRC_TOP}/ikc3/ikc3_asan time ./markdown_test
KC3S=${SRC_TOP}/kc3s/kc3s_asan time ./http_test
test_cov:
time ./libkc3_test_cov
IKC3=${SRC_TOP}/ikc3/ikc3_cov time ./ikc3_test
KC3S=${SRC_TOP}/kc3s/kc3s_cov time ./ekc3_test
+ IKC3=${SRC_TOP}/ikc3s/ikc3s_cov time ./json_test
+ IKC3=${SRC_TOP}/ikc3s/ikc3s_cov time ./markdown_test
KC3S=${SRC_TOP}/kc3s/kc3s_cov time ./http_test
test_debug: libkc3_test_debug
time ./libkc3_test_debug
IKC3=${SRC_TOP}/ikc3/ikc3_debug time ./ikc3_test
KC3S=${SRC_TOP}/kc3s/kc3s_debug time ./ekc3_test
+ IKC3=${SRC_TOP}/ikc3s/ikc3s_debug time ./json_test
+ IKC3=${SRC_TOP}/ikc3s/ikc3s_debug time ./markdown_test
KC3S=${SRC_TOP}/kc3s/kc3s_debug time ./http_test
test_ekc3:
diff --git a/test/json/inspect.out.expected b/test/json/inspect.out.expected
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/json/inspect.out.expected
diff --git a/test/json/inspect.ret.expected b/test/json/inspect.ret.expected
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/test/json/inspect.ret.expected
@@ -0,0 +1 @@
+0
diff --git a/test/markdown/.ikc3_history b/test/markdown/.ikc3_history
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/markdown/.ikc3_history
diff --git a/test/markdown/titles.diff b/test/markdown/titles.diff
new file mode 100644
index 0000000..c62a856
--- /dev/null
+++ b/test/markdown/titles.diff
@@ -0,0 +1,14 @@
+--- titles.out.expected Wed Sep 4 18:56:57 2024
++++ titles.out Thu Sep 5 01:54:45 2024
+@@ -1,4 +1,2 @@
+-quote Markdown.titles("Text.\n")
+-[]
+-quote Markdown.titles("# Title\nText.\n\n## Title 2\n")
+-["h1-1", "h2-1.1"]
++Markdown.titles("Text.\n")
++Segmentation fault (core dumped)
+--- titles.ret.expected Wed Sep 4 18:57:08 2024
++++ titles.ret Thu Sep 5 01:54:45 2024
+@@ -1 +1 @@
+-0
++139
diff --git a/test/markdown/titles.out b/test/markdown/titles.out
new file mode 100644
index 0000000..ebd449a
--- /dev/null
+++ b/test/markdown/titles.out
@@ -0,0 +1,2 @@
+Markdown.titles("Text.\n")
+Segmentation fault (core dumped)
diff --git a/test/markdown/titles.out.expected b/test/markdown/titles.out.expected
new file mode 100644
index 0000000..87a5ae0
--- /dev/null
+++ b/test/markdown/titles.out.expected
@@ -0,0 +1,4 @@
+Markdown.titles("Text.\n")
+[]
+Markdown.titles("# Title\nText.\n\n## Title 2\n")
+["h1-1", "h2-1.1"]
diff --git a/test/markdown/titles.ret b/test/markdown/titles.ret
new file mode 100644
index 0000000..897bdc8
--- /dev/null
+++ b/test/markdown/titles.ret
@@ -0,0 +1 @@
+139
diff --git a/test/markdown/titles.ret.expected b/test/markdown/titles.ret.expected
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/test/markdown/titles.ret.expected
@@ -0,0 +1 @@
+0