diff options
author | John MacFarlane <fiddlosopher@gmail.com> | 2014-11-13 10:11:46 -0800 |
---|---|---|
committer | John MacFarlane <fiddlosopher@gmail.com> | 2014-11-13 10:11:46 -0800 |
commit | 3c9bdf645958a1c5b71cc9b96a5b711cca14224f (patch) | |
tree | cd9bb05022d69a017fe8adf63fc8d5f2d5d4480c /src/ast.c | |
parent | e5fd42248067b4e8f29a9c2ed9d224ded4526c24 (diff) |
Moved cmark_free_inlines from inlines to ast.
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; + } +} |