node.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include "txt2html.h"
  2. struct node *node_create(struct node *prev, NodeType t)
  3. {
  4. struct node *n = calloc(1, sizeof(struct node));
  5. if (prev) {
  6. n->prev = prev;
  7. prev->next = n;
  8. }
  9. n->type = t;
  10. if (t == OPEN+BR+CLOSE) {
  11. n->buf = "<br/>\n\0";
  12. } else if (t & OPEN) {
  13. t &= 0x0F;
  14. if (t == H1) n->buf = "<h1>\0";
  15. else if (t == H2) n->buf = "<h2>\0";
  16. else if (t == PRE) n->buf = "<pre>\0";
  17. else if (t == P) n->buf = "<p>\0";
  18. else if (t == OL) n->buf = "<ol>\n\0";
  19. else if (t == UL) n->buf = "<ul>\n\0";
  20. else if (t == OL+LI || t == UL+LI)
  21. n->buf = "<li>\0";
  22. } else if (t & CLOSE) {
  23. t &= 0x0F;
  24. node_writec(&prev, EOF);
  25. if (t == H1) n->buf = "</h1>\n\0";
  26. else if (t == H2) n->buf = "</h2>\n\0";
  27. else if (t == PRE) n->buf = "</pre>\n\0";
  28. else if (t == P) n->buf = "</p>\n\0";
  29. else if (t == OL) n->buf = "</ol>\n\0";
  30. else if (t == UL) n->buf = "</ul>\n\0";
  31. else if (t == UL+LI || t == OL+LI)
  32. n->buf = "</li>\n\0";
  33. }
  34. return n;
  35. }
  36. // node_writec has an internal static buffer (`buf`) that it writes `c` to.
  37. // if `c == EOF` or `buf` reaches `BUFSIZ`, then `buf` it's written to n->buf.
  38. // `n->buf` will only be allocated required memory.
  39. void node_writec(struct node **n, int c)
  40. {
  41. assert(n);
  42. static int pg = 0;
  43. static int len = 0;
  44. static char buf[BUFSIZ+1];
  45. if (len+2 == BUFSIZ || (c == EOF && len > 0)) {
  46. if (c == EOF) {
  47. buf[len++] = '\0';
  48. buf[len++] = '$'; // signal malloc not assigned const
  49. }
  50. (*n)->buf = (pg == 0) ? malloc(len) : realloc((*n)->buf, strlen((*n)->buf) + len);
  51. memmove((*n)->buf, buf, len);
  52. ++pg;
  53. len = 0;
  54. memset(buf, '\0', BUFSIZ);
  55. }
  56. switch (c) {
  57. case EOF:
  58. pg = 0;
  59. break;
  60. case '\t':
  61. strncat(buf, "&emsp;", 7);
  62. len += 6;
  63. break;
  64. default:
  65. strncat(buf, (char *)&c, 2);
  66. len += 1;
  67. break;
  68. }
  69. }
  70. size_t node_next(const char *str, struct node **n)
  71. {
  72. size_t ret = 0;
  73. if (rule_match(&str[ret], OPEN+OL+LI)) {
  74. ret += rule_len(OPEN+OL+LI);
  75. *n = node_create(*n, OPEN+OL);
  76. *n = node_create(*n, OPEN+OL+LI);
  77. *n = node_create(*n, OL+LI);
  78. } else if (rule_match(&str[ret], OPEN+UL+LI)) {
  79. ret += rule_len(OPEN+UL+LI);
  80. *n = node_create(*n, OPEN+UL);
  81. *n = node_create(*n, OPEN+UL+LI);
  82. *n = node_create(*n, UL+LI);
  83. } else if (rule_match(&str[ret], OPEN+PRE)) {
  84. ret += rule_len(OPEN+PRE);
  85. *n = node_create(*n, OPEN+PRE);
  86. *n = node_create(*n, PRE);
  87. } else if (isprint(str[ret])) {
  88. switch (rule_match_heading(&str[ret])) {
  89. case H1:
  90. *n = node_create(*n, OPEN+H1);
  91. *n = node_create(*n, H1);
  92. break;
  93. case H2:
  94. *n = node_create(*n, OPEN+H2);
  95. *n = node_create(*n, H2);
  96. break;
  97. default:
  98. *n = node_create(*n, OPEN+P);
  99. *n = node_create(*n, P);
  100. break;
  101. }
  102. }
  103. return ret;
  104. }