From 3c9bdf645958a1c5b71cc9b96a5b711cca14224f Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Thu, 13 Nov 2014 10:11:46 -0800 Subject: Moved cmark_free_inlines from inlines to ast. --- src/ast.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'src/ast.c') diff --git a/src/ast.c b/src/ast.c index 8ccf184..2a9ca8f 100644 --- a/src/ast.c +++ b/src/ast.c @@ -2,7 +2,6 @@ #include #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; + } +} -- cgit v1.2.3