diff options
Diffstat (limited to 'src/ast.c')
-rw-r--r-- | src/ast.c | 53 |
1 files changed, 52 insertions, 1 deletions
@@ -2,7 +2,6 @@ #include <stdio.h> #include "buffer.h" #include "ast.h" -#include "inlines.h" #include "references.h" // Free a node_block list and any children. @@ -28,3 +27,55 @@ void cmark_free_blocks(node_block *e) } } +// Utility function used by free_inlines +static void splice_into_list(node_inl* e, node_inl* children) { + node_inl * tmp; + if (children) { + tmp = children; + // Find last child + while (tmp->next) { + tmp = tmp->next; + } + // Splice children into list + tmp->next = e->next; + e->next = children; + } + return ; +} + +// Free an inline list. Avoid recursion to prevent stack overflows +// on deeply nested structures. +extern void free_inlines(node_inl* e) +{ + node_inl * next; + + while (e != NULL) { + switch (e->tag){ + case INL_STRING: + case INL_RAW_HTML: + case INL_CODE: + chunk_free(&e->content.literal); + break; + case INL_LINEBREAK: + case INL_SOFTBREAK: + break; + case INL_LINK: + case INL_IMAGE: + free(e->content.linkable.url); + free(e->content.linkable.title); + splice_into_list(e, e->content.linkable.label); + break; + case INL_EMPH: + case INL_STRONG: + splice_into_list(e, e->content.inlines); + break; + default: + fprintf(stderr, "[WARN] (%s:%d) Unknown inline tag %d", + __FILE__, __LINE__, e->tag); + break; + } + next = e->next; + free(e); + e = next; + } +} |