diff --git a/.gitmodules b/.gitmodules
index d7ef10d..5d0e411 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -9,3 +9,6 @@
[submodule "fonts"]
path = fonts
url = https://git.kmx.io/kc3-lang/fonts.git
+[submodule "markdown/md4c"]
+ path = markdown/md4c
+ url = https://git.kmx.io/kc3-lang/md4c.git
diff --git a/Makefile b/Makefile
index 9ef9ffc..258a062 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,7 @@ all:
${MAKE} -C ekc3 all
${MAKE} -C event all
${MAKE} -C json all
+ ${MAKE} -C markdown all
${MAKE} -C socket all
${MAKE} -C http all
${MAKE} -C httpd all
@@ -35,6 +36,7 @@ asan:
${MAKE} -C ekc3 asan
${MAKE} -C event asan
${MAKE} -C json asan
+ ${MAKE} -C markdown asan
${MAKE} -C socket asan
${MAKE} -C http asan
${MAKE} -C httpd asan
@@ -51,6 +53,7 @@ build:
${MAKE} -C ekc3 build
${MAKE} -C event build
${MAKE} -C json build
+ ${MAKE} -C markdown build
${MAKE} -C socket build
${MAKE} -C http build
${MAKE} -C httpd build
@@ -66,6 +69,7 @@ clean:
${MAKE} -C ekc3 clean
${MAKE} -C event clean
${MAKE} -C json clean
+ ${MAKE} -C markdown clean
${MAKE} -C socket clean
${MAKE} -C http clean
${MAKE} -C httpd clean
@@ -80,6 +84,7 @@ clean_cov:
${MAKE} -C ekc3 clean_cov
${MAKE} -C event clean_cov
${MAKE} -C json clean_cov
+ ${MAKE} -C markdown clean_cov
${MAKE} -C socket clean_cov
${MAKE} -C http clean_cov
${MAKE} -C httpd clean_cov
@@ -95,6 +100,7 @@ cov:
${MAKE} -C ekc3 cov
${MAKE} -C event cov
${MAKE} -C json cov
+ ${MAKE} -C markdown cov
${MAKE} -C socket cov
${MAKE} -C http cov
${MAKE} -C httpd cov
@@ -110,6 +116,7 @@ debug:
${MAKE} -C ekc3 debug
${MAKE} -C event debug
${MAKE} -C json debug
+ ${MAKE} -C markdown debug
${MAKE} -C socket debug
${MAKE} -C http debug
${MAKE} -C httpd debug
@@ -151,6 +158,7 @@ distclean:
${MAKE} -C ekc3 distclean
${MAKE} -C event distclean
${MAKE} -C json distclean
+ ${MAKE} -C markdown distclean
${MAKE} -C socket distclean
${MAKE} -C http distclean
${MAKE} -C httpd distclean
@@ -228,6 +236,7 @@ gcovr:
${MAKE} -C ekc3 gcovr
${MAKE} -C event gcovr
${MAKE} -C json gcovr
+ ${MAKE} -C markdown gcovr
${MAKE} -C socket gcovr
${MAKE} -C http gcovr
${MAKE} -C httpd gcovr
@@ -270,6 +279,7 @@ gdb_test_http:
${MAKE} -C ikc3 debug
${MAKE} -C kc3s debug
${MAKE} -C json debug
+ ${MAKE} -C markdown debug
${MAKE} -C socket debug
${MAKE} -C http debug
${MAKE} -C test gdb_test_http
@@ -281,6 +291,7 @@ gdb_test_http_asan:
${MAKE} -C ikc3 asan
${MAKE} -C kc3s asan
${MAKE} -C json asan
+ ${MAKE} -C markdown asan
${MAKE} -C socket asan
${MAKE} -C http asan
${MAKE} -C test gdb_test_http_asan
@@ -292,6 +303,7 @@ gdb_test_httpd:
${MAKE} -C ikc3 debug
${MAKE} -C kc3s debug
${MAKE} -C json debug
+ ${MAKE} -C markdown debug
${MAKE} -C socket debug
${MAKE} -C http debug
${MAKE} -C httpd debug
@@ -304,6 +316,7 @@ gdb_test_httpd_asan:
${MAKE} -C ikc3 asan
${MAKE} -C kc3s asan
${MAKE} -C json asan
+ ${MAKE} -C markdown asan
${MAKE} -C socket asan
${MAKE} -C http asan
${MAKE} -C httpd asan
@@ -339,6 +352,22 @@ gdb_test_json_asan:
${MAKE} -C json asan
${MAKE} -C test gdb_test_json_asan
+gdb_test_markdown:
+ ${MAKE} -C libtommath debug
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 debug
+ ${MAKE} -C ikc3 debug
+ ${MAKE} -C markdown debug
+ ${MAKE} -C test gdb_test_markdown
+
+gdb_test_markdown_asan:
+ ${MAKE} -C libtommath asan
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 asan
+ ${MAKE} -C ikc3 asan
+ ${MAKE} -C markdown asan
+ ${MAKE} -C test gdb_test_markdown_asan
+
gen:
${MAKE} -C libkc3 gen
@@ -351,6 +380,7 @@ http:
${MAKE} -C ekc3 build
${MAKE} -C event build
${MAKE} -C json build
+ ${MAKE} -C markdown build
${MAKE} -C socket build
${MAKE} -C http build
@@ -363,6 +393,7 @@ httpd:
${MAKE} -C ekc3 build
${MAKE} -C event build
${MAKE} -C json build
+ ${MAKE} -C markdown build
${MAKE} -C socket build
${MAKE} -C http build
${MAKE} -C httpd build
@@ -400,6 +431,19 @@ ikc3_gcovr:
${MAKE} ikc3_test_cov
${MAKE} gcovr
+install:
+ ${MAKE} -C libkc3 install
+ ${MAKE} -C ikc3 install
+ ${MAKE} -C kc3s install
+ ${MAKE} -C ekc3 install
+ ${MAKE} -C event install
+ ${MAKE} -C json install
+ ${MAKE} -C markdown install
+ ${MAKE} -C socket install
+ ${MAKE} -C http install
+ ${MAKE} -C httpd install
+ ${MAKE} -C window install
+
json:
${MAKE} -C libtommath build
${MAKE} -C ucd2c
@@ -428,19 +472,6 @@ json_debug:
${MAKE} -C ikc3 debug
${MAKE} -C json debug
-install:
- ${MAKE} -C libkc3 install
- ${MAKE} -C ikc3 install
- ${MAKE} -C kc3s install
- ${MAKE} -C ekc3 install
- ${MAKE} -C event install
- ${MAKE} -C json install
- ${MAKE} -C socket install
- ${MAKE} -C http install
- ${MAKE} -C httpd install
- ${MAKE} -C json install
- ${MAKE} -C window install
-
kc3-${KC3_VERSION}.tar.gz: kc3.index
rm -rf kc3-${KC3_VERSION}.old
-mv kc3-${KC3_VERSION} kc3-${KC3_VERSION}.old
@@ -482,6 +513,7 @@ lib_links_bsd:
ln -sf ../../../event/.libs/libkc3_event.so.0.0 lib/kc3/0.1/event.so
ln -sf ../../../http/.libs/libkc3_http.so.0.0 lib/kc3/0.1/http.so
ln -sf ../../../json/.libs/libkc3_json.so.0.0 lib/kc3/0.1/json.so
+ ln -sf ../../../markdown/.libs/libkc3_markdown.so.0.0 lib/kc3/0.1/markdown.so
ln -sf ../../../socket/.libs/libkc3_socket.so.0.0 lib/kc3/0.1/socket.so
lib_links_bsd_debug:
@@ -489,6 +521,7 @@ lib_links_bsd_debug:
ln -sf ../../../event/.libs/libkc3_event_debug.so.0.0 lib/kc3/0.1/event.so
ln -sf ../../../http/.libs/libkc3_http_debug.so.0.0 lib/kc3/0.1/http.so
ln -sf ../../../json/.libs/libkc3_json_debug.so.0.0 lib/kc3/0.1/json.so
+ ln -sf ../../../markdown/.libs/libkc3_markdown_debug.so.0.0 lib/kc3/0.1/markdown.so
ln -sf ../../../socket/.libs/libkc3_socket_debug.so.0.0 lib/kc3/0.1/socket.so
lib_links_linux:
@@ -496,6 +529,7 @@ lib_links_linux:
ln -sf ../../../event/.libs/libkc3_event.so lib/kc3/0.1/event.so
ln -sf ../../../http/.libs/libkc3_http.so lib/kc3/0.1/http.so
ln -sf ../../../json/.libs/libkc3_json.so lib/kc3/0.1/json.so
+ ln -sf ../../../markdown/.libs/libkc3_markdown.so lib/kc3/0.1/markdown.so
ln -sf ../../../socket/.libs/libkc3_socket.so lib/kc3/0.1/socket.so
lib_links_linux_asan:
@@ -503,6 +537,7 @@ lib_links_linux_asan:
ln -sf ../../../event/.libs/libkc3_event_asan.so lib/kc3/0.1/event.so
ln -sf ../../../http/.libs/libkc3_http_asan.so lib/kc3/0.1/http.so
ln -sf ../../../json/.libs/libkc3_json_asan.so lib/kc3/0.1/json.so
+ ln -sf ../../../markdown/.libs/libkc3_markdown_asan.so lib/kc3/0.1/markdown.so
ln -sf ../../../socket/.libs/libkc3_socket_asan.so lib/kc3/0.1/socket.so
lib_links_linux_debug:
@@ -510,6 +545,7 @@ lib_links_linux_debug:
ln -sf ../../../event/.libs/libkc3_event_debug.so lib/kc3/0.1/event.so
ln -sf ../../../http/.libs/libkc3_http_debug.so lib/kc3/0.1/http.so
ln -sf ../../../json/.libs/libkc3_json_debug.so lib/kc3/0.1/json.so
+ ln -sf ../../../markdown/.libs/libkc3_markdown_debug.so lib/kc3/0.1/markdown.so
ln -sf ../../../socket/.libs/libkc3_socket_debug.so lib/kc3/0.1/socket.so
libkc3_gcovr:
@@ -543,11 +579,40 @@ lldb_test:
${MAKE} -C ekc3 debug
${MAKE} -C event debug
${MAKE} -C json debug
+ ${MAKE} -C markdown debug
${MAKE} -C socket debug
${MAKE} -C http debug
${MAKE} -C httpd debug
${MAKE} -C test lldb_test
+markdown:
+ ${MAKE} -C libtommath build
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 build
+ ${MAKE} -C ikc3 build
+ ${MAKE} -C markdown build
+
+markdown_asan:
+ ${MAKE} -C libtommath asan
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 asan
+ ${MAKE} -C ikc3 asan
+ ${MAKE} -C markdown asan
+
+markdown_cov:
+ ${MAKE} -C libtommath cov
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 cov
+ ${MAKE} -C ikc3 cov
+ ${MAKE} -C markdown cov
+
+markdown_debug:
+ ${MAKE} -C libtommath debug
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 debug
+ ${MAKE} -C ikc3 debug
+ ${MAKE} -C markdown debug
+
test:
${MAKE} -C libtommath build
${MAKE} -C ucd2c
@@ -557,6 +622,7 @@ test:
${MAKE} -C ekc3 build
${MAKE} -C event build
${MAKE} -C json build
+ ${MAKE} -C markdown build
${MAKE} -C socket build
${MAKE} -C http build
${MAKE} -C httpd build
@@ -572,6 +638,7 @@ test_asan:
${MAKE} -C ekc3 asan
${MAKE} -C event asan
${MAKE} -C json asan
+ ${MAKE} -C markdown asan
${MAKE} -C socket asan
${MAKE} -C http asan
${MAKE} -C httpd asan
@@ -586,6 +653,7 @@ test_cov:
${MAKE} -C ekc3 cov clean_cov
${MAKE} -C event cov clean_cov
${MAKE} -C json cov clean_cov
+ ${MAKE} -C markdown cov clean_cov
${MAKE} -C socket cov clean_cov
${MAKE} -C http cov clean_cov
${MAKE} -C httpd cov clean_cov
@@ -600,6 +668,7 @@ test_debug:
${MAKE} -C ekc3 debug
${MAKE} -C event debug
${MAKE} -C json debug
+ ${MAKE} -C markdown debug
${MAKE} -C socket debug
${MAKE} -C http debug
${MAKE} -C httpd debug
@@ -655,6 +724,7 @@ test_http:
${MAKE} -C ikc3 build
${MAKE} -C kc3s build
${MAKE} -C json build
+ ${MAKE} -C markdown build
${MAKE} -C socket build
${MAKE} -C http build
${MAKE} -C test test_http
@@ -666,6 +736,7 @@ test_http_asan:
${MAKE} -C ikc3 asan
${MAKE} -C kc3s asan
${MAKE} -C json asan
+ ${MAKE} -C markdown asan
${MAKE} -C socket asan
${MAKE} -C http asan
${MAKE} -C test test_http_asan
@@ -677,6 +748,7 @@ test_http_cov:
${MAKE} -C ikc3 cov
${MAKE} -C kc3s cov
${MAKE} -C json cov
+ ${MAKE} -C markdown cov
${MAKE} -C socket cov
${MAKE} -C http cov
${MAKE} -C test test_http_cov
@@ -688,6 +760,7 @@ test_http_debug:
${MAKE} -C ikc3 debug
${MAKE} -C kc3s debug
${MAKE} -C json debug
+ ${MAKE} -C markdown debug
${MAKE} -C socket debug
${MAKE} -C http debug
${MAKE} -C test test_http_debug
@@ -699,6 +772,7 @@ test_httpd:
${MAKE} -C ikc3 build
${MAKE} -C kc3s build
${MAKE} -C json build
+ ${MAKE} -C markdown build
${MAKE} -C socket build
${MAKE} -C http build
${MAKE} -C httpd build
@@ -711,6 +785,7 @@ test_httpd_asan:
${MAKE} -C ikc3 asan
${MAKE} -C kc3s asan
${MAKE} -C json asan
+ ${MAKE} -C markdown asan
${MAKE} -C socket asan
${MAKE} -C http asan
${MAKE} -C httpd asan
@@ -723,6 +798,7 @@ test_httpd_cov:
${MAKE} -C ikc3 cov
${MAKE} -C kc3s cov
${MAKE} -C json cov
+ ${MAKE} -C markdown cov
${MAKE} -C socket cov
${MAKE} -C http cov
${MAKE} -C httpd cov
@@ -735,6 +811,7 @@ test_httpd_debug:
${MAKE} -C ikc3 debug
${MAKE} -C kc3s debug
${MAKE} -C json debug
+ ${MAKE} -C markdown debug
${MAKE} -C socket debug
${MAKE} -C http debug
${MAKE} -C httpd debug
@@ -818,6 +895,38 @@ test_libkc3_debug:
${MAKE} -C libkc3 debug
${MAKE} -C test test_libkc3_debug
+test_markdown:
+ ${MAKE} -C libtommath build
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 build
+ ${MAKE} -C ikc3 build
+ ${MAKE} -C markdown build
+ ${MAKE} -C test test_markdown
+
+test_markdown_asan:
+ ${MAKE} -C libtommath asan
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 asan
+ ${MAKE} -C ikc3 asan
+ ${MAKE} -C markdown asan
+ ${MAKE} -C test test_markdown_asan
+
+test_markdown_cov:
+ ${MAKE} -C libtommath cov
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 cov
+ ${MAKE} -C ikc3 cov
+ ${MAKE} -C markdown cov
+ ${MAKE} -C test test_markdown_cov
+
+test_markdown_debug:
+ ${MAKE} -C libtommath debug
+ ${MAKE} -C ucd2c
+ ${MAKE} -C libkc3 debug
+ ${MAKE} -C ikc3 debug
+ ${MAKE} -C markdown debug
+ ${MAKE} -C test test_markdown_debug
+
test_socket:
${MAKE} -C libtommath build
${MAKE} -C ucd2c
@@ -906,6 +1015,9 @@ test_socket_debug:
gdb_test_libkc3 \
gdb_test_libkc3_asan \
gdb_test_libkc3_debug \
+ gdb_test_markdown \
+ gdb_test_markdown_asan \
+ gdb_test_markdown_debug \
gdb_test_socket \
gdb_test_socket_asan \
gdb_test_socket_debug \
@@ -938,6 +1050,10 @@ test_socket_debug:
libkc3 \
libtommath \
license \
+ markdown \
+ markdown_asan \
+ markdown_cov \
+ markdown_debug \
test \
test_asan \
test_cov \
@@ -971,6 +1087,10 @@ test_socket_debug:
test_libkc3_asan \
test_libkc3_cov \
test_libkc3_debug \
+ test_markdown \
+ test_markdown_asan \
+ test_markdown_cov \
+ test_markdown_debug \
test_socket \
test_socket_asan \
test_socket_cov \
diff --git a/configure b/configure
index ad771a3..f867913 100755
--- a/configure
+++ b/configure
@@ -58,6 +58,7 @@ config_subdirs \
ekc3 \
event \
json \
+ markdown \
socket \
http \
httpd \
diff --git a/env b/env
index 5d7cb09..154bb51 100644
--- a/env
+++ b/env
@@ -1,4 +1,4 @@
-export LD_LIBRARY_PATH="$PWD/libkc3/.libs:$PWD/ekc3/.libs:$PWD/http/.libs:$PWD/lib/kc3/0.1:$LD_LIBRARY_PATH"
+export LD_LIBRARY_PATH="$PWD/libkc3/.libs:$PWD/ekc3/.libs:$PWD/http/.libs:$PWD/markdown/.libs:$PWD/lib/kc3/0.1:$LD_LIBRARY_PATH"
export KC3_HTTPD_HOST=0.0.0.0
export KC3_HTTPD_PORT=58000
#export MALLOC_OPTIONS=CDFGJU
diff --git a/lib/kc3/0.1/markdown.kc3 b/lib/kc3/0.1/markdown.kc3
new file mode 100644
index 0000000..e2f004c
--- /dev/null
+++ b/lib/kc3/0.1/markdown.kc3
@@ -0,0 +1,7 @@
+defmodule Markdown do
+
+ dlopen(__DIR__ + "markdown.so")
+
+ def to_html_str = cfn Str "markdown_to_html_str" (Str, Result)
+
+end
diff --git a/libkc3/kc3_main.h b/libkc3/kc3_main.h
index 8c24837..49d185e 100644
--- a/libkc3/kc3_main.h
+++ b/libkc3/kc3_main.h
@@ -41,6 +41,7 @@ const s_sym ** kc3_module (const s_sym **dest);
uw * kc3_offsetof (const s_sym * const *module,
const s_sym * const *field, uw *dest);
sw kc3_puts (const s_tag *tag);
+s_str * kc3_str (const s_tag *tag, s_str *dest);
/* Operators. */
s_tag * kc3_access (const s_tag *tag, const s_list * const *addr,
diff --git a/libkc3/str.c b/libkc3/str.c
index 87bdd1b..c5dba48 100644
--- a/libkc3/str.c
+++ b/libkc3/str.c
@@ -437,7 +437,7 @@ s_str * str_init_concatenate (s_str *str, const s_str *a,
}
s_str * str_init_concatenate_list (s_str *str,
- const s_list **list)
+ const s_list * const *list)
{
const s_list *l;
char *p;
diff --git a/libkc3/str.h b/libkc3/str.h
index 304a4b5..18294c6 100644
--- a/libkc3/str.h
+++ b/libkc3/str.h
@@ -48,7 +48,7 @@ s_str * str_init_cast (s_str *str, const s_sym * const *type,
s_str * str_init_concatenate (s_str *str, const s_str *a,
const s_str *b);
s_str * str_init_concatenate_list (s_str *str,
- const s_list **list);
+ const s_list * const *list);
s_str * str_init_character (s_str *str, const character src);
s_str * str_init_copy (s_str *str, const s_str *src);
s_str * str_init_copy_1 (s_str *str, const char *p);
diff --git a/markdown/Makefile b/markdown/Makefile
new file mode 100644
index 0000000..a4db491
--- /dev/null
+++ b/markdown/Makefile
@@ -0,0 +1,78 @@
+## kc3
+## Copyright 2022-2024 kmx.io <contact@kmx.io>
+##
+## Permission is hereby granted to use this software granted the above
+## copyright notice and this permission paragraph are included in all
+## copies and substantial portions of this software.
+##
+## THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+## PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+## AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+## THIS SOFTWARE.
+
+CLEANFILES = *.a *.gcno *.la .libs *.lo *.o
+
+CLEANFILES_COV = *.css *.gcda *.html .libs/*.gcda
+
+CLEANFILES += ${CLEANFILES_COV}
+
+DISTCLEANFILES = .build ${CLEANFILES} config.h config.mk
+
+all:
+ ${MAKE} build
+ ${MAKE} debug
+ if ${HAVE_ASAN}; then ${MAKE} asan; fi
+ if ${HAVE_GCOV}; then ${MAKE} cov; fi
+
+asan:
+ ${MAKE} ${LIB_ASAN}
+
+build:
+ ${MAKE} ${LIB}
+
+clean:
+ rm -rf ${CLEANFILES}
+
+clean_cov:
+ rm -rf ${CLEANFILES_COV}
+
+cov:
+ ${MAKE} ${LIB_COV}
+
+debug:
+ ${MAKE} ${LIB_DEBUG}
+
+distclean:
+ rm -rf ${DISTCLEANFILES}
+
+gcovr:
+ gcovr --gcov-executable ${GCOV} --html-details libkc3_web.html
+
+install:
+ ${INSTALL} -o ${OWNER} -g ${GROUP} -m 0755 -d ${prefix}/include/libkc3/ekc3
+ ${LIBTOOL} --tag=CC --mode=install ${INSTALL} -o ${OWNER} -g ${GROUP} -m 0644 ${HEADERS} ${prefix}/include/libkc3/ekc3
+ ${INSTALL} -o ${OWNER} -g ${GROUP} -m 0755 -d ${prefix}/lib
+ ${LIBTOOL} --tag=CC --mode=install ${INSTALL} -o ${OWNER} -g ${GROUP} -m 0644 ${LIB} ${prefix}/lib
+ ${LIBTOOL} --tag=CC --mode=install ${INSTALL} -o ${OWNER} -g ${GROUP} -m 0644 ${LIB_DEBUG} ${prefix}/lib
+ ${LIBTOOL} --finish ${prefix}/lib
+
+test:
+
+update_sources:
+ ./update_sources
+
+.PHONY: \
+ all \
+ asan \
+ build \
+ clean \
+ cov \
+ debug \
+ distclean \
+ gen \
+ install \
+ test \
+ update_sources \
+
+include config.mk
+include sources.mk
diff --git a/markdown/configure b/markdown/configure
new file mode 100755
index 0000000..2b7acb6
--- /dev/null
+++ b/markdown/configure
@@ -0,0 +1,118 @@
+#!/bin/sh
+## kc3
+## Copyright 2022-2024 kmx.io <contact@kmx.io>
+##
+## Permission is hereby granted to use this software granted the above
+## copyright notice and this permission paragraph are included in all
+## copies and substantial portions of this software.
+##
+## THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+## PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+## AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+## THIS SOFTWARE.
+
+set -e
+
+echo "$PWD/configure"
+
+export SRC_TOP="$(dirname "$PWD")"
+
+CONFIG_H_PREFIX=KC3_MARKDOWN_
+
+. ../config.subr
+
+LIB=libkc3_markdown.la
+LIB_ASAN=libkc3_markdown_asan.la
+LIB_COV=libkc3_markdown_cov.la
+LIB_DEBUG=libkc3_markdown_debug.la
+
+echo "LIB = $LIB" >> ${CONFIG_MK}
+echo "LIB_ASAN = $LIB_ASAN" >> ${CONFIG_MK}
+echo "LIB_COV = $LIB_COV" >> ${CONFIG_MK}
+echo "LIB_DEBUG = $LIB_DEBUG" >> ${CONFIG_MK}
+
+. ./sources.sh
+
+OBJECTS="$(c2ext .main.lo "$SOURCES")"
+echo "OBJECTS = $OBJECTS" >> ${CONFIG_MK}
+OBJECTS_ASAN="$(c2ext .asan.lo "$SOURCES")"
+OBJECTS_COV="$(c2ext .cov.lo "$SOURCES")"
+OBJECTS_DEBUG="$(c2ext .debug.lo "$SOURCES")"
+
+# Common config for all targets
+CPPFLAGS="-I.. $CPPFLAGS"
+CFLAGS="$CFLAGS -W -Wall -Werror -std=c11 -pedantic -pipe"
+LDFLAGS="-export-dynamic $LDFLAGS -rdynamic"
+config_asan
+config_gnu
+config_i386
+pkg_config libbsd-overlay
+pkg_config libffi
+pkg_config libmd
+config_define PREFIX "\"${PREFIX}\""
+update_config_h
+LIBS="$LIBS -lm -rpath ${PREFIX}/lib"
+
+# Address Sanitizer config
+CPPFLAGS_ASAN="$CPPFLAGS"
+CFLAGS_ASAN="$CFLAGS -DDEBUG -O1 -g"
+CFLAGS_ASAN="$CFLAGS_ASAN -fsanitize=address -fno-omit-frame-pointer"
+LDFLAGS_ASAN="$LDFLAGS"
+LIBS_LOCAL_ASAN="../libkc3/libkc3_asan.la"
+LIBS_ASAN="$LIBS $LIBS_LOCAL_ASAN"
+
+# Coverage config
+CPPFLAGS_COV="$CPPFLAGS"
+CFLAGS_COV="$CFLAGS -fprofile-arcs -ftest-coverage"
+LDFLAGS_COV="$LDFLAGS --coverage"
+LIBS_LOCAL_COV="../libkc3/libkc3_cov.la"
+LIBS_COV="$LIBS $LIBS_LOCAL_COV -lgcov"
+
+# Debug config
+CPPFLAGS_DEBUG="$CPPFLAGS"
+CFLAGS_DEBUG="$CFLAGS -DDEBUG -O0 -g"
+LDFLAGS_DEBUG="$LDFLAGS"
+LIBS_LOCAL_DEBUG="../libkc3/libkc3_debug.la"
+LIBS_DEBUG="$LIBS $LIBS_LOCAL_DEBUG"
+
+# Main config
+DEFAULT_CFLAGS="-O2 -fPIC"
+if [ "x$ENV_CFLAGS" = "x" ]; then
+ CFLAGS="$CFLAGS $DEFAULT_CFLAGS"
+fi
+CFLAGS="$CFLAGS -DNDEBUG"
+LIBS_LOCAL="../libkc3/libkc3.la"
+LIBS="$LIBS $LIBS_LOCAL"
+
+echo "LIB = $LIB" >> ${CONFIG_MK}
+echo "HAVE_ASAN = $HAVE_ASAN" >> ${CONFIG_MK}
+echo "CPPFLAGS = $CPPFLAGS" >> ${CONFIG_MK}
+echo "CFLAGS = $CFLAGS" >> ${CONFIG_MK}
+echo "LDFLAGS = $LDFLAGS" >> ${CONFIG_MK}
+echo "LIBS = $LIBS" >> ${CONFIG_MK}
+echo >> ${CONFIG_MK}
+echo "LIB_ASAN = $LIB_ASAN" >> ${CONFIG_MK}
+echo "CPPFLAGS_ASAN = $CPPFLAGS_ASAN" >> ${CONFIG_MK}
+echo "CFLAGS_ASAN = $CFLAGS_ASAN" >> ${CONFIG_MK}
+echo "LDFLAGS_ASAN = $LDFLAGS_ASAN" >> ${CONFIG_MK}
+echo "LIBS_ASAN = $LIBS_ASAN" >> ${CONFIG_MK}
+echo >> ${CONFIG_MK}
+echo "LIB_COV = $LIB_COV" >> ${CONFIG_MK}
+echo "CPPFLAGS_COV = $CPPFLAGS_COV" >> ${CONFIG_MK}
+echo "CFLAGS_COV = $CFLAGS_COV" >> ${CONFIG_MK}
+echo "LDFLAGS_COV = $LDFLAGS_COV" >> ${CONFIG_MK}
+echo "LIBS_COV = $LIBS_COV" >> ${CONFIG_MK}
+echo >> ${CONFIG_MK}
+echo "LIB_DEBUG = $LIB_DEBUG" >> ${CONFIG_MK}
+echo "CPPFLAGS_DEBUG = $CPPFLAGS_DEBUG" >> ${CONFIG_MK}
+echo "CFLAGS_DEBUG = $CFLAGS_DEBUG" >> ${CONFIG_MK}
+echo "LDFLAGS_DEBUG = $LDFLAGS_DEBUG" >> ${CONFIG_MK}
+echo "LIBS_DEBUG = $LIBS_DEBUG" >> ${CONFIG_MK}
+
+update_build
+update_build_lib
+
+build_lo
+build_lib
+
+update_config_mk
diff --git a/markdown/entity.c b/markdown/entity.c
new file mode 120000
index 0000000..6b7dbf7
--- /dev/null
+++ b/markdown/entity.c
@@ -0,0 +1 @@
+md4c/src/entity.c
\ No newline at end of file
diff --git a/markdown/entity.h b/markdown/entity.h
new file mode 120000
index 0000000..ae4f56b
--- /dev/null
+++ b/markdown/entity.h
@@ -0,0 +1 @@
+md4c/src/entity.h
\ No newline at end of file
diff --git a/markdown/markdown.c b/markdown/markdown.c
new file mode 100644
index 0000000..490fd6f
--- /dev/null
+++ b/markdown/markdown.c
@@ -0,0 +1,54 @@
+/* kc3
+ * Copyright 2022,2023,2024 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#include <md4c.h>
+#include <md4c-html.h>
+#include <libkc3/kc3.h>
+#include "markdown.h"
+
+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)
+{
+ s_list *list;
+ s_list **l;
+ s_str tmp;
+ assert(markdown);
+ assert(dest);
+ list = NULL;
+ l = &list;
+ md_html(markdown->ptr.pchar, markdown->size,
+ markdown_to_html_str_callback,
+ &l, 0, 0);
+ if (! str_init_concatenate_list(&tmp,
+ (const s_list * const *) &list)) {
+ list_delete_all(list);
+ return NULL;
+ }
+ list_delete_all(list);
+ *dest = tmp;
+ return dest;
+}
+
+void markdown_to_html_str_callback (const MD_CHAR *p, MD_SIZE size,
+ void *data)
+{
+ s_list **l;
+ l = *(s_list ***) data;
+ if (! (*l = list_new_str_alloc_copy(size, p, NULL))) {
+ err_puts("markdown_to_html_str_callback: list_new_str_cpy");
+ assert(! "markdown_to_html_str_callback: list_new_str_cpy");
+ return;
+ }
+ l = &(*l)->next.data.list;
+ *(s_list ***) data = l;
+}
diff --git a/markdown/markdown.h b/markdown/markdown.h
new file mode 100644
index 0000000..9c6fb36
--- /dev/null
+++ b/markdown/markdown.h
@@ -0,0 +1,21 @@
+/* kc3
+ * Copyright 2022,2023,2024 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#ifndef MARKDOWN_H
+#define MARKDOWN_H
+
+//#include "types.h"
+
+/* Observers. */
+s_str * markdown_to_html (const s_str *markdown, s_str *dest);
+
+#endif /* MARKDOWN_H */
diff --git a/markdown/md4c b/markdown/md4c
new file mode 160000
index 0000000..481fbfb
--- /dev/null
+++ b/markdown/md4c
@@ -0,0 +1 @@
+Subproject commit 481fbfbdf72daab2912380d62bb5f2187d438408
diff --git a/markdown/md4c-html.c b/markdown/md4c-html.c
new file mode 120000
index 0000000..374c94f
--- /dev/null
+++ b/markdown/md4c-html.c
@@ -0,0 +1 @@
+md4c/src/md4c-html.c
\ No newline at end of file
diff --git a/markdown/md4c-html.h b/markdown/md4c-html.h
new file mode 120000
index 0000000..3836198
--- /dev/null
+++ b/markdown/md4c-html.h
@@ -0,0 +1 @@
+md4c/src/md4c-html.h
\ No newline at end of file
diff --git a/markdown/md4c.c b/markdown/md4c.c
new file mode 120000
index 0000000..586ad87
--- /dev/null
+++ b/markdown/md4c.c
@@ -0,0 +1 @@
+md4c/src/md4c.c
\ No newline at end of file
diff --git a/markdown/md4c.h b/markdown/md4c.h
new file mode 120000
index 0000000..151b21c
--- /dev/null
+++ b/markdown/md4c.h
@@ -0,0 +1 @@
+md4c/src/md4c.h
\ No newline at end of file
diff --git a/markdown/sources.mk b/markdown/sources.mk
new file mode 100644
index 0000000..b762875
--- /dev/null
+++ b/markdown/sources.mk
@@ -0,0 +1,13 @@
+# sources.mk generated by update_sources
+HEADERS = \
+ "entity.h" \
+ "markdown.h" \
+ "md4c-html.h" \
+ "md4c.h" \
+
+SOURCES = \
+ "entity.c" \
+ "markdown.c" \
+ "md4c-html.c" \
+ "md4c.c" \
+
diff --git a/markdown/sources.sh b/markdown/sources.sh
new file mode 100644
index 0000000..858b532
--- /dev/null
+++ b/markdown/sources.sh
@@ -0,0 +1,3 @@
+# sources.sh generated by update_sources
+HEADERS='entity.h markdown.h md4c-html.h md4c.h '
+SOURCES='entity.c markdown.c md4c-html.c md4c.c '
diff --git a/markdown/update_sources b/markdown/update_sources
new file mode 100755
index 0000000..a4101fe
--- /dev/null
+++ b/markdown/update_sources
@@ -0,0 +1,28 @@
+#!/bin/sh
+## kc3
+## Copyright 2022-2024 kmx.io <contact@kmx.io>
+##
+## Permission is hereby granted to use this software granted the above
+## copyright notice and this permission paragraph are included in all
+## copies and substantial portions of this software.
+##
+## THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+## PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+## AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+## THIS SOFTWARE.
+
+. ../config.subr
+
+echo "$PWD/update_sources"
+
+echo "# sources.mk generated by update_sources" > ${SOURCES_MK}
+echo "# sources.sh generated by update_sources" > ${SOURCES_SH}
+
+HEADERS="$(ls *.h | grep -v '^config.h$')"
+sources HEADERS "$HEADERS"
+
+SOURCES="$(ls *.c)"
+sources SOURCES "$SOURCES"
+
+update_sources_mk
+update_sources_sh
diff --git a/test/Makefile b/test/Makefile
index c2b734f..19790d5 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -101,6 +101,12 @@ gdb_test_json:
gdb_test_json_asan:
cd json && ${GDB} ../../ikc3/.libs/ikc3_asan
+gdb_test_markdown:
+ cd markdown && ${GDB} ../../ikc3/.libs/ikc3_debug
+
+gdb_test_markdown_asan:
+ cd markdown && ${GDB} ../../ikc3/.libs/ikc3_asan
+
lldb_test: debug
if [ -f libkc3_test_debug.core ]; then lldb .libs/libkc3_test_debug libkc3_test_debug.core; else lldb .libs/libkc3_test_debug; fi
@@ -194,6 +200,18 @@ test_libkc3: libkc3_test
test_libkc3_cov: libkc3_test_cov
time ./libkc3_test_cov
+test_markdown:
+ IKC3=${SRC_TOP}/ikc3/ikc3 time ./markdown_test
+
+test_markdown_asan:
+ IKC3=${SRC_TOP}/ikc3/ikc3_asan time ./markdown_test
+
+test_markdown_cov:
+ IKC3=${SRC_TOP}/ikc3/ikc3_cov time ./markdown_test
+
+test_markdown_debug:
+ IKC3=${SRC_TOP}/ikc3/ikc3_debug time ./markdown_test
+
test_valgrind: libkc3_test
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./libkc3_test
diff --git a/test/markdown/titles.kc3 b/test/markdown/titles.kc3
new file mode 100644
index 0000000..0255ddb
--- /dev/null
+++ b/test/markdown/titles.kc3
@@ -0,0 +1,4 @@
+quote Markdown.titles("Text.\n")
+Markdown.titles("Text.\n")
+quote Markdown.titles("# Title\nText.\n\n## Title 2\n")
+Markdown.titles("# Title\nText.\n\n## Title 2\n")
diff --git a/test/markdown/to_html_str.kc3 b/test/markdown/to_html_str.kc3
new file mode 100644
index 0000000..2cb23c4
--- /dev/null
+++ b/test/markdown/to_html_str.kc3
@@ -0,0 +1,4 @@
+quote Markdown.to_html_str("Text.\n")
+Markdown.to_html_str("Text.\n")
+quote Markdown.to_html_str("# Title\nText.\n\n## Title 2\n")
+Markdown.to_html_str("# Title\nText.\n\n## Title 2\n")
diff --git a/test/markdown/to_html_str.out b/test/markdown/to_html_str.out
new file mode 100644
index 0000000..e63e2a5
--- /dev/null
+++ b/test/markdown/to_html_str.out
@@ -0,0 +1,4 @@
+Markdown.to_html_str("Text.\n")
+"<p>Text.</p>\n"
+Markdown.to_html_str("# Title\nText.\n\n## Title 2\n")
+"<h1>Title</h1>\n<p>Text.</p>\n<h2>Title 2</h2>\n"
diff --git a/test/markdown/to_html_str.out.expected b/test/markdown/to_html_str.out.expected
new file mode 100644
index 0000000..e63e2a5
--- /dev/null
+++ b/test/markdown/to_html_str.out.expected
@@ -0,0 +1,4 @@
+Markdown.to_html_str("Text.\n")
+"<p>Text.</p>\n"
+Markdown.to_html_str("# Title\nText.\n\n## Title 2\n")
+"<h1>Title</h1>\n<p>Text.</p>\n<h2>Title 2</h2>\n"
diff --git a/test/markdown/to_html_str.ret b/test/markdown/to_html_str.ret
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/test/markdown/to_html_str.ret
@@ -0,0 +1 @@
+0
diff --git a/test/markdown/to_html_str.ret.expected b/test/markdown/to_html_str.ret.expected
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/test/markdown/to_html_str.ret.expected
@@ -0,0 +1 @@
+0
diff --git a/test/markdown_test b/test/markdown_test
new file mode 100755
index 0000000..ccaceff
--- /dev/null
+++ b/test/markdown_test
@@ -0,0 +1,80 @@
+#!/bin/sh
+cd "$(dirname $0)/markdown" || exit
+
+TEST_COLOR_KO="[0;91m"
+TEST_COLOR_OK="[0;92m"
+TEST_COLOR_RESET="[0m"
+TEST_COUNT=0
+TEST_KO=0
+TEST_OK=0
+
+if [ "x$IKC3" = "x" ]; then
+ if [ -f ../../ikc3/ikc3 ]; then
+ IKC3=../../ikc3/ikc3
+ elif [ -f ../../ikc3 ]; then
+ IKC3=../../ikc3
+ fi
+fi
+
+test_ko() {
+ printf "%s" "${TEST_COLOR_KO}F${TEST_COLOR_RESET}"
+ TEST_KO=$(($TEST_KO + 1))
+ TEST_COUNT=$(($TEST_COUNT + 1))
+}
+
+test_ok() {
+ printf "%s" "${TEST_COLOR_OK}.${TEST_COLOR_RESET}"
+ TEST_OK=$(($TEST_OK + 1))
+ TEST_COUNT=$(($TEST_COUNT + 1))
+}
+
+if [ $# = 0 ]; then
+ if [ "x${MARKDOWN_TEST}" = "x" ]; then
+ TARGETS="$(ls -1 *.kc3 | sed -e 's/[.]kc3$//')"
+ else
+ TARGETS="${MARKDOWN_TEST}"
+ fi
+else
+ TARGETS="$@"
+fi
+
+rm -f *.diff *.out *.ret
+for TARGET in $TARGETS; do
+ RESULT=test_ok
+ $IKC3 --load ${TARGET}.kc3 --quit > ${TARGET}.out 2>&1
+ echo $? > ${TARGET}.ret
+ if ! diff -abu ${TARGET}.out.expected ${TARGET}.out > ${TARGET}.diff
+ then
+ RESULT=test_ko
+ fi
+ if ! diff -abu ${TARGET}.ret.expected ${TARGET}.ret >> ${TARGET}.diff
+ then
+ RESULT=test_ko
+ fi
+ if [ "x$RESULT" = "xtest_ok" ]; then
+ rm ${TARGET}.diff
+ test_ok
+ else
+ test_ko
+ fi
+done
+echo
+DIFFS="$(for TARGET in $TARGETS; do
+ if [ -f "${TARGET}.diff" ]; then
+ printf "%s " "${TARGET}.diff"
+ fi
+done)"
+if [ "x$DIFFS" != "x" ]; then
+ ls $DIFFS
+ less $DIFFS || cat $DIFFS
+fi
+echo
+printf "%s" "Total $TEST_COUNT tests. "
+printf "%s" "${TEST_COLOR_OK}OK $TEST_OK ($(($TEST_OK * 100 / $TEST_COUNT))%)${TEST_COLOR_RESET}. "
+echo "${TEST_COLOR_KO}KO $TEST_KO ($(($TEST_KO * 100 / $TEST_COUNT))%)${TEST_COLOR_RESET}."
+
+if [ "x$TEST_KO" = "x0" ]; then
+ exit 0
+fi
+
+exit 1
diff --git a/update_sources b/update_sources
index a5eb9d1..e7d8f85 100755
--- a/update_sources
+++ b/update_sources
@@ -89,6 +89,7 @@ update_sources_sh
( cd ekc3 && ./update_sources; )
( cd event && ./update_sources; )
( cd json && ./update_sources; )
+( cd markdown && ./update_sources; )
( cd socket && ./update_sources; )
( cd http && ./update_sources; )
( cd httpd && ./update_sources; )