diff options
Diffstat (limited to 'src/blocks.c')
-rw-r--r-- | src/blocks.c | 124 |
1 files changed, 78 insertions, 46 deletions
diff --git a/src/blocks.c b/src/blocks.c index 7613c82..ccb84a7 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -20,14 +20,14 @@ static node_block* make_block(int tag, int start_line, int start_column) node_block* e; e = calloc(1, sizeof(*e)); - if(e != NULL) { - e->tag = tag; - e->open = true; - e->start_line = start_line; - e->start_column = start_column; - e->end_line = start_line; - strbuf_init(&e->string_content, 32); - } + if(e != NULL) { + e->tag = tag; + e->open = true; + e->start_line = start_line; + e->start_column = start_column; + e->end_line = start_line; + strbuf_init(&e->string_content, 32); + } return e; } @@ -252,12 +252,12 @@ static node_block* add_child(node_block* parent, return child; } + // Free a node_block list and any children. void cmark_free_nodes(node_block *e) { node_block * next; while (e != NULL) { - next = e->next; free_inlines(e->inline_content); strbuf_free(&e->string_content); if (e->tag == BLOCK_FENCED_CODE) { @@ -265,31 +265,63 @@ void cmark_free_nodes(node_block *e) } else if (e->tag == BLOCK_DOCUMENT) { reference_map_free(e->as.document.refmap); } - cmark_free_nodes(e->children); + if (e->last_child) { + // Splice children into list + e->last_child->next = e->next; + e->next = e->children; + } + next = e->next; free(e); e = next; } } +typedef struct BlockStack { + struct BlockStack *previous; + node_block *next_sibling; +} block_stack; + // Walk through node_block and all children, recursively, parsing // string content into inline content where appropriate. void process_inlines(node_block* cur, reference_map *refmap) { - switch (cur->tag) { - case BLOCK_PARAGRAPH: - case BLOCK_ATX_HEADER: - case BLOCK_SETEXT_HEADER: - cur->inline_content = parse_inlines(&cur->string_content, refmap); - break; + block_stack* stack = NULL; + block_stack* newstack = NULL; + + while (cur != NULL) { + switch (cur->tag) { + case BLOCK_PARAGRAPH: + case BLOCK_ATX_HEADER: + case BLOCK_SETEXT_HEADER: + cur->inline_content = parse_inlines(&cur->string_content, refmap); + break; - default: - break; - } + default: + break; + } - node_block *child = cur->children; - while (child != NULL) { - process_inlines(child, refmap); - child = child->next; + if (cur->children) { + newstack = (block_stack*)malloc(sizeof(block_stack)); + if (newstack == NULL) return; + newstack->previous = stack; + stack = newstack; + stack->next_sibling = cur->next; + cur = cur->children; + } else { + cur = cur->next; + } + + while (cur == NULL && stack != NULL) { + cur = stack->next_sibling; + newstack = stack->previous; + free(stack); + stack = newstack; + } + } + while (stack != NULL) { + newstack = stack->previous; + free(stack); + stack = newstack; } } @@ -311,16 +343,16 @@ static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr) return 0; } data = calloc(1, sizeof(*data)); - if(data == NULL) { - return 0; - } else { - data->marker_offset = 0; // will be adjusted later - data->list_type = bullet; - data->bullet_char = c; - data->start = 1; - data->delimiter = period; - data->tight = false; - } + if(data == NULL) { + return 0; + } else { + data->marker_offset = 0; // will be adjusted later + data->list_type = bullet; + data->bullet_char = c; + data->start = 1; + data->delimiter = period; + data->tight = false; + } } else if (isdigit(c)) { int start = 0; @@ -336,16 +368,16 @@ static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr) return 0; } data = calloc(1, sizeof(*data)); - if(data == NULL) { - return 0; - } else { - data->marker_offset = 0; // will be adjusted later - data->list_type = ordered; - data->bullet_char = 0; - data->start = start; - data->delimiter = (c == '.' ? period : parens); - data->tight = false; - } + if(data == NULL) { + return 0; + } else { + data->marker_offset = 0; // will be adjusted later + data->list_type = ordered; + data->bullet_char = 0; + data->start = start; + data->delimiter = (c == '.' ? period : parens); + data->tight = false; + } } else { return 0; } @@ -438,8 +470,8 @@ static void chop_trailing_hashtags(chunk *ch) // Check for a be a space before the final #s: if (n != orig_n && n >= 0 && peek_at(ch, n) == ' ') { - ch->len = n; - chunk_rtrim(ch); + ch->len = n; + chunk_rtrim(ch); } } @@ -462,7 +494,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) // Add a newline to the end if not present: if (line->ptr[line->size - 1] != '\n') { - strbuf_putc(line, '\n'); + strbuf_putc(line, '\n'); } input.data = line->ptr; input.len = line->size; |