Commit baf87c618d0fb7282bbfef4d63eb2e1eb17ac7d4

Thomas de Grivel 2024-07-18T15:42:02

ekc3: with html_escape by default

diff --git a/Makefile b/Makefile
index 73d338f..d91381c 100644
--- a/Makefile
+++ b/Makefile
@@ -154,6 +154,10 @@ gdb_test:
 	${MAKE} debug
 	${MAKE} -C test gdb_test
 
+gdb_test_ekc3:
+	${MAKE} debug
+	${MAKE} -C test gdb_test_ekc3
+
 gen:
 	${MAKE} -C libkc3 gen
 
diff --git a/ekc3/ekc3.c b/ekc3/ekc3.c
index a5930bb..72a7f41 100644
--- a/ekc3/ekc3.c
+++ b/ekc3/ekc3.c
@@ -516,31 +516,34 @@ sw ekc3_render_tag (const s_tag *tag)
       assert(! "ekc3_render_tag: ekc3_render_block_to_str");
       return -1;
     }
-    break;
+    if (! html_escape(&in, &escaped)) {
+      str_clean(&in);
+      err_puts("ekc3_render_tag: html_escape");
+      assert(! "ekc3_render_tag: html_escape");
+      return -1;
+    }
+    str_clean(&in);
+    if ((r = io_write_str(&escaped)) < 0) {
+      err_puts("ekc3_render_tag: io_write_str 1");
+      assert(! "ekc3_render_tag: io_write_str 1");
+    }
+    str_clean(&escaped);
+    return r;
   case TAG_STR:
-    str_init(&in, NULL, tag->data.str.size, tag->data.str.ptr.pchar);
-    break;
+    if ((r = io_write_str(&tag->data.str)) < 0) {
+      err_puts("ekc3_render_tag: io_write_str 2");
+      assert(! "ekc3_render_tag: io_write_str 2");
+    }
+    return r;
   default:
-    err_write_1("ekc3_render_tag: cannot render ");
-    err_write_1(tag_type_to_string(tag->type));
-    err_write_1(": ");
-    err_inspect_tag(tag);
-    err_write_1("\n");
-    return -1;
-  }
-  if (! html_escape(&in, &escaped)) {
-    str_clean(&in);
-    err_puts("ekc3_render_tag: html_escape");
-    assert(! "ekc3_render_tag: html_escape");
-    return -1;
-  }
-  if ((r = io_write_str(&escaped)) < 0) {
-    err_puts("ekc3_render_tag: io_write_str");
-    assert(! "ekc3_render_tag: io_write_str");
+    break;
   }
-  str_clean(&in);
-  str_clean(&escaped);
-  return r;
+  err_write_1("ekc3_render_tag: cannot render ");
+  err_write_1(tag_type_to_string(tag->type));
+  err_write_1(": ");
+  err_inspect_tag(tag);
+  err_write_1("\n");
+  return -1;
 }
 
 s_fn * ekc3_to_render_fn (const p_ekc3 *ekc3, s_fn *dest)
diff --git a/ekc3/html.c b/ekc3/html.c
index 88eefd7..41c2138 100644
--- a/ekc3/html.c
+++ b/ekc3/html.c
@@ -16,6 +16,7 @@
 s_str * html_escape (const s_str *str, s_str *dest)
 {
   s_buf buf;
+  character c;
   const s_list *e;
   const s_list *escape;
   s_ident       escape_ident;
@@ -23,7 +24,7 @@ s_str * html_escape (const s_str *str, s_str *dest)
   s_tag *replace;
   s_tag *reserved;
   s_str s;
-  s_tag tag_c;
+  s_tag tag;
   assert(str);
   assert(dest);
   ident_init(&escape_ident, sym_1("EKC3"), sym_1("html_escape"));
@@ -42,9 +43,12 @@ s_str * html_escape (const s_str *str, s_str *dest)
   escape = escape_tag.data.list;
   if (! buf_init_alloc(&buf, str->size * 8))
     return NULL;
-  tag_c.type = TAG_CHARACTER;
+  tag.type = TAG_STR;
+  tag.data.str = (s_str) {0};
   s = *str;
-  while (str_read_character_utf8(&s, &tag_c.data.character) > 0) {
+  while (str_read_character_utf8(&s, &c) > 0) {
+    if (! str_init_character(&tag.data.str, c))
+      goto ko;
     replace = NULL;
     e = escape;
     while (e) {
@@ -54,21 +58,24 @@ s_str * html_escape (const s_str *str, s_str *dest)
                  " not a Str");
         assert(!("html_escape: EKC3.html_escape: reserved that is"
                  " not a Str"));
+        str_clean(&tag.data.str);
         goto ko;
       }
-      if (! compare_tag(reserved, &tag_c)) {
+      if (! compare_tag(reserved, &tag)) {
         replace = e->tag.data.tuple.tag + 1;
         if (replace->type != TAG_STR) {
           err_puts("html_escape: EKC3.html_escape: replacement that is"
                    " not a Str");
           assert(!("html_escape: EKC3.html_escape: replacement that is"
                    " not a Str"));
+          str_clean(&tag.data.str);
           goto ko;
         }
         break;
       }
       e = list_next(e);
     }
+    str_clean(&tag.data.str);
     if (replace) {
       if (buf_write_str(&buf, &replace->data.str) <= 0) {
         err_puts("html_escape: buf_write_str");
@@ -77,7 +84,7 @@ s_str * html_escape (const s_str *str, s_str *dest)
       }
     }
     else {
-      if (buf_write_character_utf8(&buf, tag_c.data.character) <= 0) {
+      if (buf_write_character_utf8(&buf, c) <= 0) {
         err_puts("html_escape: buf_write_character_utf8");
         assert(! "html_escape: buf_write_character_utf8");
         goto ko;
diff --git a/lib/kc3/0.1/ekc3.kc3 b/lib/kc3/0.1/ekc3.kc3
index ca5b6ea..4f53dcf 100644
--- a/lib/kc3/0.1/ekc3.kc3
+++ b/lib/kc3/0.1/ekc3.kc3
@@ -1,12 +1,12 @@
 defmodule EKC3 do
 
-  dlopen(__DIR__ + "ekc3.so")
+  dlopen(__DIR__ + "ekc3_debug.so")
 
-  def html_escape = [{"&", "&amp"},
-                     {"<", "&lt"},
-                     {">", "&gt"},
-                     {"\"", "&quot"},
-                     {"'", "&#39"}]
+  def html_escape = [{"&", "&amp;"},
+                     {"<", "&lt;"},
+                     {">", "&gt;"},
+                     {"\"", "&quot;"},
+                     {"'", "&#39;"}]
 
   def render_file = cfn Str "ekc3_render_file" (Str)
 
diff --git a/lib/kc3/0.1/ekc3_debug.so b/lib/kc3/0.1/ekc3_debug.so
new file mode 120000
index 0000000..39ab92d
--- /dev/null
+++ b/lib/kc3/0.1/ekc3_debug.so
@@ -0,0 +1 @@
+../../../ekc3/.libs/libekc3_debug.so.0.0
\ No newline at end of file
diff --git a/libkc3/str.c b/libkc3/str.c
index 7eab910..f5cfba5 100644
--- a/libkc3/str.c
+++ b/libkc3/str.c
@@ -155,6 +155,8 @@ s_str * str_init_cast (s_str *str, const s_sym * const *type,
   assert(type);
   assert(tag);
   switch (tag->type) {
+  case TAG_CHARACTER:
+    return str_init_character(str, tag->data.character);
   case TAG_S8:
     return str_init_s8(str, tag->data.s8);
   case TAG_S16:
@@ -214,6 +216,18 @@ s_str * str_init_cat (s_str *str, const s_str *a, const s_str *b)
   return str;
 }
 
+s_str * str_init_character (s_str *str, const character src)
+{
+  char b[4];
+  s_buf buf;
+  buf_init(&buf, false, sizeof(b), b);
+  if (buf_write_character_utf8(&buf, src) < 0)
+    return NULL;
+  if (buf_read_to_str(&buf, str) < 0)
+    return NULL;
+  return str;
+}
+
 s_str * str_init_copy (s_str *str, const s_str *src)
 {
   s_str tmp = {0};
diff --git a/libkc3/str.h b/libkc3/str.h
index a578575..d035c3a 100644
--- a/libkc3/str.h
+++ b/libkc3/str.h
@@ -37,6 +37,7 @@ s_str * str_init_alloc (s_str *str, uw size, const char *p);
 s_str * str_init_cast (s_str *str, const s_sym * const *type,
                        const s_tag *tag);
 s_str * str_init_cat (s_str *str, const s_str *a, const s_str *b);
+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);
 s_str * str_init_empty (s_str *str);
diff --git a/test/Makefile b/test/Makefile
index f8bb43a..6c5eebe 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -70,6 +70,9 @@ gcovr:
 gdb_test: debug
 	if [ -f libkc3_test_debug.core ]; then gdb .libs/libkc3_test_debug libkc3_test_debug.core; else gdb .libs/libkc3_test_debug; fi
 
+gdb_test_ekc3:
+	cd ekc3 && gdb ../../kc3s/.libs/kc3s_debug
+
 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
 
diff --git a/test/ekc3/title.html.ekc3 b/test/ekc3/title.html.ekc3
index 8190173..7a86e6e 100644
--- a/test/ekc3/title.html.ekc3
+++ b/test/ekc3/title.html.ekc3
@@ -3,7 +3,9 @@
     <title><%= title %></title>
   </head>
   <body>
-    <% title2 = title + " H1" %>
+    <% title2 = title + " H1 (silent block)" %>
     <h1><%= title2 %></h1>
+    <h1><%= title_h1 %></h1>
+    <%= title_h2 %>
   </body>
 </html>
diff --git a/test/ekc3/title.kc3 b/test/ekc3/title.kc3
index 3c9b93d..e3e44a8 100644
--- a/test/ekc3/title.kc3
+++ b/test/ekc3/title.kc3
@@ -1,2 +1,4 @@
 title = "EKC3 test title"
+title_h1 = "<title>\"Title escaped &amp; in title'</title>"
+title_h2 = "<h2>Title H2 (raw)</h2>"
 EKC3.render_file(__DIR__ + "title.html.ekc3")
diff --git a/test/ekc3/title.out.expected b/test/ekc3/title.out.expected
index 21462c9..2446475 100644
--- a/test/ekc3/title.out.expected
+++ b/test/ekc3/title.out.expected
@@ -3,6 +3,8 @@
     <title>EKC3 test title</title>
   </head>
   <body>
-    <h1>EKC3 test title H1</h1>
+    <h1>EKC3 test title H1 (silent block)</h1>
+    <h1>&lt;title&gt;&quot;Title escaped &amp;amp; in title&#39;&lt;/title&gt;</h1>
+    <h2>Title H2 (raw)</h2>
   </body>
 </html>