typedef struct {
char *name;
char *glyph;
-} nchar_t;
+} nstring_t;
-nchar_t elements[] = {
+nstring_t html_elements[] = {
{ "Aacute;", "Á" },
{ "Aacute", "Á" },
{ "aacute;", "á" },
{ 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) {
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)
{
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] != ';') {
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: */
#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__ */
/* 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;
}
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) {
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) {
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);
}
printf ("%s", out);
}
pt++;
+ VERBOSE (DEBUG, " %p\n", pt);
}
free (buffer);
/* test: echo 'f6F' | html2txt.exe -v 1| grep '^f6F$' */
/* 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: */