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