diff options
author | John MacFarlane <jgm@berkeley.edu> | 2014-11-05 09:49:05 -0800 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2014-11-05 09:49:05 -0800 |
commit | 90c48e849440e50b3fef21f0cd6c38b998490073 (patch) | |
tree | 9fef39485b98b5ba07de88487c6d564f79d378f4 /src/inlines.c | |
parent | 9d33831ee4008a795ccec026ce65e424d15f9eaa (diff) |
free_inlines: use non-recursive algorithm.
This will help avoid stack overflows in deeply nested structures.
Partially addresses #187 (still need to do renderers).
Diffstat (limited to 'src/inlines.c')
-rw-r--r-- | src/inlines.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/src/inlines.c b/src/inlines.c index 2fe0caa..1ab1b29 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -121,10 +121,29 @@ inline static node_inl* make_simple(int t) #define make_emph(contents) make_inlines(INL_EMPH, contents) #define make_strong(contents) make_inlines(INL_STRONG, contents) -// Free an inline list. +// Utility function used by free_inlines +void splice_into_list(node_inl* e, node_inl* children) { + node_inl * tmp; + tmp = children; + if (!tmp) { + return ; + } + // 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: @@ -139,11 +158,11 @@ extern void free_inlines(node_inl* e) case INL_IMAGE: free(e->content.linkable.url); free(e->content.linkable.title); - free_inlines(e->content.linkable.label); + splice_into_list(e, e->content.linkable.label); break; case INL_EMPH: case INL_STRONG: - free_inlines(e->content.inlines); + splice_into_list(e, e->content.inlines); break; default: break; |