txt2html

Converts plaintext to HTML
git clone git://src.gearsix.net/txt2html
Log | Files | Refs | Atom | README

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 }