support c codes
authorLaurent MAZET <laurent.mazet@thalesgroup.com>
Tue, 6 Oct 2026 17:26:45 +0000 (19:26 +0200)
committerLaurent MAZET <laurent.mazet@thalesgroup.com>
Tue, 6 Oct 2026 17:35:06 +0000 (19:35 +0200)
element.c
element.h
html2txt.c

index 618ea52c688f36e5a90fa0d935720de00fdc301e..a7153eed65053a620ae96d8dd4a0294853ca0380 100644 (file)
--- a/element.c
+++ b/element.c
@@ -6,9 +6,9 @@
 typedef struct {
     char *name;
     char *glyph;
-} nchar_t;
+} nstring_t;
 
-nchar_t elements[] = {
+nstring_t html_elements[] = {
     { "Aacute;", "Á" },
     { "Aacute", "Á" },
     { "aacute;", "á" },
@@ -2243,10 +2243,10 @@ nchar_t elements[] = {
     { NULL, NULL }
 };
 
-/* check element */
-int check_element (char *str, char **glyph)
+/* check Html element */
+int check_html_element (char *str, char **glyph)
 {
-    nchar_t *pt = elements;
+    nstring_t *pt = html_elements;
     while (pt->name) {
         int len = strlen (pt->name);
         if (strncmp (str, pt->name, len) == 0) {
@@ -2258,6 +2258,41 @@ int check_element (char *str, char **glyph)
     return 0;
 }
 
+typedef struct {
+    char letter;
+    char *glyph;
+} nchar_t;
+
+nchar_t c_elements[] = {
+    { 'a', "\a" },
+    { 'b', "\b" },
+    { 'e', "\e" },
+    { 'f', "\f" },
+    { 'n', "\n" },
+    { 'r', "\r" },
+    { 't', "\t" },
+    { 'v', "\v" },
+    { '\\', "\\" },
+    { '\'', "'" },
+    { '"', "\"" },
+    { '?', "\?" },
+    { '\0', NULL }
+};
+
+/* check C element */
+int check_c_element (char c, char **glyph)
+{
+    nchar_t *pt = c_elements;
+    while (pt->letter) {
+        if (c == pt->letter) {
+            *glyph = pt->glyph;
+            return 1;
+        }
+        pt++;
+    }
+    return 0;
+}
+
 /* check hexa character */
 int is_hexa (char c)
 {
@@ -2272,8 +2307,8 @@ int is_hexa (char c)
     return ret;
 }
 
-/* check code */
-int check_code (char *str, char *out)
+/* check Html code */
+int check_html_code (char *str, char *out)
 {
     int i = 0, l = 0;
     while (str[i] != ';') {
@@ -2294,4 +2329,46 @@ int check_code (char *str, char *out)
     return i + 1;
 }
 
+/* check C code in octal */
+int check_c_code_octal (char *str, char *out)
+{
+    for (int i = 0; i < 3; i++) {
+        if ((str[i] < '0') || (str[i] > '7')) {
+            out[0] = '\0';
+            return 0;
+        }
+        out[0] = (out[0] << 3) + str[i] - '0';
+    }
+    return 3;
+}
+
+/* check C code in hexa */
+int check_c_code_hexa (char *str, char *out, int len)
+{
+    int i = 0, l = 0;
+    while (len-- != 0) {
+        int v = 0;
+        if ((str[i] == '\0') || ((v = is_hexa(str[i])) < 0)) {
+            if (len < 0) {
+                if ((i > 1) && (i % 2 == 1)) {
+                    i = 2 * (i / 2);
+                    out[l] = '\0';
+                }
+                return i;
+            }
+            *out = '\0';
+            return 0;
+        }
+
+        out[l] = (out[l] << 4) + v;
+        if (i % 2 == 1) {
+            if (out[l] != 0) {
+                l++;
+            }
+        }
+        i++;
+    }
+    return i;
+}
+
 /* vim: set ts=4 sw=4 et: */
index 4cd8c101feb1bab8238e0d028e7038e9cea11006..e56cb5e3ec50b4fffa976bd3c3344d93d378b640 100644 (file)
--- a/element.h
+++ b/element.h
@@ -1,9 +1,15 @@
 #ifndef __ELEMENT_H__
 #define __ELEMENT_H__
 
-int check_element (char *str, char **glyph);
+int check_html_element (char *str, char **glyph);
 
-int check_code (char *str, char *out);
+int check_c_element (char c, char **glyph);
+
+int check_html_code (char *str, char *out);
+
+int check_c_code_octal (char *str, char *out);
+
+int check_c_code_hexa (char *str, char *out, int len);
 
 #endif /* __ELEMENT_H__ */
 
index 2b5183fd34d35da0a7a5aed4d861210013e59507..614ed045e7b891dd51419b5bf95bb265ddff6469 100644 (file)
 /* static variables */
 char *progname = NULL;
 char *version = "0.1";
-
+int ccode = 0;
 char *fin = NULL;
 
 /* usage function */
 int usage (int ret)
 {
     FILE *fd = ret ? stderr : stdout;
-    fprintf (fd, "usage: %s [-v int] [-h] [-i file]\n", progname);
+    fprintf (fd, "usage: %s [-c] [-i file] [-v int] [-h]\n", progname);
+    fprintf (fd, " -c: translate c code (%s)\n", ccode ? "true" : "false");
     fprintf (fd, " -h: help message\n");
-    fprintf (fd, " -v: verbose level(%d)\n", verbose);
     fprintf (fd, " -i file: input file (%s)\n", fin ? fin : "<stdin>");
+    fprintf (fd, " -v: verbose level(%d)\n", verbose);
     fprintf (fd, "%s version %s\n", progname, version);
 
     return ret;
@@ -69,6 +70,9 @@ int main (int argc, char *argv[])
         }
         char c = arg[1];
         switch (c) {
+        case 'c':
+            ccode = 1;
+            break;
         case 'i':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
             if (arg == NULL) {
@@ -129,19 +133,20 @@ int main (int argc, char *argv[])
     while (*pt) {
         char *glyph = NULL;
         char out[5] = {0};
+        VERBOSE (DEBUG, "::: %c(%d) 0x%p", *pt, *pt, pt); 
         switch (*pt) {
         case '<':
             while ((*pt) && (*pt != '>')) pt++;
             break;
         case '&':
             if (pt[1] == '#') {
-                pt += check_code (pt + 2, out);
+                pt += check_html_code (pt + 2, out);
                 if (*out != '\0') {
                     glyph = out;
                     pt++;
                 }
             } else {
-                pt += check_element (pt + 1, &glyph);
+                pt += check_html_element (pt + 1, &glyph);
             }
             if (glyph) {
                 if (glyph != out) {
@@ -152,6 +157,41 @@ int main (int argc, char *argv[])
                 out[1] = '\0';
             }
             break;
+        case '\\':
+            if (ccode) {
+                int offset = 0;
+                if ((pt[1] >= '0') && (pt[1] <= '7')) {
+                    pt += check_c_code_octal (pt + 1, out);
+                } else if (pt[1] == 'x') {
+                    pt += check_c_code_hexa (pt + 2, out, -1);
+                    offset++;
+                } else if (pt[1] == 'u') {
+                    pt += check_c_code_hexa (pt + 2, out, 4);
+                    offset++;
+                } else if (pt[1] == 'U') {
+                    pt += check_c_code_hexa (pt + 2, out, 8);
+                    offset++;
+                } else {
+                    VERBOSE (DEBUG, " 0x%p -> ", pt); 
+                    pt += check_c_element (pt[1], &glyph);
+                    VERBOSE (DEBUG, " 0x%p %d", pt, offset); 
+                }
+                if (*out != '\0') {
+                    glyph = out;
+                }
+                if (glyph) {
+                    if (glyph != out) {
+                        strcpy (out, glyph);
+                    }
+                    pt += offset;
+                    VERBOSE (DEBUG, " 0x%p", pt); 
+                } else {
+                    strncpy (out, pt, 1);
+                    out[1] = '\0';
+                }
+                break;
+            }
+            // fallthrough
         default:
             strncpy (out, pt, 1);
         }
@@ -159,6 +199,7 @@ int main (int argc, char *argv[])
             printf ("%s", out);
         }
         pt++;
+        VERBOSE (DEBUG, " %p\n", pt); 
     }
 
     free (buffer);
@@ -177,6 +218,16 @@ int main (int argc, char *argv[])
 /* test: echo '&#6f6F' | html2txt.exe -v 1| grep '^&#6f6F$' */
 /* test: echo '&#foobar' | html2txt.exe -v 1| grep '^&#foobar$' */
 /* test: echo '&foobar' | html2txt.exe -v 2 | grep '^&foobar' */
+/* test: echo '\nx\tx\z' | html2txt.exe -c | grep '^x.x\\z$' */
+/* test: echo '\101b\102a' | html2txt.exe -c | grep '^AbBa$' */
+/* test: echo 'a\108b' | html2txt.exe -c | grep '^a\\108b$' */
+/* test: echo '\x41b\x62a' | html2txt.exe -c | grep '^Abba$' */
+/* test: echo '\x41 b\x62 a' | html2txt.exe -c | grep '^A bb a$' */
+/* test: echo '\x41b\xa\x62a' | html2txt.exe -c | grep '^Ab$' */
+/* test: echo '\x41b\xa\x62a' | html2txt.exe -c | grep '^ba$' */
+/* test: echo '\u0041b\u0062a' | html2txt.exe -c | grep '^Abba$' */
+/* test: echo '\u004xb\u62a' | html2txt.exe -c | grep '^\\u004xb\\u62a$' */
+/* test: echo '\U00000041b\U00000062a' | html2txt.exe -c | grep '^Abba$' */
 /* test: html2txt.exe -i test.html >/dev/null */
 
 /* vim: set ts=4 sw=4 et: */