summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api_test/main.c39
-rw-r--r--src/blocks.c2
-rw-r--r--src/node.c55
-rw-r--r--src/node.h4
4 files changed, 64 insertions, 36 deletions
diff --git a/api_test/main.c b/api_test/main.c
index 1b5725d..f484a53 100644
--- a/api_test/main.c
+++ b/api_test/main.c
@@ -261,6 +261,22 @@ accessors(test_batch_runner *runner)
}
static void
+node_check(test_batch_runner *runner) {
+ // Construct an incomplete tree.
+ cmark_node *doc = cmark_node_new(CMARK_NODE_DOCUMENT);
+ cmark_node *p1 = cmark_node_new(CMARK_NODE_PARAGRAPH);
+ cmark_node *p2 = cmark_node_new(CMARK_NODE_PARAGRAPH);
+ doc->first_child = p1;
+ p1->next = p2;
+
+ INT_EQ(runner, cmark_node_check(doc, NULL), 4, "node_check works");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0,
+ "node_check fixes tree");
+
+ cmark_node_destroy(doc);
+}
+
+static void
create_tree(test_batch_runner *runner)
{
char *html;
@@ -268,27 +284,27 @@ create_tree(test_batch_runner *runner)
cmark_node *p = cmark_node_new(CMARK_NODE_PARAGRAPH);
OK(runner, cmark_node_append_child(doc, p), "append1");
- INT_EQ(runner, cmark_node_check(doc), 0, "append1 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0, "append1 consistent");
OK(runner, cmark_node_parent(p) == doc, "node_parent");
cmark_node *emph = cmark_node_new(CMARK_NODE_EMPH);
OK(runner, cmark_node_prepend_child(p, emph), "prepend1");
- INT_EQ(runner, cmark_node_check(doc), 0, "prepend1 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0, "prepend1 consistent");
cmark_node *str1 = cmark_node_new(CMARK_NODE_STRING);
cmark_node_set_string_content(str1, "Hello, ");
OK(runner, cmark_node_prepend_child(p, str1), "prepend2");
- INT_EQ(runner, cmark_node_check(doc), 0, "prepend2 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0, "prepend2 consistent");
cmark_node *str3 = cmark_node_new(CMARK_NODE_STRING);
cmark_node_set_string_content(str3, "!");
OK(runner, cmark_node_append_child(p, str3), "append2");
- INT_EQ(runner, cmark_node_check(doc), 0, "append2 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0, "append2 consistent");
cmark_node *str2 = cmark_node_new(CMARK_NODE_STRING);
cmark_node_set_string_content(str2, "world");
OK(runner, cmark_node_append_child(emph, str2), "append3");
- INT_EQ(runner, cmark_node_check(doc), 0, "append3 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0, "append3 consistent");
html = (char *)cmark_render_html(doc);
STR_EQ(runner, html, "<p>Hello, <em>world</em>!</p>\n",
@@ -296,22 +312,26 @@ create_tree(test_batch_runner *runner)
free(html);
OK(runner, cmark_node_insert_before(str1, str3), "ins before1");
- INT_EQ(runner, cmark_node_check(doc), 0, "ins before1 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0,
+ "ins before1 consistent");
// 31e
OK(runner, cmark_node_first_child(p) == str3, "ins before1 works");
OK(runner, cmark_node_insert_before(str1, emph), "ins before2");
- INT_EQ(runner, cmark_node_check(doc), 0, "ins before2 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0,
+ "ins before2 consistent");
// 3e1
OK(runner, cmark_node_last_child(p) == str1, "ins before2 works");
OK(runner, cmark_node_insert_after(str1, str3), "ins after1");
- INT_EQ(runner, cmark_node_check(doc), 0, "ins after1 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0,
+ "ins after1 consistent");
// e13
OK(runner, cmark_node_next(str1) == str3, "ins after1 works");
OK(runner, cmark_node_insert_after(str1, emph), "ins after2");
- INT_EQ(runner, cmark_node_check(doc), 0, "ins after2 consistent");
+ INT_EQ(runner, cmark_node_check(doc, NULL), 0,
+ "ins after2 consistent");
// 1e3
OK(runner, cmark_node_previous(emph) == str1, "ins after2 works");
@@ -425,6 +445,7 @@ int main() {
constructor(runner);
accessors(runner);
+ node_check(runner);
create_tree(runner);
hierarchy(runner);
diff --git a/src/blocks.c b/src/blocks.c
index 58162b5..ab9f667 100644
--- a/src/blocks.c
+++ b/src/blocks.c
@@ -818,7 +818,7 @@ cmark_node *cmark_finish(cmark_doc_parser *parser)
finalize_document(parser);
strbuf_free(parser->curline);
#if CMARK_DEBUG_NODES
- if (cmark_node_check(parser->root)) {
+ if (cmark_node_check(parser->root, stderr)) {
abort();
}
#endif
diff --git a/src/node.c b/src/node.c
index bb9cacc..a79dd82 100644
--- a/src/node.c
+++ b/src/node.c
@@ -558,58 +558,63 @@ cmark_node_append_child(cmark_node *node, cmark_node *child)
}
static void
-S_print_error(cmark_node *node, const char *elem)
+S_print_error(FILE *out, cmark_node *node, const char *elem)
{
- fprintf(stderr, "Invalid '%s' in node type %s at %d:%d\n", elem,
+ if (out == NULL) {
+ return;
+ }
+ fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem,
S_type_string(node), node->start_line, node->start_column);
}
int
-cmark_node_check(cmark_node *node)
+cmark_node_check(cmark_node *node, FILE *out)
{
- cmark_node *cur = node;
+ cmark_node *cur;
int errors = 0;
- while (cur) {
+ if (!node) {
+ return 0;
+ }
+
+ cur = node;
+ while (true) {
if (cur->first_child) {
if (cur->first_child->parent != cur) {
- S_print_error(cur->first_child, "parent");
+ S_print_error(out, cur->first_child, "parent");
cur->first_child->parent = cur;
++errors;
}
cur = cur->first_child;
+ continue;
+ }
+
+ next_sibling:
+ if (cur == node) {
+ break;
}
- else if (cur->next) {
+ if (cur->next) {
if (cur->next->prev != cur) {
- S_print_error(cur->next, "prev");
+ S_print_error(out, cur->next, "prev");
cur->next->prev = cur;
++errors;
}
if (cur->next->parent != cur->parent) {
- S_print_error(cur->next, "parent");
+ S_print_error(out, cur->next, "parent");
cur->next->parent = cur->parent;
++errors;
}
cur = cur->next;
+ continue;
}
- else {
- if (cur->parent->last_child != cur) {
- S_print_error(cur->parent, "last_child");
- cur->parent->last_child = cur;
- ++errors;
- }
- cmark_node *ancestor = cur->parent;
- cur = NULL;
-
- while (ancestor != node->parent) {
- if (ancestor->next) {
- cur = ancestor->next;
- break;
- }
- ancestor = ancestor->parent;
- }
+ if (cur->parent->last_child != cur) {
+ S_print_error(out, cur->parent, "last_child");
+ cur->parent->last_child = cur;
+ ++errors;
}
+ cur = cur->parent;
+ goto next_sibling;
}
return errors;
diff --git a/src/node.h b/src/node.h
index 2d7f0a1..d1245a5 100644
--- a/src/node.h
+++ b/src/node.h
@@ -5,6 +5,8 @@
extern "C" {
#endif
+#include <stdio.h>
+
#include "cmark.h"
#include "buffer.h"
#include "chunk.h"
@@ -62,7 +64,7 @@ struct cmark_node {
};
CMARK_EXPORT int
-cmark_node_check(cmark_node *node);
+cmark_node_check(cmark_node *node, FILE *out);
#ifdef __cplusplus
}