parse.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "txt2html.h"
  2. struct node *parse_buf(const char *buf, struct node **n, uint8_t opts)
  3. {
  4. size_t i = 0;
  5. size_t len = (buf) ? strlen(buf) : 0;
  6. if (!buf && (*n)) {
  7. *n = node_create(*n, CLOSE+(*n)->type);
  8. i = len;
  9. }
  10. while (i < len && buf) {
  11. while (buf[i] == '\n') ++i;
  12. if (!(*n) || ((*n)->type & CLOSE))
  13. i += node_next(&buf[i], n);
  14. switch ((*n)->type) {
  15. case H1:
  16. case H2:
  17. i += parse_heading(&buf[i], n);
  18. break;
  19. case P: i += parse_p(&buf[i], n, opts); break;
  20. case OL+LI: i += parse_oli(&buf[i], n, opts); break;
  21. case UL+LI: i += parse_uli(&buf[i], n, opts); break;
  22. case PRE:
  23. i += parse_textblock(&buf[i], n, opts & OPT_BR);
  24. *n = node_create(*n, CLOSE+PRE);
  25. break;
  26. default:
  27. i += node_next(&buf[i], n);
  28. break;
  29. }
  30. }
  31. return *n;
  32. }
  33. size_t parse_textblock(const char *str, struct node **n, bool softbreaks)
  34. {
  35. size_t ret = 0;
  36. while (str[ret] != '\0' && (isprint(str[ret]) || str[ret] == '\n' || str[ret] == '\t')) {
  37. if (str[ret] == '\n' && str[ret+1] == '\n')
  38. break;
  39. else if ((*n)->type == PRE && str[ret] == '\t')
  40. ++ret;
  41. else if (str[ret] == '\n') {
  42. if (((*n)->type & (OL+LI) && rule_match(&str[ret+1], OPEN+OL+LI)) ||
  43. ((*n)->type & (UL+LI) && rule_match(&str[ret+1], OPEN+UL+LI))) {
  44. ++ret;
  45. break;
  46. }
  47. if ((*n)->type == PRE && str[ret+1] == '\t') {
  48. node_writec(n, '\n');
  49. ++ret;
  50. } else if ((*n)->type == PRE && str[ret+1] != '\t') {
  51. break;
  52. } else if (softbreaks) {
  53. *n = node_create(*n, OPEN+BR+CLOSE);
  54. *n = node_create(*n, (*n)->prev->type);
  55. } else {
  56. node_writec(n, str[ret]);
  57. }
  58. } else {
  59. node_writec(n, str[ret]);
  60. }
  61. ++ret;
  62. }
  63. node_writec(n, EOF);
  64. return ret;
  65. }
  66. size_t parse_heading(const char *str, struct node **n)
  67. {
  68. assert(str);
  69. size_t i = 0;
  70. while(str[i] && str[i] != '\n')
  71. node_writec(n, str[i++]);
  72. node_writec(n, EOF);
  73. do { ++i; } while (str[i] == '-' || str[i] == '=');
  74. *n = node_create(*n, CLOSE+(*n)->type);
  75. return i;
  76. }
  77. size_t parse_oli(const char *str, struct node **n, uint8_t opts)
  78. {
  79. assert(str);
  80. size_t i = 0, len = strlen(str);
  81. while(i < len) {
  82. i += parse_textblock(&str[i], n, opts & OPT_BR);
  83. *n = node_create(*n, CLOSE+OL+LI);
  84. if (str[i] == '\0' || rule_match(&str[i], CLOSE+OL)) {
  85. i += rule_len(CLOSE+OL);
  86. *n = node_create(*n, CLOSE+OL);
  87. break;
  88. } else if (rule_match(&str[i], OPEN+OL+LI)) {
  89. i += rule_len(OPEN+OL+LI);
  90. *n = node_create(*n, OPEN+OL+LI);
  91. *n = node_create(*n, OL+LI);
  92. }
  93. }
  94. return i;
  95. }
  96. size_t parse_p(const char *str, struct node **n, uint8_t opts)
  97. {
  98. size_t i = parse_textblock(str, n, opts & OPT_BR);
  99. if (str[i] == '\n' && str[i+1] == '\n')
  100. *n = node_create(*n, CLOSE+P);
  101. return i;
  102. }
  103. size_t parse_uli(const char *str, struct node **n, uint8_t opts)
  104. {
  105. size_t ret = 0;
  106. size_t len = strlen(str);
  107. while (ret < len) {
  108. ret += parse_textblock(&str[ret], n, opts & OPT_BR);
  109. *n = node_create(*n, CLOSE+UL+LI);
  110. if (str[ret] == '\0' || rule_match(&str[ret], CLOSE+UL)) {
  111. ret += rule_len(CLOSE+UL);
  112. *n = node_create(*n, CLOSE+UL);
  113. break;
  114. } else if (rule_match(&str[ret], OPEN+UL+LI)) {
  115. ret += rule_len(OPEN+UL+LI);
  116. *n = node_create(*n, OPEN+UL+LI);
  117. *n = node_create(*n, UL+LI);
  118. } else break;
  119. }
  120. return ret;
  121. }