commonmarker 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of commonmarker might be problematic. Click here for more details.

Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/ext/commonmarker/cmark/CMakeLists.txt +10 -4
  3. data/ext/commonmarker/cmark/Makefile +5 -5
  4. data/ext/commonmarker/cmark/api_test/CMakeLists.txt +1 -1
  5. data/ext/commonmarker/cmark/api_test/main.c +16 -0
  6. data/ext/commonmarker/cmark/build/CMakeCache.txt +3 -4
  7. data/ext/commonmarker/cmark/build/CMakeFiles/2.8.10.1/CMakeSystem.cmake +4 -4
  8. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +12 -12
  9. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +97 -142
  10. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile.cmake +0 -1
  11. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/build.make +1 -1
  12. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/link.txt +1 -1
  13. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/DependInfo.cmake +1 -1
  14. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/build.make +23 -23
  15. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmake_clean.cmake +2 -2
  16. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/link.txt +1 -1
  17. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/blocks.c.o +0 -0
  18. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/buffer.c.o +0 -0
  19. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark.c.o +0 -0
  20. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/commonmark.c.o +0 -0
  21. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_u.c.o +0 -0
  22. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/html.c.o +0 -0
  23. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/inlines.c.o +0 -0
  24. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/node.c.o +0 -0
  25. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/references.c.o +0 -0
  26. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/render.c.o +0 -0
  27. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/scanners.c.o +0 -0
  28. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/utf8.c.o +0 -0
  29. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/xml.c.o +0 -0
  30. data/ext/commonmarker/cmark/build/src/cmake_install.cmake +3 -3
  31. data/ext/commonmarker/cmark/build/src/cmark_version.h +2 -2
  32. data/ext/commonmarker/cmark/build/src/config.h +6 -6
  33. data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
  34. data/ext/commonmarker/cmark/build/src/libcmark.pc +1 -1
  35. data/ext/commonmarker/cmark/build/testdir/CTestTestfile.cmake +4 -4
  36. data/ext/commonmarker/cmark/changelog.txt +46 -0
  37. data/ext/commonmarker/cmark/man/man3/cmark.3 +21 -20
  38. data/ext/commonmarker/cmark/src/CMakeLists.txt +4 -6
  39. data/ext/commonmarker/cmark/src/bench.h +8 -8
  40. data/ext/commonmarker/cmark/src/blocks.c +917 -947
  41. data/ext/commonmarker/cmark/src/buffer.c +213 -288
  42. data/ext/commonmarker/cmark/src/buffer.h +19 -21
  43. data/ext/commonmarker/cmark/src/chunk.h +78 -82
  44. data/ext/commonmarker/cmark/src/cmark.c +9 -17
  45. data/ext/commonmarker/cmark/src/cmark.h +113 -157
  46. data/ext/commonmarker/cmark/src/cmark_ctype.c +24 -35
  47. data/ext/commonmarker/cmark/src/commonmark.c +390 -425
  48. data/ext/commonmarker/cmark/src/config.h.in +6 -6
  49. data/ext/commonmarker/cmark/src/houdini.h +21 -15
  50. data/ext/commonmarker/cmark/src/houdini_href_e.c +50 -57
  51. data/ext/commonmarker/cmark/src/houdini_html_e.c +36 -51
  52. data/ext/commonmarker/cmark/src/houdini_html_u.c +119 -124
  53. data/ext/commonmarker/cmark/src/html.c +289 -307
  54. data/ext/commonmarker/cmark/src/inlines.c +976 -1030
  55. data/ext/commonmarker/cmark/src/inlines.h +4 -2
  56. data/ext/commonmarker/cmark/src/iterator.c +96 -126
  57. data/ext/commonmarker/cmark/src/iterator.h +5 -5
  58. data/ext/commonmarker/cmark/src/latex.c +379 -401
  59. data/ext/commonmarker/cmark/src/main.c +168 -175
  60. data/ext/commonmarker/cmark/src/man.c +212 -226
  61. data/ext/commonmarker/cmark/src/node.c +746 -839
  62. data/ext/commonmarker/cmark/src/node.h +47 -48
  63. data/ext/commonmarker/cmark/src/parser.h +14 -14
  64. data/ext/commonmarker/cmark/src/references.c +101 -111
  65. data/ext/commonmarker/cmark/src/references.h +10 -8
  66. data/ext/commonmarker/cmark/src/render.c +144 -167
  67. data/ext/commonmarker/cmark/src/render.h +22 -41
  68. data/ext/commonmarker/cmark/src/scanners.c +27695 -20903
  69. data/ext/commonmarker/cmark/src/scanners.h +2 -1
  70. data/ext/commonmarker/cmark/src/scanners.re +1 -1
  71. data/ext/commonmarker/cmark/src/utf8.c +276 -419
  72. data/ext/commonmarker/cmark/src/utf8.h +6 -6
  73. data/ext/commonmarker/cmark/src/xml.c +129 -144
  74. data/ext/commonmarker/cmark/test/CMakeLists.txt +4 -4
  75. data/ext/commonmarker/cmark/test/smart_punct.txt +8 -0
  76. data/ext/commonmarker/cmark/test/spec.txt +109 -47
  77. data/lib/commonmarker/version.rb +1 -1
  78. metadata +2 -2
@@ -4,855 +4,762 @@
4
4
  #include "config.h"
5
5
  #include "node.h"
6
6
 
7
- static void
8
- S_node_unlink(cmark_node *node);
9
-
10
- static inline bool
11
- S_is_block(cmark_node *node)
12
- {
13
- if (node == NULL) {
14
- return false;
15
- }
16
- return node->type >= CMARK_NODE_FIRST_BLOCK
17
- && node->type <= CMARK_NODE_LAST_BLOCK;
18
- }
19
-
20
- static inline bool
21
- S_is_inline(cmark_node *node)
22
- {
23
- if (node == NULL) {
24
- return false;
25
- }
26
- return node->type >= CMARK_NODE_FIRST_INLINE
27
- && node->type <= CMARK_NODE_LAST_INLINE;
28
- }
29
-
30
- static bool
31
- S_can_contain(cmark_node *node, cmark_node *child)
32
- {
33
- cmark_node *cur;
34
-
35
- if (node == NULL || child == NULL) {
36
- return false;
37
- }
38
-
39
- // Verify that child is not an ancestor of node or equal to node.
40
- cur = node;
41
- do {
42
- if (cur == child) {
43
- return false;
44
- }
45
- cur = cur->parent;
46
- } while (cur != NULL);
47
-
48
- if (child->type == CMARK_NODE_DOCUMENT) {
49
- return false;
50
- }
51
-
52
- switch (node->type) {
53
- case CMARK_NODE_DOCUMENT:
54
- case CMARK_NODE_BLOCK_QUOTE:
55
- case CMARK_NODE_ITEM:
56
- return S_is_block(child)
57
- && child->type != CMARK_NODE_ITEM;
58
-
59
- case CMARK_NODE_LIST:
60
- return child->type == CMARK_NODE_ITEM;
61
-
62
- case CMARK_NODE_PARAGRAPH:
63
- case CMARK_NODE_HEADER:
64
- case CMARK_NODE_EMPH:
65
- case CMARK_NODE_STRONG:
66
- case CMARK_NODE_LINK:
67
- case CMARK_NODE_IMAGE:
68
- return S_is_inline(child);
69
-
70
- default:
71
- break;
72
- }
73
-
74
- return false;
75
- }
76
-
77
- cmark_node*
78
- cmark_node_new(cmark_node_type type)
79
- {
80
- cmark_node *node = (cmark_node *)calloc(1, sizeof(*node));
81
- node->type = type;
82
-
83
- switch (node->type) {
84
- case CMARK_NODE_HEADER:
85
- node->as.header.level = 1;
86
- break;
87
-
88
- case CMARK_NODE_LIST: {
89
- cmark_list *list = &node->as.list;
90
- list->list_type = CMARK_BULLET_LIST;
91
- list->start = 1;
92
- list->tight = false;
93
- break;
94
- }
95
-
96
- default:
97
- break;
98
- }
99
-
100
- return node;
7
+ static void S_node_unlink(cmark_node *node);
8
+
9
+ static inline bool S_is_block(cmark_node *node) {
10
+ if (node == NULL) {
11
+ return false;
12
+ }
13
+ return node->type >= CMARK_NODE_FIRST_BLOCK &&
14
+ node->type <= CMARK_NODE_LAST_BLOCK;
15
+ }
16
+
17
+ static inline bool S_is_inline(cmark_node *node) {
18
+ if (node == NULL) {
19
+ return false;
20
+ }
21
+ return node->type >= CMARK_NODE_FIRST_INLINE &&
22
+ node->type <= CMARK_NODE_LAST_INLINE;
23
+ }
24
+
25
+ static bool S_can_contain(cmark_node *node, cmark_node *child) {
26
+ cmark_node *cur;
27
+
28
+ if (node == NULL || child == NULL) {
29
+ return false;
30
+ }
31
+
32
+ // Verify that child is not an ancestor of node or equal to node.
33
+ cur = node;
34
+ do {
35
+ if (cur == child) {
36
+ return false;
37
+ }
38
+ cur = cur->parent;
39
+ } while (cur != NULL);
40
+
41
+ if (child->type == CMARK_NODE_DOCUMENT) {
42
+ return false;
43
+ }
44
+
45
+ switch (node->type) {
46
+ case CMARK_NODE_DOCUMENT:
47
+ case CMARK_NODE_BLOCK_QUOTE:
48
+ case CMARK_NODE_ITEM:
49
+ return S_is_block(child) && child->type != CMARK_NODE_ITEM;
50
+
51
+ case CMARK_NODE_LIST:
52
+ return child->type == CMARK_NODE_ITEM;
53
+
54
+ case CMARK_NODE_PARAGRAPH:
55
+ case CMARK_NODE_HEADER:
56
+ case CMARK_NODE_EMPH:
57
+ case CMARK_NODE_STRONG:
58
+ case CMARK_NODE_LINK:
59
+ case CMARK_NODE_IMAGE:
60
+ return S_is_inline(child);
61
+
62
+ default:
63
+ break;
64
+ }
65
+
66
+ return false;
67
+ }
68
+
69
+ cmark_node *cmark_node_new(cmark_node_type type) {
70
+ cmark_node *node = (cmark_node *)calloc(1, sizeof(*node));
71
+ node->type = type;
72
+
73
+ switch (node->type) {
74
+ case CMARK_NODE_HEADER:
75
+ node->as.header.level = 1;
76
+ break;
77
+
78
+ case CMARK_NODE_LIST: {
79
+ cmark_list *list = &node->as.list;
80
+ list->list_type = CMARK_BULLET_LIST;
81
+ list->start = 1;
82
+ list->tight = false;
83
+ break;
84
+ }
85
+
86
+ default:
87
+ break;
88
+ }
89
+
90
+ return node;
101
91
  }
102
92
 
103
93
  // Free a cmark_node list and any children.
104
- static
105
- void S_free_nodes(cmark_node *e)
106
- {
107
- cmark_node *next;
108
- while (e != NULL) {
109
- if (S_is_block(e)) {
110
- cmark_strbuf_free(&e->string_content);
111
- }
112
- switch (e->type) {
113
- case NODE_CODE_BLOCK:
114
- cmark_chunk_free(&e->as.code.info);
115
- cmark_chunk_free(&e->as.code.literal);
116
- break;
117
- case NODE_TEXT:
118
- case NODE_INLINE_HTML:
119
- case NODE_CODE:
120
- case NODE_HTML:
121
- cmark_chunk_free(&e->as.literal);
122
- break;
123
- case NODE_LINK:
124
- case NODE_IMAGE:
125
- cmark_chunk_free(&e->as.link.url);
126
- cmark_chunk_free(&e->as.link.title);
127
- break;
128
- default:
129
- break;
130
- }
131
- if (e->last_child) {
132
- // Splice children into list
133
- e->last_child->next = e->next;
134
- e->next = e->first_child;
135
- }
136
- next = e->next;
137
- free(e);
138
- e = next;
139
- }
140
- }
141
-
142
- void
143
- cmark_node_free(cmark_node *node)
144
- {
145
- S_node_unlink(node);
146
- node->next = NULL;
147
- S_free_nodes(node);
148
- }
149
-
150
- cmark_node_type
151
- cmark_node_get_type(cmark_node *node)
152
- {
153
- if (node == NULL) {
154
- return CMARK_NODE_NONE;
155
- } else {
156
- return node->type;
157
- }
158
- }
159
-
160
- const char*
161
- cmark_node_get_type_string(cmark_node *node)
162
- {
163
- if (node == NULL) {
164
- return "NONE";
165
- }
166
-
167
- switch (node->type) {
168
- case CMARK_NODE_NONE:
169
- return "none";
170
- case CMARK_NODE_DOCUMENT:
171
- return "document";
172
- case CMARK_NODE_BLOCK_QUOTE:
173
- return "block_quote";
174
- case CMARK_NODE_LIST:
175
- return "list";
176
- case CMARK_NODE_ITEM:
177
- return "item";
178
- case CMARK_NODE_CODE_BLOCK:
179
- return "code_block";
180
- case CMARK_NODE_HTML:
181
- return "html";
182
- case CMARK_NODE_PARAGRAPH:
183
- return "paragraph";
184
- case CMARK_NODE_HEADER:
185
- return "header";
186
- case CMARK_NODE_HRULE:
187
- return "hrule";
188
- case CMARK_NODE_TEXT:
189
- return "text";
190
- case CMARK_NODE_SOFTBREAK:
191
- return "softbreak";
192
- case CMARK_NODE_LINEBREAK:
193
- return "linebreak";
194
- case CMARK_NODE_CODE:
195
- return "code";
196
- case CMARK_NODE_INLINE_HTML:
197
- return "inline_html";
198
- case CMARK_NODE_EMPH:
199
- return "emph";
200
- case CMARK_NODE_STRONG:
201
- return "strong";
202
- case CMARK_NODE_LINK:
203
- return "link";
204
- case CMARK_NODE_IMAGE:
205
- return "image";
206
- }
207
-
208
- return "<unknown>";
209
- }
210
-
211
- cmark_node*
212
- cmark_node_next(cmark_node *node)
213
- {
214
- if (node == NULL) {
215
- return NULL;
216
- } else {
217
- return node->next;
218
- }
219
- }
220
-
221
- cmark_node*
222
- cmark_node_previous(cmark_node *node)
223
- {
224
- if (node == NULL) {
225
- return NULL;
226
- } else {
227
- return node->prev;
228
- }
229
- }
230
-
231
- cmark_node*
232
- cmark_node_parent(cmark_node *node)
233
- {
234
- if (node == NULL) {
235
- return NULL;
236
- } else {
237
- return node->parent;
238
- }
239
- }
240
-
241
- cmark_node*
242
- cmark_node_first_child(cmark_node *node)
243
- {
244
- if (node == NULL) {
245
- return NULL;
246
- } else {
247
- return node->first_child;
248
- }
249
- }
250
-
251
- cmark_node*
252
- cmark_node_last_child(cmark_node *node)
253
- {
254
- if (node == NULL) {
255
- return NULL;
256
- } else {
257
- return node->last_child;
258
- }
259
- }
260
-
261
- void*
262
- cmark_node_get_user_data(cmark_node *node)
263
- {
264
- if (node == NULL) {
265
- return NULL;
266
- } else {
267
- return node->user_data;
268
- }
269
- }
270
-
271
- int
272
- cmark_node_set_user_data(cmark_node *node, void *user_data)
273
- {
274
- if (node == NULL) {
275
- return 0;
276
- }
277
- node->user_data = user_data;
278
- return 1;
279
- }
280
-
281
- const char*
282
- cmark_node_get_literal(cmark_node *node)
283
- {
284
- if (node == NULL) {
285
- return NULL;
286
- }
287
-
288
- switch (node->type) {
289
- case NODE_HTML:
290
- case NODE_TEXT:
291
- case NODE_INLINE_HTML:
292
- case NODE_CODE:
293
- return cmark_chunk_to_cstr(&node->as.literal);
294
-
295
- case NODE_CODE_BLOCK:
296
- return cmark_chunk_to_cstr(&node->as.code.literal);
297
-
298
- default:
299
- break;
300
- }
301
-
302
- return NULL;
303
- }
304
-
305
- int
306
- cmark_node_set_literal(cmark_node *node, const char *content)
307
- {
308
- if (node == NULL) {
309
- return 0;
310
- }
311
-
312
- switch (node->type) {
313
- case NODE_HTML:
314
- case NODE_TEXT:
315
- case NODE_INLINE_HTML:
316
- case NODE_CODE:
317
- cmark_chunk_set_cstr(&node->as.literal, content);
318
- return 1;
319
-
320
- case NODE_CODE_BLOCK:
321
- cmark_chunk_set_cstr(&node->as.code.literal, content);
322
- return 1;
323
-
324
- default:
325
- break;
326
- }
327
-
328
- return 0;
329
- }
330
-
331
- int
332
- cmark_node_get_header_level(cmark_node *node)
333
- {
334
- if (node == NULL) {
335
- return 0;
336
- }
337
-
338
- switch (node->type) {
339
- case CMARK_NODE_HEADER:
340
- return node->as.header.level;
341
-
342
- default:
343
- break;
344
- }
345
-
346
- return 0;
347
- }
348
-
349
- int
350
- cmark_node_set_header_level(cmark_node *node, int level)
351
- {
352
- if (node == NULL || level < 1 || level > 6) {
353
- return 0;
354
- }
355
-
356
- switch (node->type) {
357
- case CMARK_NODE_HEADER:
358
- node->as.header.level = level;
359
- return 1;
360
-
361
- default:
362
- break;
363
- }
364
-
365
- return 0;
366
- }
367
-
368
- cmark_list_type
369
- cmark_node_get_list_type(cmark_node *node)
370
- {
371
- if (node == NULL) {
372
- return CMARK_NO_LIST;
373
- }
374
-
375
- if (node->type == CMARK_NODE_LIST) {
376
- return node->as.list.list_type;
377
- } else {
378
- return CMARK_NO_LIST;
379
- }
380
- }
381
-
382
- int
383
- cmark_node_set_list_type(cmark_node *node, cmark_list_type type)
384
- {
385
- if (!(type == CMARK_BULLET_LIST || type == CMARK_ORDERED_LIST)) {
386
- return 0;
387
- }
388
-
389
- if (node == NULL) {
390
- return 0;
391
- }
392
-
393
- if (node->type == CMARK_NODE_LIST) {
394
- node->as.list.list_type = type;
395
- return 1;
396
- } else {
397
- return 0;
398
- }
399
- }
400
-
401
- cmark_delim_type
402
- cmark_node_get_list_delim(cmark_node *node)
403
- {
404
- if (node == NULL) {
405
- return CMARK_NO_DELIM;
406
- }
407
-
408
- if (node->type == CMARK_NODE_LIST) {
409
- return node->as.list.delimiter;
410
- } else {
411
- return CMARK_NO_DELIM;
412
- }
413
- }
414
-
415
- int
416
- cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim)
417
- {
418
- if (!(delim == CMARK_PERIOD_DELIM || delim == CMARK_PAREN_DELIM)) {
419
- return 0;
420
- }
421
-
422
- if (node == NULL) {
423
- return 0;
424
- }
425
-
426
- if (node->type == CMARK_NODE_LIST) {
427
- node->as.list.delimiter = delim;
428
- return 1;
429
- } else {
430
- return 0;
431
- }
432
- }
433
-
434
- int
435
- cmark_node_get_list_start(cmark_node *node)
436
- {
437
- if (node == NULL) {
438
- return 0;
439
- }
440
-
441
- if (node->type == CMARK_NODE_LIST) {
442
- return node->as.list.start;
443
- } else {
444
- return 0;
445
- }
446
- }
447
-
448
- int
449
- cmark_node_set_list_start(cmark_node *node, int start)
450
- {
451
- if (node == NULL || start < 0) {
452
- return 0;
453
- }
454
-
455
- if (node->type == CMARK_NODE_LIST) {
456
- node->as.list.start = start;
457
- return 1;
458
- } else {
459
- return 0;
460
- }
461
- }
462
-
463
- int
464
- cmark_node_get_list_tight(cmark_node *node)
465
- {
466
- if (node == NULL) {
467
- return 0;
468
- }
469
-
470
- if (node->type == CMARK_NODE_LIST) {
471
- return node->as.list.tight;
472
- } else {
473
- return 0;
474
- }
475
- }
476
-
477
- int
478
- cmark_node_set_list_tight(cmark_node *node, int tight)
479
- {
480
- if (node == NULL) {
481
- return 0;
482
- }
483
-
484
- if (node->type == CMARK_NODE_LIST) {
485
- node->as.list.tight = tight;
486
- return 1;
487
- } else {
488
- return 0;
489
- }
490
- }
491
-
492
- const char*
493
- cmark_node_get_fence_info(cmark_node *node)
494
- {
495
- if (node == NULL) {
496
- return NULL;
497
- }
498
-
499
- if (node->type == NODE_CODE_BLOCK) {
500
- return cmark_chunk_to_cstr(&node->as.code.info);
501
- } else {
502
- return NULL;
503
- }
504
- }
505
-
506
- int
507
- cmark_node_set_fence_info(cmark_node *node, const char *info)
508
- {
509
- if (node == NULL) {
510
- return 0;
511
- }
512
-
513
- if (node->type == NODE_CODE_BLOCK) {
514
- cmark_chunk_set_cstr(&node->as.code.info, info);
515
- return 1;
516
- } else {
517
- return 0;
518
- }
519
- }
520
-
521
- const char*
522
- cmark_node_get_url(cmark_node *node)
523
- {
524
- if (node == NULL) {
525
- return NULL;
526
- }
527
-
528
- switch (node->type) {
529
- case NODE_LINK:
530
- case NODE_IMAGE:
531
- return cmark_chunk_to_cstr(&node->as.link.url);
532
- default:
533
- break;
534
- }
535
-
536
- return NULL;
537
- }
538
-
539
- int
540
- cmark_node_set_url(cmark_node *node, const char *url)
541
- {
542
- if (node == NULL) {
543
- return 0;
544
- }
545
-
546
- switch (node->type) {
547
- case NODE_LINK:
548
- case NODE_IMAGE:
549
- cmark_chunk_set_cstr(&node->as.link.url, url);
550
- return 1;
551
- default:
552
- break;
553
- }
554
-
555
- return 0;
556
- }
557
-
558
- const char*
559
- cmark_node_get_title(cmark_node *node)
560
- {
561
- if (node == NULL) {
562
- return NULL;
563
- }
564
-
565
- switch (node->type) {
566
- case NODE_LINK:
567
- case NODE_IMAGE:
568
- return cmark_chunk_to_cstr(&node->as.link.title);
569
- default:
570
- break;
571
- }
572
-
573
- return NULL;
574
- }
575
-
576
- int
577
- cmark_node_set_title(cmark_node *node, const char *title)
578
- {
579
- if (node == NULL) {
580
- return 0;
581
- }
582
-
583
- switch (node->type) {
584
- case NODE_LINK:
585
- case NODE_IMAGE:
586
- cmark_chunk_set_cstr(&node->as.link.title, title);
587
- return 1;
588
- default:
589
- break;
590
- }
591
-
592
- return 0;
593
- }
594
-
595
- int
596
- cmark_node_get_start_line(cmark_node *node)
597
- {
598
- if (node == NULL) {
599
- return 0;
600
- }
601
- return node->start_line;
602
- }
603
-
604
- int
605
- cmark_node_get_start_column(cmark_node *node)
606
- {
607
- if (node == NULL) {
608
- return 0;
609
- }
610
- return node->start_column;
611
- }
612
-
613
- int
614
- cmark_node_get_end_line(cmark_node *node)
615
- {
616
- if (node == NULL) {
617
- return 0;
618
- }
619
- return node->end_line;
620
- }
621
-
622
- int
623
- cmark_node_get_end_column(cmark_node *node)
624
- {
625
- if (node == NULL) {
626
- return 0;
627
- }
628
- return node->end_column;
94
+ static void S_free_nodes(cmark_node *e) {
95
+ cmark_node *next;
96
+ while (e != NULL) {
97
+ if (S_is_block(e)) {
98
+ cmark_strbuf_free(&e->string_content);
99
+ }
100
+ switch (e->type) {
101
+ case NODE_CODE_BLOCK:
102
+ cmark_chunk_free(&e->as.code.info);
103
+ cmark_chunk_free(&e->as.code.literal);
104
+ break;
105
+ case NODE_TEXT:
106
+ case NODE_INLINE_HTML:
107
+ case NODE_CODE:
108
+ case NODE_HTML:
109
+ cmark_chunk_free(&e->as.literal);
110
+ break;
111
+ case NODE_LINK:
112
+ case NODE_IMAGE:
113
+ cmark_chunk_free(&e->as.link.url);
114
+ cmark_chunk_free(&e->as.link.title);
115
+ break;
116
+ default:
117
+ break;
118
+ }
119
+ if (e->last_child) {
120
+ // Splice children into list
121
+ e->last_child->next = e->next;
122
+ e->next = e->first_child;
123
+ }
124
+ next = e->next;
125
+ free(e);
126
+ e = next;
127
+ }
128
+ }
129
+
130
+ void cmark_node_free(cmark_node *node) {
131
+ S_node_unlink(node);
132
+ node->next = NULL;
133
+ S_free_nodes(node);
134
+ }
135
+
136
+ cmark_node_type cmark_node_get_type(cmark_node *node) {
137
+ if (node == NULL) {
138
+ return CMARK_NODE_NONE;
139
+ } else {
140
+ return node->type;
141
+ }
142
+ }
143
+
144
+ const char *cmark_node_get_type_string(cmark_node *node) {
145
+ if (node == NULL) {
146
+ return "NONE";
147
+ }
148
+
149
+ switch (node->type) {
150
+ case CMARK_NODE_NONE:
151
+ return "none";
152
+ case CMARK_NODE_DOCUMENT:
153
+ return "document";
154
+ case CMARK_NODE_BLOCK_QUOTE:
155
+ return "block_quote";
156
+ case CMARK_NODE_LIST:
157
+ return "list";
158
+ case CMARK_NODE_ITEM:
159
+ return "item";
160
+ case CMARK_NODE_CODE_BLOCK:
161
+ return "code_block";
162
+ case CMARK_NODE_HTML:
163
+ return "html";
164
+ case CMARK_NODE_PARAGRAPH:
165
+ return "paragraph";
166
+ case CMARK_NODE_HEADER:
167
+ return "header";
168
+ case CMARK_NODE_HRULE:
169
+ return "hrule";
170
+ case CMARK_NODE_TEXT:
171
+ return "text";
172
+ case CMARK_NODE_SOFTBREAK:
173
+ return "softbreak";
174
+ case CMARK_NODE_LINEBREAK:
175
+ return "linebreak";
176
+ case CMARK_NODE_CODE:
177
+ return "code";
178
+ case CMARK_NODE_INLINE_HTML:
179
+ return "inline_html";
180
+ case CMARK_NODE_EMPH:
181
+ return "emph";
182
+ case CMARK_NODE_STRONG:
183
+ return "strong";
184
+ case CMARK_NODE_LINK:
185
+ return "link";
186
+ case CMARK_NODE_IMAGE:
187
+ return "image";
188
+ }
189
+
190
+ return "<unknown>";
191
+ }
192
+
193
+ cmark_node *cmark_node_next(cmark_node *node) {
194
+ if (node == NULL) {
195
+ return NULL;
196
+ } else {
197
+ return node->next;
198
+ }
199
+ }
200
+
201
+ cmark_node *cmark_node_previous(cmark_node *node) {
202
+ if (node == NULL) {
203
+ return NULL;
204
+ } else {
205
+ return node->prev;
206
+ }
207
+ }
208
+
209
+ cmark_node *cmark_node_parent(cmark_node *node) {
210
+ if (node == NULL) {
211
+ return NULL;
212
+ } else {
213
+ return node->parent;
214
+ }
215
+ }
216
+
217
+ cmark_node *cmark_node_first_child(cmark_node *node) {
218
+ if (node == NULL) {
219
+ return NULL;
220
+ } else {
221
+ return node->first_child;
222
+ }
223
+ }
224
+
225
+ cmark_node *cmark_node_last_child(cmark_node *node) {
226
+ if (node == NULL) {
227
+ return NULL;
228
+ } else {
229
+ return node->last_child;
230
+ }
231
+ }
232
+
233
+ void *cmark_node_get_user_data(cmark_node *node) {
234
+ if (node == NULL) {
235
+ return NULL;
236
+ } else {
237
+ return node->user_data;
238
+ }
239
+ }
240
+
241
+ int cmark_node_set_user_data(cmark_node *node, void *user_data) {
242
+ if (node == NULL) {
243
+ return 0;
244
+ }
245
+ node->user_data = user_data;
246
+ return 1;
247
+ }
248
+
249
+ const char *cmark_node_get_literal(cmark_node *node) {
250
+ if (node == NULL) {
251
+ return NULL;
252
+ }
253
+
254
+ switch (node->type) {
255
+ case NODE_HTML:
256
+ case NODE_TEXT:
257
+ case NODE_INLINE_HTML:
258
+ case NODE_CODE:
259
+ return cmark_chunk_to_cstr(&node->as.literal);
260
+
261
+ case NODE_CODE_BLOCK:
262
+ return cmark_chunk_to_cstr(&node->as.code.literal);
263
+
264
+ default:
265
+ break;
266
+ }
267
+
268
+ return NULL;
269
+ }
270
+
271
+ int cmark_node_set_literal(cmark_node *node, const char *content) {
272
+ if (node == NULL) {
273
+ return 0;
274
+ }
275
+
276
+ switch (node->type) {
277
+ case NODE_HTML:
278
+ case NODE_TEXT:
279
+ case NODE_INLINE_HTML:
280
+ case NODE_CODE:
281
+ cmark_chunk_set_cstr(&node->as.literal, content);
282
+ return 1;
283
+
284
+ case NODE_CODE_BLOCK:
285
+ cmark_chunk_set_cstr(&node->as.code.literal, content);
286
+ return 1;
287
+
288
+ default:
289
+ break;
290
+ }
291
+
292
+ return 0;
293
+ }
294
+
295
+ int cmark_node_get_header_level(cmark_node *node) {
296
+ if (node == NULL) {
297
+ return 0;
298
+ }
299
+
300
+ switch (node->type) {
301
+ case CMARK_NODE_HEADER:
302
+ return node->as.header.level;
303
+
304
+ default:
305
+ break;
306
+ }
307
+
308
+ return 0;
309
+ }
310
+
311
+ int cmark_node_set_header_level(cmark_node *node, int level) {
312
+ if (node == NULL || level < 1 || level > 6) {
313
+ return 0;
314
+ }
315
+
316
+ switch (node->type) {
317
+ case CMARK_NODE_HEADER:
318
+ node->as.header.level = level;
319
+ return 1;
320
+
321
+ default:
322
+ break;
323
+ }
324
+
325
+ return 0;
326
+ }
327
+
328
+ cmark_list_type cmark_node_get_list_type(cmark_node *node) {
329
+ if (node == NULL) {
330
+ return CMARK_NO_LIST;
331
+ }
332
+
333
+ if (node->type == CMARK_NODE_LIST) {
334
+ return node->as.list.list_type;
335
+ } else {
336
+ return CMARK_NO_LIST;
337
+ }
338
+ }
339
+
340
+ int cmark_node_set_list_type(cmark_node *node, cmark_list_type type) {
341
+ if (!(type == CMARK_BULLET_LIST || type == CMARK_ORDERED_LIST)) {
342
+ return 0;
343
+ }
344
+
345
+ if (node == NULL) {
346
+ return 0;
347
+ }
348
+
349
+ if (node->type == CMARK_NODE_LIST) {
350
+ node->as.list.list_type = type;
351
+ return 1;
352
+ } else {
353
+ return 0;
354
+ }
355
+ }
356
+
357
+ cmark_delim_type cmark_node_get_list_delim(cmark_node *node) {
358
+ if (node == NULL) {
359
+ return CMARK_NO_DELIM;
360
+ }
361
+
362
+ if (node->type == CMARK_NODE_LIST) {
363
+ return node->as.list.delimiter;
364
+ } else {
365
+ return CMARK_NO_DELIM;
366
+ }
367
+ }
368
+
369
+ int cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim) {
370
+ if (!(delim == CMARK_PERIOD_DELIM || delim == CMARK_PAREN_DELIM)) {
371
+ return 0;
372
+ }
373
+
374
+ if (node == NULL) {
375
+ return 0;
376
+ }
377
+
378
+ if (node->type == CMARK_NODE_LIST) {
379
+ node->as.list.delimiter = delim;
380
+ return 1;
381
+ } else {
382
+ return 0;
383
+ }
384
+ }
385
+
386
+ int cmark_node_get_list_start(cmark_node *node) {
387
+ if (node == NULL) {
388
+ return 0;
389
+ }
390
+
391
+ if (node->type == CMARK_NODE_LIST) {
392
+ return node->as.list.start;
393
+ } else {
394
+ return 0;
395
+ }
396
+ }
397
+
398
+ int cmark_node_set_list_start(cmark_node *node, int start) {
399
+ if (node == NULL || start < 0) {
400
+ return 0;
401
+ }
402
+
403
+ if (node->type == CMARK_NODE_LIST) {
404
+ node->as.list.start = start;
405
+ return 1;
406
+ } else {
407
+ return 0;
408
+ }
409
+ }
410
+
411
+ int cmark_node_get_list_tight(cmark_node *node) {
412
+ if (node == NULL) {
413
+ return 0;
414
+ }
415
+
416
+ if (node->type == CMARK_NODE_LIST) {
417
+ return node->as.list.tight;
418
+ } else {
419
+ return 0;
420
+ }
421
+ }
422
+
423
+ int cmark_node_set_list_tight(cmark_node *node, int tight) {
424
+ if (node == NULL) {
425
+ return 0;
426
+ }
427
+
428
+ if (node->type == CMARK_NODE_LIST) {
429
+ node->as.list.tight = tight == 1;
430
+ return 1;
431
+ } else {
432
+ return 0;
433
+ }
434
+ }
435
+
436
+ const char *cmark_node_get_fence_info(cmark_node *node) {
437
+ if (node == NULL) {
438
+ return NULL;
439
+ }
440
+
441
+ if (node->type == NODE_CODE_BLOCK) {
442
+ return cmark_chunk_to_cstr(&node->as.code.info);
443
+ } else {
444
+ return NULL;
445
+ }
446
+ }
447
+
448
+ int cmark_node_set_fence_info(cmark_node *node, const char *info) {
449
+ if (node == NULL) {
450
+ return 0;
451
+ }
452
+
453
+ if (node->type == NODE_CODE_BLOCK) {
454
+ cmark_chunk_set_cstr(&node->as.code.info, info);
455
+ return 1;
456
+ } else {
457
+ return 0;
458
+ }
459
+ }
460
+
461
+ const char *cmark_node_get_url(cmark_node *node) {
462
+ if (node == NULL) {
463
+ return NULL;
464
+ }
465
+
466
+ switch (node->type) {
467
+ case NODE_LINK:
468
+ case NODE_IMAGE:
469
+ return cmark_chunk_to_cstr(&node->as.link.url);
470
+ default:
471
+ break;
472
+ }
473
+
474
+ return NULL;
475
+ }
476
+
477
+ int cmark_node_set_url(cmark_node *node, const char *url) {
478
+ if (node == NULL) {
479
+ return 0;
480
+ }
481
+
482
+ switch (node->type) {
483
+ case NODE_LINK:
484
+ case NODE_IMAGE:
485
+ cmark_chunk_set_cstr(&node->as.link.url, url);
486
+ return 1;
487
+ default:
488
+ break;
489
+ }
490
+
491
+ return 0;
492
+ }
493
+
494
+ const char *cmark_node_get_title(cmark_node *node) {
495
+ if (node == NULL) {
496
+ return NULL;
497
+ }
498
+
499
+ switch (node->type) {
500
+ case NODE_LINK:
501
+ case NODE_IMAGE:
502
+ return cmark_chunk_to_cstr(&node->as.link.title);
503
+ default:
504
+ break;
505
+ }
506
+
507
+ return NULL;
508
+ }
509
+
510
+ int cmark_node_set_title(cmark_node *node, const char *title) {
511
+ if (node == NULL) {
512
+ return 0;
513
+ }
514
+
515
+ switch (node->type) {
516
+ case NODE_LINK:
517
+ case NODE_IMAGE:
518
+ cmark_chunk_set_cstr(&node->as.link.title, title);
519
+ return 1;
520
+ default:
521
+ break;
522
+ }
523
+
524
+ return 0;
525
+ }
526
+
527
+ int cmark_node_get_start_line(cmark_node *node) {
528
+ if (node == NULL) {
529
+ return 0;
530
+ }
531
+ return node->start_line;
532
+ }
533
+
534
+ int cmark_node_get_start_column(cmark_node *node) {
535
+ if (node == NULL) {
536
+ return 0;
537
+ }
538
+ return node->start_column;
539
+ }
540
+
541
+ int cmark_node_get_end_line(cmark_node *node) {
542
+ if (node == NULL) {
543
+ return 0;
544
+ }
545
+ return node->end_line;
546
+ }
547
+
548
+ int cmark_node_get_end_column(cmark_node *node) {
549
+ if (node == NULL) {
550
+ return 0;
551
+ }
552
+ return node->end_column;
629
553
  }
630
554
 
631
555
  // Unlink a node without adjusting its next, prev, and parent pointers.
632
- static void
633
- S_node_unlink(cmark_node *node)
634
- {
635
- if (node == NULL) {
636
- return;
637
- }
556
+ static void S_node_unlink(cmark_node *node) {
557
+ if (node == NULL) {
558
+ return;
559
+ }
638
560
 
639
- if (node->prev) {
640
- node->prev->next = node->next;
641
- }
642
- if (node->next) {
643
- node->next->prev = node->prev;
644
- }
645
-
646
- // Adjust first_child and last_child of parent.
647
- cmark_node *parent = node->parent;
648
- if (parent) {
649
- if (parent->first_child == node) {
650
- parent->first_child = node->next;
651
- }
652
- if (parent->last_child == node) {
653
- parent->last_child = node->prev;
654
- }
655
- }
656
- }
657
-
658
- void
659
- cmark_node_unlink(cmark_node *node)
660
- {
661
- S_node_unlink(node);
662
-
663
- node->next = NULL;
664
- node->prev = NULL;
665
- node->parent = NULL;
561
+ if (node->prev) {
562
+ node->prev->next = node->next;
563
+ }
564
+ if (node->next) {
565
+ node->next->prev = node->prev;
566
+ }
666
567
 
667
- }
668
-
669
- int
670
- cmark_node_insert_before(cmark_node *node, cmark_node *sibling)
671
- {
672
- if (node == NULL || sibling == NULL) {
673
- return 0;
674
- }
568
+ // Adjust first_child and last_child of parent.
569
+ cmark_node *parent = node->parent;
570
+ if (parent) {
571
+ if (parent->first_child == node) {
572
+ parent->first_child = node->next;
573
+ }
574
+ if (parent->last_child == node) {
575
+ parent->last_child = node->prev;
576
+ }
577
+ }
578
+ }
675
579
 
676
- if (!node->parent || !S_can_contain(node->parent, sibling)) {
677
- return 0;
678
- }
679
-
680
- S_node_unlink(sibling);
580
+ void cmark_node_unlink(cmark_node *node) {
581
+ S_node_unlink(node);
681
582
 
682
- cmark_node *old_prev = node->prev;
683
-
684
- // Insert 'sibling' between 'old_prev' and 'node'.
685
- if (old_prev) {
686
- old_prev->next = sibling;
687
- }
688
- sibling->prev = old_prev;
689
- sibling->next = node;
690
- node->prev = sibling;
583
+ node->next = NULL;
584
+ node->prev = NULL;
585
+ node->parent = NULL;
586
+ }
587
+
588
+ int cmark_node_insert_before(cmark_node *node, cmark_node *sibling) {
589
+ if (node == NULL || sibling == NULL) {
590
+ return 0;
591
+ }
592
+
593
+ if (!node->parent || !S_can_contain(node->parent, sibling)) {
594
+ return 0;
595
+ }
596
+
597
+ S_node_unlink(sibling);
598
+
599
+ cmark_node *old_prev = node->prev;
600
+
601
+ // Insert 'sibling' between 'old_prev' and 'node'.
602
+ if (old_prev) {
603
+ old_prev->next = sibling;
604
+ }
605
+ sibling->prev = old_prev;
606
+ sibling->next = node;
607
+ node->prev = sibling;
691
608
 
692
- // Set new parent.
693
- cmark_node *parent = node->parent;
694
- sibling->parent = parent;
695
-
696
- // Adjust first_child of parent if inserted as first child.
697
- if (parent && !old_prev) {
698
- parent->first_child = sibling;
699
- }
700
-
701
- return 1;
609
+ // Set new parent.
610
+ cmark_node *parent = node->parent;
611
+ sibling->parent = parent;
612
+
613
+ // Adjust first_child of parent if inserted as first child.
614
+ if (parent && !old_prev) {
615
+ parent->first_child = sibling;
616
+ }
617
+
618
+ return 1;
702
619
  }
703
-
704
- int
705
- cmark_node_insert_after(cmark_node *node, cmark_node *sibling)
706
- {
707
- if (node == NULL || sibling == NULL) {
708
- return 0;
709
- }
710
-
711
- if (!node->parent || !S_can_contain(node->parent, sibling)) {
712
- return 0;
713
- }
714
-
715
- S_node_unlink(sibling);
716
-
717
- cmark_node *old_next = node->next;
718
-
719
- // Insert 'sibling' between 'node' and 'old_next'.
720
- if (old_next) {
721
- old_next->prev = sibling;
722
- }
723
- sibling->next = old_next;
724
- sibling->prev = node;
725
- node->next = sibling;
726
-
727
- // Set new parent.
728
- cmark_node *parent = node->parent;
729
- sibling->parent = parent;
730
-
731
- // Adjust last_child of parent if inserted as last child.
732
- if (parent && !old_next) {
733
- parent->last_child = sibling;
734
- }
735
-
736
- return 1;
737
- }
738
-
739
- int
740
- cmark_node_prepend_child(cmark_node *node, cmark_node *child)
741
- {
742
- if (!S_can_contain(node, child)) {
743
- return 0;
744
- }
745
-
746
- S_node_unlink(child);
747
-
748
- cmark_node *old_first_child = node->first_child;
749
-
750
- child->next = old_first_child;
751
- child->prev = NULL;
752
- child->parent = node;
753
- node->first_child = child;
754
-
755
- if (old_first_child) {
756
- old_first_child->prev = child;
757
- } else {
758
- // Also set last_child if node previously had no children.
759
- node->last_child = child;
760
- }
761
-
762
- return 1;
763
- }
764
-
765
- int
766
- cmark_node_append_child(cmark_node *node, cmark_node *child)
767
- {
768
- if (!S_can_contain(node, child)) {
769
- return 0;
770
- }
771
-
772
- S_node_unlink(child);
773
-
774
- cmark_node *old_last_child = node->last_child;
775
-
776
- child->next = NULL;
777
- child->prev = old_last_child;
778
- child->parent = node;
779
- node->last_child = child;
780
-
781
- if (old_last_child) {
782
- old_last_child->next = child;
783
- } else {
784
- // Also set first_child if node previously had no children.
785
- node->first_child = child;
786
- }
787
-
788
- return 1;
789
- }
790
-
791
- static void
792
- S_print_error(FILE *out, cmark_node *node, const char *elem)
793
- {
794
- if (out == NULL) {
795
- return;
796
- }
797
- fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem,
798
- cmark_node_get_type_string(node), node->start_line,
799
- node->start_column);
800
- }
801
-
802
- int
803
- cmark_node_check(cmark_node *node, FILE *out)
804
- {
805
- cmark_node *cur;
806
- int errors = 0;
807
-
808
- if (!node) {
809
- return 0;
810
- }
811
-
812
- cur = node;
813
- while (true) {
814
- if (cur->first_child) {
815
- if (cur->first_child->prev != NULL) {
816
- S_print_error(out, cur->first_child, "prev");
817
- cur->first_child->prev = NULL;
818
- ++errors;
819
- }
820
- if (cur->first_child->parent != cur) {
821
- S_print_error(out, cur->first_child, "parent");
822
- cur->first_child->parent = cur;
823
- ++errors;
824
- }
825
- cur = cur->first_child;
826
- continue;
827
- }
828
-
829
- next_sibling:
830
- if (cur == node) {
831
- break;
832
- }
833
- if (cur->next) {
834
- if (cur->next->prev != cur) {
835
- S_print_error(out, cur->next, "prev");
836
- cur->next->prev = cur;
837
- ++errors;
838
- }
839
- if (cur->next->parent != cur->parent) {
840
- S_print_error(out, cur->next, "parent");
841
- cur->next->parent = cur->parent;
842
- ++errors;
843
- }
844
- cur = cur->next;
845
- continue;
846
- }
847
-
848
- if (cur->parent->last_child != cur) {
849
- S_print_error(out, cur->parent, "last_child");
850
- cur->parent->last_child = cur;
851
- ++errors;
852
- }
853
- cur = cur->parent;
854
- goto next_sibling;
855
- }
856
-
857
- return errors;
620
+
621
+ int cmark_node_insert_after(cmark_node *node, cmark_node *sibling) {
622
+ if (node == NULL || sibling == NULL) {
623
+ return 0;
624
+ }
625
+
626
+ if (!node->parent || !S_can_contain(node->parent, sibling)) {
627
+ return 0;
628
+ }
629
+
630
+ S_node_unlink(sibling);
631
+
632
+ cmark_node *old_next = node->next;
633
+
634
+ // Insert 'sibling' between 'node' and 'old_next'.
635
+ if (old_next) {
636
+ old_next->prev = sibling;
637
+ }
638
+ sibling->next = old_next;
639
+ sibling->prev = node;
640
+ node->next = sibling;
641
+
642
+ // Set new parent.
643
+ cmark_node *parent = node->parent;
644
+ sibling->parent = parent;
645
+
646
+ // Adjust last_child of parent if inserted as last child.
647
+ if (parent && !old_next) {
648
+ parent->last_child = sibling;
649
+ }
650
+
651
+ return 1;
652
+ }
653
+
654
+ int cmark_node_prepend_child(cmark_node *node, cmark_node *child) {
655
+ if (!S_can_contain(node, child)) {
656
+ return 0;
657
+ }
658
+
659
+ S_node_unlink(child);
660
+
661
+ cmark_node *old_first_child = node->first_child;
662
+
663
+ child->next = old_first_child;
664
+ child->prev = NULL;
665
+ child->parent = node;
666
+ node->first_child = child;
667
+
668
+ if (old_first_child) {
669
+ old_first_child->prev = child;
670
+ } else {
671
+ // Also set last_child if node previously had no children.
672
+ node->last_child = child;
673
+ }
674
+
675
+ return 1;
676
+ }
677
+
678
+ int cmark_node_append_child(cmark_node *node, cmark_node *child) {
679
+ if (!S_can_contain(node, child)) {
680
+ return 0;
681
+ }
682
+
683
+ S_node_unlink(child);
684
+
685
+ cmark_node *old_last_child = node->last_child;
686
+
687
+ child->next = NULL;
688
+ child->prev = old_last_child;
689
+ child->parent = node;
690
+ node->last_child = child;
691
+
692
+ if (old_last_child) {
693
+ old_last_child->next = child;
694
+ } else {
695
+ // Also set first_child if node previously had no children.
696
+ node->first_child = child;
697
+ }
698
+
699
+ return 1;
700
+ }
701
+
702
+ static void S_print_error(FILE *out, cmark_node *node, const char *elem) {
703
+ if (out == NULL) {
704
+ return;
705
+ }
706
+ fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem,
707
+ cmark_node_get_type_string(node), node->start_line,
708
+ node->start_column);
709
+ }
710
+
711
+ int cmark_node_check(cmark_node *node, FILE *out) {
712
+ cmark_node *cur;
713
+ int errors = 0;
714
+
715
+ if (!node) {
716
+ return 0;
717
+ }
718
+
719
+ cur = node;
720
+ for (;;) {
721
+ if (cur->first_child) {
722
+ if (cur->first_child->prev != NULL) {
723
+ S_print_error(out, cur->first_child, "prev");
724
+ cur->first_child->prev = NULL;
725
+ ++errors;
726
+ }
727
+ if (cur->first_child->parent != cur) {
728
+ S_print_error(out, cur->first_child, "parent");
729
+ cur->first_child->parent = cur;
730
+ ++errors;
731
+ }
732
+ cur = cur->first_child;
733
+ continue;
734
+ }
735
+
736
+ next_sibling:
737
+ if (cur == node) {
738
+ break;
739
+ }
740
+ if (cur->next) {
741
+ if (cur->next->prev != cur) {
742
+ S_print_error(out, cur->next, "prev");
743
+ cur->next->prev = cur;
744
+ ++errors;
745
+ }
746
+ if (cur->next->parent != cur->parent) {
747
+ S_print_error(out, cur->next, "parent");
748
+ cur->next->parent = cur->parent;
749
+ ++errors;
750
+ }
751
+ cur = cur->next;
752
+ continue;
753
+ }
754
+
755
+ if (cur->parent->last_child != cur) {
756
+ S_print_error(out, cur->parent, "last_child");
757
+ cur->parent->last_child = cur;
758
+ ++errors;
759
+ }
760
+ cur = cur->parent;
761
+ goto next_sibling;
762
+ }
763
+
764
+ return errors;
858
765
  }