@@ -70,6 +70,22 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
70
70
static void S_process_line (cmark_parser * parser , const unsigned char * buffer ,
71
71
bufsize_t bytes );
72
72
73
+ static void subtract_open_block_counts (cmark_parser * parser , cmark_node * node ) {
74
+ do {
75
+ decr_open_block_count (parser , S_type (node ));
76
+ node -> flags &= ~CMARK_NODE__OPEN_BLOCK ;
77
+ node = node -> last_child ;
78
+ } while (node );
79
+ }
80
+
81
+ static void add_open_block_counts (cmark_parser * parser , cmark_node * node ) {
82
+ do {
83
+ incr_open_block_count (parser , S_type (node ));
84
+ node -> flags |= CMARK_NODE__OPEN_BLOCK ;
85
+ node = node -> last_child ;
86
+ } while (node );
87
+ }
88
+
73
89
static cmark_node * make_block (cmark_mem * mem , cmark_node_type tag ,
74
90
int start_line , int start_column ) {
75
91
cmark_node * e ;
@@ -129,6 +145,7 @@ static void cmark_parser_reset(cmark_parser *parser) {
129
145
parser -> refmap = cmark_reference_map_new (parser -> mem );
130
146
parser -> root = document ;
131
147
parser -> current = document ;
148
+ add_open_block_counts (parser , document );
132
149
133
150
parser -> syntax_extensions = saved_exts ;
134
151
parser -> inline_syntax_extensions = saved_inline_exts ;
@@ -310,6 +327,12 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
310
327
has_content = resolve_reference_link_definitions (parser , b );
311
328
if (!has_content ) {
312
329
// remove blank node (former reference def)
330
+ if (b -> flags & CMARK_NODE__OPEN_BLOCK ) {
331
+ decr_open_block_count (parser , S_type (b ));
332
+ if (b -> prev ) {
333
+ add_open_block_counts (parser , b -> prev );
334
+ }
335
+ }
313
336
cmark_node_free (b );
314
337
}
315
338
break ;
@@ -382,6 +405,15 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
382
405
return parent ;
383
406
}
384
407
408
+ // Recalculates the number of open blocks. Returns true if it matches what's currently stored
409
+ // in parser. (Used to check that the counts in parser, which are updated incrementally, are
410
+ // correct.)
411
+ bool check_open_block_counts (cmark_parser * parser ) {
412
+ cmark_parser tmp_parser = {0 }; // Only used for its open_block_counts field.
413
+ add_open_block_counts (& tmp_parser , parser -> root );
414
+ return memcmp (tmp_parser .open_block_counts , parser -> open_block_counts , sizeof (parser -> open_block_counts )) == 0 ;
415
+ }
416
+
385
417
// Add a node as child of another. Return pointer to child.
386
418
static cmark_node * add_child (cmark_parser * parser , cmark_node * parent ,
387
419
cmark_node_type block_type , int start_column ) {
@@ -400,11 +432,14 @@ static cmark_node *add_child(cmark_parser *parser, cmark_node *parent,
400
432
if (parent -> last_child ) {
401
433
parent -> last_child -> next = child ;
402
434
child -> prev = parent -> last_child ;
435
+ subtract_open_block_counts (parser , parent -> last_child );
403
436
} else {
404
437
parent -> first_child = child ;
405
438
child -> prev = NULL ;
406
439
}
407
440
parent -> last_child = child ;
441
+ add_open_block_counts (parser , child );
442
+
408
443
return child ;
409
444
}
410
445
@@ -1048,6 +1083,8 @@ static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input,
1048
1083
cmark_node * container = parser -> root ;
1049
1084
cmark_node_type cont_type ;
1050
1085
1086
+ assert (check_open_block_counts (parser ));
1087
+
1051
1088
while (S_last_child_is_open (container )) {
1052
1089
container = container -> last_child ;
1053
1090
cont_type = S_type (container );
@@ -1193,8 +1230,9 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
1193
1230
has_content = resolve_reference_link_definitions (parser , * container );
1194
1231
1195
1232
if (has_content ) {
1196
-
1197
- (* container )-> type = (uint16_t )CMARK_NODE_HEADING ;
1233
+ cmark_node_set_type (* container , CMARK_NODE_HEADING );
1234
+ decr_open_block_count (parser , CMARK_NODE_PARAGRAPH );
1235
+ incr_open_block_count (parser , CMARK_NODE_HEADING );
1198
1236
(* container )-> as .heading .level = lev ;
1199
1237
(* container )-> as .heading .setext = true;
1200
1238
S_advance_offset (parser , input , input -> len - 1 - parser -> offset , false);
@@ -1478,6 +1516,7 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
1478
1516
1479
1517
parser -> line_number ++ ;
1480
1518
1519
+ assert (parser -> current -> next == NULL );
1481
1520
last_matched_container = check_open_blocks (parser , & input , & all_matched );
1482
1521
1483
1522
if (!last_matched_container )
0 commit comments