summaryrefslogtreecommitdiff
path: root/src/blocks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/blocks.c')
-rw-r--r--src/blocks.c124
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;