commonmarker 0.9.1 → 0.9.2

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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/Rakefile +9 -9
  4. data/ext/commonmarker/cmark/api_test/main.c +5 -0
  5. data/ext/commonmarker/cmark/build/CMakeCache.txt +459 -0
  6. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeCCompiler.cmake +67 -0
  7. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeCXXCompiler.cmake +68 -0
  8. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeDetermineCompilerABI_C.bin +0 -0
  9. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
  10. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CMakeSystem.cmake +15 -0
  11. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CompilerIdC/CMakeCCompilerId.c +544 -0
  12. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CompilerIdC/a.out +0 -0
  13. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +533 -0
  14. data/ext/commonmarker/cmark/build/CMakeFiles/3.5.2/CompilerIdCXX/a.out +0 -0
  15. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  16. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeError.log +14 -0
  17. data/ext/commonmarker/cmark/build/CMakeFiles/CMakeOutput.log +562 -0
  18. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile.cmake +150 -0
  19. data/ext/commonmarker/cmark/build/CMakeFiles/Makefile2 +295 -0
  20. data/ext/commonmarker/cmark/build/CMakeFiles/TargetDirectories.txt +39 -0
  21. data/ext/commonmarker/cmark/build/CMakeFiles/cmake.check_cache +1 -0
  22. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.bin +0 -0
  23. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.c +34 -0
  24. data/ext/commonmarker/cmark/build/CMakeFiles/feature_tests.cxx +405 -0
  25. data/ext/commonmarker/cmark/build/CMakeFiles/progress.marks +1 -0
  26. data/ext/commonmarker/cmark/build/CTestTestfile.cmake +10 -0
  27. data/ext/commonmarker/cmark/build/Makefile +250 -0
  28. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  29. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/DependInfo.cmake +35 -0
  30. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/build.make +168 -0
  31. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/cmake_clean.cmake +12 -0
  32. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/depend.make +2 -0
  33. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/flags.make +17 -0
  34. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/link.txt +1 -0
  35. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/api_test.dir/progress.make +5 -0
  36. data/ext/commonmarker/cmark/build/api_test/CMakeFiles/progress.marks +1 -0
  37. data/ext/commonmarker/cmark/build/api_test/Makefile +300 -0
  38. data/ext/commonmarker/cmark/build/api_test/cmake_install.cmake +29 -0
  39. data/ext/commonmarker/cmark/build/cmake_install.cmake +48 -0
  40. data/ext/commonmarker/cmark/build/man/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  41. data/ext/commonmarker/cmark/build/man/CMakeFiles/progress.marks +1 -0
  42. data/ext/commonmarker/cmark/build/man/Makefile +194 -0
  43. data/ext/commonmarker/cmark/build/man/cmake_install.cmake +37 -0
  44. data/ext/commonmarker/cmark/build/src/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  45. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/DependInfo.cmake +41 -0
  46. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/build.make +626 -0
  47. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/cmake_clean.cmake +29 -0
  48. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/depend.make +2 -0
  49. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/flags.make +10 -0
  50. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/link.txt +1 -0
  51. data/ext/commonmarker/cmark/build/src/CMakeFiles/cmark.dir/progress.make +22 -0
  52. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/DependInfo.cmake +46 -0
  53. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/build.make +603 -0
  54. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/cmake_clean.cmake +29 -0
  55. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/depend.make +2 -0
  56. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/flags.make +10 -0
  57. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/link.txt +1 -0
  58. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark.dir/progress.make +21 -0
  59. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/C.includecache +468 -0
  60. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/DependInfo.cmake +40 -0
  61. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/blocks.c.o +0 -0
  62. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/buffer.c.o +0 -0
  63. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/build.make +600 -0
  64. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmake_clean.cmake +28 -0
  65. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmake_clean_target.cmake +3 -0
  66. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark.c.o +0 -0
  67. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/cmark_ctype.c.o +0 -0
  68. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/commonmark.c.o +0 -0
  69. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.internal +211 -0
  70. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/depend.make +211 -0
  71. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/flags.make +10 -0
  72. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_href_e.c.o +0 -0
  73. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_e.c.o +0 -0
  74. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/houdini_html_u.c.o +0 -0
  75. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/html.c.o +0 -0
  76. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/inlines.c.o +0 -0
  77. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/iterator.c.o +0 -0
  78. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/latex.c.o +0 -0
  79. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/link.txt +2 -0
  80. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/man.c.o +0 -0
  81. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/node.c.o +0 -0
  82. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/progress.make +21 -0
  83. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/references.c.o +0 -0
  84. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/render.c.o +0 -0
  85. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/scanners.c.o +0 -0
  86. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/utf8.c.o +0 -0
  87. data/ext/commonmarker/cmark/build/src/CMakeFiles/libcmark_static.dir/xml.c.o +0 -0
  88. data/ext/commonmarker/cmark/build/src/CMakeFiles/progress.marks +1 -0
  89. data/ext/commonmarker/cmark/build/src/Makefile +956 -0
  90. data/ext/commonmarker/cmark/build/src/cmake_install.cmake +77 -0
  91. data/ext/commonmarker/cmark/build/src/cmark_export.h +41 -0
  92. data/ext/commonmarker/cmark/build/src/cmark_version.h +7 -0
  93. data/ext/commonmarker/cmark/build/src/config.h +84 -0
  94. data/ext/commonmarker/cmark/build/src/libcmark.a +0 -0
  95. data/ext/commonmarker/cmark/build/src/libcmark.pc +10 -0
  96. data/ext/commonmarker/cmark/build/testdir/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  97. data/ext/commonmarker/cmark/build/testdir/CMakeFiles/progress.marks +1 -0
  98. data/ext/commonmarker/cmark/build/testdir/CTestTestfile.cmake +14 -0
  99. data/ext/commonmarker/cmark/build/testdir/Makefile +194 -0
  100. data/ext/commonmarker/cmark/build/testdir/cmake_install.cmake +29 -0
  101. data/ext/commonmarker/cmark/man/man1/cmark.1 +11 -4
  102. data/ext/commonmarker/cmark/man/man3/cmark.3 +66 -11
  103. data/ext/commonmarker/cmark/src/blocks.c +232 -235
  104. data/ext/commonmarker/cmark/src/buffer.c +19 -56
  105. data/ext/commonmarker/cmark/src/buffer.h +7 -20
  106. data/ext/commonmarker/cmark/src/chunk.h +19 -19
  107. data/ext/commonmarker/cmark/src/cmark.c +14 -0
  108. data/ext/commonmarker/cmark/src/cmark.h +45 -6
  109. data/ext/commonmarker/cmark/src/cmark_ctype.c +2 -0
  110. data/ext/commonmarker/cmark/src/cmark_ctype.h +2 -0
  111. data/ext/commonmarker/cmark/src/commonmark.c +42 -29
  112. data/ext/commonmarker/cmark/src/config.h.in +8 -0
  113. data/ext/commonmarker/cmark/src/html.c +3 -1
  114. data/ext/commonmarker/cmark/src/inlines.c +111 -150
  115. data/ext/commonmarker/cmark/src/inlines.h +4 -4
  116. data/ext/commonmarker/cmark/src/iterator.c +6 -7
  117. data/ext/commonmarker/cmark/src/iterator.h +2 -0
  118. data/ext/commonmarker/cmark/src/latex.c +10 -8
  119. data/ext/commonmarker/cmark/src/main.c +6 -2
  120. data/ext/commonmarker/cmark/src/man.c +9 -5
  121. data/ext/commonmarker/cmark/src/node.c +38 -29
  122. data/ext/commonmarker/cmark/src/node.h +15 -11
  123. data/ext/commonmarker/cmark/src/parser.h +4 -2
  124. data/ext/commonmarker/cmark/src/references.c +23 -22
  125. data/ext/commonmarker/cmark/src/references.h +3 -1
  126. data/ext/commonmarker/cmark/src/render.c +9 -7
  127. data/ext/commonmarker/cmark/src/render.h +3 -1
  128. data/ext/commonmarker/cmark/src/scanners.c +30 -22
  129. data/ext/commonmarker/cmark/src/xml.c +1 -1
  130. data/ext/commonmarker/cmark/test/CMakeLists.txt +8 -8
  131. data/ext/commonmarker/cmark/test/cmark.py +34 -14
  132. data/ext/commonmarker/cmark/test/roundtrip_tests.py +47 -0
  133. data/ext/commonmarker/cmark/test/spec.txt +96 -6
  134. data/ext/commonmarker/cmark/test/spec_tests.py +5 -8
  135. data/ext/commonmarker/commonmarker.c +14 -8
  136. data/lib/commonmarker/config.rb +2 -2
  137. data/lib/commonmarker/renderer.rb +17 -7
  138. data/lib/commonmarker/renderer/html_renderer.rb +16 -21
  139. data/lib/commonmarker/version.rb +1 -1
  140. data/test/test_pathological_inputs.rb +11 -11
  141. metadata +99 -4
  142. data/ext/commonmarker/cmark/test/roundtrip.bat +0 -1
  143. data/ext/commonmarker/cmark/test/roundtrip.sh +0 -2
@@ -0,0 +1,29 @@
1
+ # Install script for directory: /Users/gjtorikian/Development/commonmarker/ext/commonmarker/cmark/test
2
+
3
+ # Set the install prefix
4
+ if(NOT DEFINED CMAKE_INSTALL_PREFIX)
5
+ set(CMAKE_INSTALL_PREFIX "/usr/local")
6
+ endif()
7
+ string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
8
+
9
+ # Set the install configuration name.
10
+ if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
11
+ if(BUILD_TYPE)
12
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
13
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
14
+ else()
15
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
16
+ endif()
17
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
18
+ endif()
19
+
20
+ # Set the component getting installed.
21
+ if(NOT CMAKE_INSTALL_COMPONENT)
22
+ if(COMPONENT)
23
+ message(STATUS "Install component: \"${COMPONENT}\"")
24
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
25
+ else()
26
+ set(CMAKE_INSTALL_COMPONENT)
27
+ endif()
28
+ endif()
29
+
@@ -25,13 +25,20 @@ Specify a column width to which to wrap the output. For no wrapping, use
25
25
  the value 0 (the default). This option currently only affects the
26
26
  commonmark, latex, and man renderers.
27
27
  .TP 12n
28
+ .B \-\-hardbreaks
29
+ Render soft breaks (newlines inside paragraphs in the CommonMark source)
30
+ as hard line breaks in the target format. If this option is specified,
31
+ hard wrapping is disabled for CommonMark output, regardless of the value
32
+ given with \-\-width.
33
+ .TP 12n
34
+ .B \-\-nobreaks
35
+ Render soft breaks as spaces. If this option is specified,
36
+ hard wrapping is disabled for all output formats, regardless of the value
37
+ given with \-\-width.
38
+ .TP 12n
28
39
  .B \-\-sourcepos
29
40
  Include source position attribute.
30
41
  .TP 12n
31
- .B \-\-hardbreaks
32
- Treat newlines as hard line breaks. If this option is specified,
33
- hard wrapping is disabled, regardless of the value given with \-\-width.
34
- .TP 12n
35
42
  .B \-\-normalize
36
43
  Consolidate adjacent text nodes.
37
44
  .TP 12n
@@ -1,4 +1,4 @@
1
- .TH cmark 3 "March 24, 2016" "LOCAL" "Library Functions Manual"
1
+ .TH cmark 3 "June 06, 2016" "LOCAL" "Library Functions Manual"
2
2
  .SH
3
3
  NAME
4
4
  .PP
@@ -15,7 +15,8 @@ Simple Interface
15
15
  .PP
16
16
  Convert \f[I]text\f[] (assumed to be a UTF\-8 encoded string with length
17
17
  \f[I]len\f[]) from CommonMark Markdown to HTML, returning a
18
- null\-terminated, UTF\-8\-encoded string.
18
+ null\-terminated, UTF\-8\-encoded string. It is the caller\[cq]s
19
+ responsibility to free the returned buffer.
19
20
 
20
21
  .SS
21
22
  Node Structure
@@ -94,6 +95,26 @@ typedef enum {
94
95
 
95
96
 
96
97
 
98
+ .SS
99
+ Custom memory allocator support
100
+
101
+ .PP
102
+ .nf
103
+ \fC
104
+ .RS 0n
105
+ typedef struct cmark_mem {
106
+ void *(*calloc)(size_t, size_t);
107
+ void *(*realloc)(void *, size_t);
108
+ void (*free)(void *);
109
+ } cmark_mem;
110
+ .RE
111
+ \f[]
112
+ .fi
113
+
114
+ .PP
115
+ Defines the memory allocation functions to be used by CMark when parsing
116
+ and allocating a document tree
117
+
97
118
  .SS
98
119
  Creating and Destroying Nodes
99
120
 
@@ -105,6 +126,13 @@ Creates a new node of type \f[I]type\f[]. Note that the node may have
105
126
  other required properties, which it is the caller\[cq]s responsibility
106
127
  to assign.
107
128
 
129
+ .PP
130
+ \fIcmark_node *\f[] \fBcmark_node_new_with_mem\f[](\fIcmark_node_type type\f[], \fIcmark_mem *mem\f[])
131
+
132
+ .PP
133
+ Same as \f[C]cmark_node_new\f[], but explicitly listing the memory
134
+ allocator used to allocate the node
135
+
108
136
  .PP
109
137
  \fIvoid\f[] \fBcmark_node_free\f[](\fIcmark_node *node\f[])
110
138
 
@@ -224,8 +252,9 @@ typedef enum {
224
252
 
225
253
  .PP
226
254
  Creates a new iterator starting at \f[I]root\f[]. The current node and
227
- event type are undefined until \f[C]cmark_iter_next\f[] is called for
228
- the first time.
255
+ event type are undefined until \f[I]cmark_iter_next\f[] is called for
256
+ the first time. The memory allocated for the iterator should be released
257
+ using \f[I]cmark_iter_free\f[] when it is no longer needed.
229
258
 
230
259
  .PP
231
260
  \fIvoid\f[] \fBcmark_iter_free\f[](\fIcmark_iter *iter\f[])
@@ -561,6 +590,12 @@ cmark_parser_free(parser);
561
590
  .PP
562
591
  Creates a new parser object.
563
592
 
593
+ .PP
594
+ \fIcmark_parser *\f[] \fBcmark_parser_new_with_mem\f[](\fIint options\f[], \fIcmark_mem *mem\f[])
595
+
596
+ .PP
597
+ Creates a new parser object with the given memory allocator
598
+
564
599
  .PP
565
600
  \fIvoid\f[] \fBcmark_parser_free\f[](\fIcmark_parser *parser\f[])
566
601
 
@@ -584,14 +619,17 @@ Finish parsing and return a pointer to a tree of nodes.
584
619
 
585
620
  .PP
586
621
  Parse a CommonMark document in \f[I]buffer\f[] of length \f[I]len\f[].
587
- Returns a pointer to a tree of nodes.
622
+ Returns a pointer to a tree of nodes. The memory allocated for the node
623
+ tree should be released using \f[I]cmark_node_free\f[] when it is no
624
+ longer needed.
588
625
 
589
626
  .PP
590
627
  \fIcmark_node *\f[] \fBcmark_parse_file\f[](\fIFILE *f\f[], \fIint options\f[])
591
628
 
592
629
  .PP
593
630
  Parse a CommonMark document in file \f[I]f\f[], returning a pointer to a
594
- tree of nodes.
631
+ tree of nodes. The memory allocated for the node tree should be released
632
+ using \f[I]cmark_node_free\f[] when it is no longer needed.
595
633
 
596
634
  .SS
597
635
  Rendering
@@ -600,32 +638,37 @@ Rendering
600
638
  \fIchar *\f[] \fBcmark_render_xml\f[](\fIcmark_node *root\f[], \fIint options\f[])
601
639
 
602
640
  .PP
603
- Render a \f[I]node\f[] tree as XML.
641
+ Render a \f[I]node\f[] tree as XML. It is the caller\[cq]s
642
+ responsibility to free the returned buffer.
604
643
 
605
644
  .PP
606
645
  \fIchar *\f[] \fBcmark_render_html\f[](\fIcmark_node *root\f[], \fIint options\f[])
607
646
 
608
647
  .PP
609
648
  Render a \f[I]node\f[] tree as an HTML fragment. It is up to the user to
610
- add an appropriate header and footer.
649
+ add an appropriate header and footer. It is the caller\[cq]s
650
+ responsibility to free the returned buffer.
611
651
 
612
652
  .PP
613
653
  \fIchar *\f[] \fBcmark_render_man\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[])
614
654
 
615
655
  .PP
616
- Render a \f[I]node\f[] tree as a groff man page, without the header.
656
+ Render a \f[I]node\f[] tree as a groff man page, without the header. It
657
+ is the caller\[cq]s responsibility to free the returned buffer.
617
658
 
618
659
  .PP
619
660
  \fIchar *\f[] \fBcmark_render_commonmark\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[])
620
661
 
621
662
  .PP
622
- Render a \f[I]node\f[] tree as a commonmark document.
663
+ Render a \f[I]node\f[] tree as a commonmark document. It is the
664
+ caller\[cq]s responsibility to free the returned buffer.
623
665
 
624
666
  .PP
625
667
  \fIchar *\f[] \fBcmark_render_latex\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[])
626
668
 
627
669
  .PP
628
- Render a \f[I]node\f[] tree as a LaTeX document.
670
+ Render a \f[I]node\f[] tree as a LaTeX document. It is the caller\[cq]s
671
+ responsibility to free the returned buffer.
629
672
 
630
673
  .SS
631
674
  Options
@@ -685,6 +728,18 @@ Suppress raw HTML and unsafe links (\f[C]javascript:\f[],
685
728
  \f[C]image/webp\f[] mime types). Raw HTML is replaced by a placeholder
686
729
  HTML comment. Unsafe links are replaced by empty strings.
687
730
 
731
+ .PP
732
+ .nf
733
+ \fC
734
+ .RS 0n
735
+ #define CMARK_OPT_NOBREAKS (1 << 4)
736
+ .RE
737
+ \f[]
738
+ .fi
739
+
740
+ .PP
741
+ Render \f[C]softbreak\f[] elements as spaces.
742
+
688
743
  .SS
689
744
  Options affecting parsing
690
745
 
@@ -30,6 +30,21 @@
30
30
 
31
31
  #define peek_at(i, n) (i)->data[n]
32
32
 
33
+ static bool S_last_line_blank(const cmark_node *node) {
34
+ return (node->flags & CMARK_NODE__LAST_LINE_BLANK) != 0;
35
+ }
36
+
37
+ static CMARK_INLINE cmark_node_type S_type(const cmark_node *node) {
38
+ return (cmark_node_type)node->type;
39
+ }
40
+
41
+ static void S_set_last_line_blank(cmark_node *node, bool is_blank) {
42
+ if (is_blank)
43
+ node->flags |= CMARK_NODE__LAST_LINE_BLANK;
44
+ else
45
+ node->flags &= ~CMARK_NODE__LAST_LINE_BLANK;
46
+ }
47
+
33
48
  static CMARK_INLINE bool S_is_line_end_char(char c) {
34
49
  return (c == '\n' || c == '\r');
35
50
  }
@@ -44,38 +59,37 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
44
59
  static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
45
60
  bufsize_t bytes);
46
61
 
47
- static cmark_node *make_block(cmark_node_type tag, int start_line,
62
+ static cmark_node *make_block(cmark_mem *mem, cmark_node_type tag, int start_line,
48
63
  int start_column) {
49
64
  cmark_node *e;
50
65
 
51
- e = (cmark_node *)calloc(1, sizeof(*e));
52
- if (e != NULL) {
53
- e->type = tag;
54
- e->open = true;
55
- e->start_line = start_line;
56
- e->start_column = start_column;
57
- e->end_line = start_line;
58
- cmark_strbuf_init(&e->string_content, 32);
59
- }
66
+ e = (cmark_node *)mem->calloc(1, sizeof(*e));
67
+ cmark_strbuf_init(mem, &e->content, 32);
68
+ e->type = (uint16_t)tag;
69
+ e->flags = CMARK_NODE__OPEN;
70
+ e->start_line = start_line;
71
+ e->start_column = start_column;
72
+ e->end_line = start_line;
60
73
 
61
74
  return e;
62
75
  }
63
76
 
64
77
  // Create a root document node.
65
- static cmark_node *make_document() {
66
- cmark_node *e = make_block(CMARK_NODE_DOCUMENT, 1, 1);
78
+ static cmark_node *make_document(cmark_mem *mem) {
79
+ cmark_node *e = make_block(mem, CMARK_NODE_DOCUMENT, 1, 1);
67
80
  return e;
68
81
  }
69
82
 
70
- cmark_parser *cmark_parser_new(int options) {
71
- cmark_parser *parser = (cmark_parser *)malloc(sizeof(cmark_parser));
72
- cmark_node *document = make_document();
73
- cmark_strbuf *line = (cmark_strbuf *)malloc(sizeof(cmark_strbuf));
74
- cmark_strbuf *buf = (cmark_strbuf *)malloc(sizeof(cmark_strbuf));
75
- cmark_strbuf_init(line, 256);
76
- cmark_strbuf_init(buf, 0);
77
-
78
- parser->refmap = cmark_reference_map_new();
83
+ cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem) {
84
+ cmark_parser *parser = (cmark_parser *)mem->calloc(1, sizeof(cmark_parser));
85
+ parser->mem = mem;
86
+
87
+ cmark_node *document = make_document(mem);
88
+
89
+ cmark_strbuf_init(mem, &parser->curline, 256);
90
+ cmark_strbuf_init(mem, &parser->linebuf, 0);
91
+
92
+ parser->refmap = cmark_reference_map_new(mem);
79
93
  parser->root = document;
80
94
  parser->current = document;
81
95
  parser->line_number = 0;
@@ -86,22 +100,24 @@ cmark_parser *cmark_parser_new(int options) {
86
100
  parser->indent = 0;
87
101
  parser->blank = false;
88
102
  parser->partially_consumed_tab = false;
89
- parser->curline = line;
90
103
  parser->last_line_length = 0;
91
- parser->linebuf = buf;
92
104
  parser->options = options;
93
105
  parser->last_buffer_ended_with_cr = false;
94
106
 
95
107
  return parser;
96
108
  }
97
109
 
110
+ cmark_parser *cmark_parser_new(int options) {
111
+ extern cmark_mem DEFAULT_MEM_ALLOCATOR;
112
+ return cmark_parser_new_with_mem(options, &DEFAULT_MEM_ALLOCATOR);
113
+ }
114
+
98
115
  void cmark_parser_free(cmark_parser *parser) {
99
- cmark_strbuf_free(parser->curline);
100
- free(parser->curline);
101
- cmark_strbuf_free(parser->linebuf);
102
- free(parser->linebuf);
116
+ cmark_mem *mem = parser->mem;
117
+ cmark_strbuf_free(&parser->curline);
118
+ cmark_strbuf_free(&parser->linebuf);
103
119
  cmark_reference_map_free(parser->refmap);
104
- free(parser);
120
+ mem->free(parser);
105
121
  }
106
122
 
107
123
  static cmark_node *finalize(cmark_parser *parser, cmark_node *b);
@@ -128,7 +144,7 @@ static bool is_blank(cmark_strbuf *s, bufsize_t offset) {
128
144
  }
129
145
 
130
146
  static CMARK_INLINE bool can_contain(cmark_node_type parent_type,
131
- cmark_node_type child_type) {
147
+ cmark_node_type child_type) {
132
148
  return (parent_type == CMARK_NODE_DOCUMENT ||
133
149
  parent_type == CMARK_NODE_BLOCK_QUOTE ||
134
150
  parent_type == CMARK_NODE_ITEM ||
@@ -149,18 +165,17 @@ static CMARK_INLINE bool contains_inlines(cmark_node_type block_type) {
149
165
  static void add_line(cmark_node *node, cmark_chunk *ch, cmark_parser *parser) {
150
166
  int chars_to_tab;
151
167
  int i;
152
- assert(node->open);
168
+ assert(node->flags & CMARK_NODE__OPEN);
153
169
  if (parser->partially_consumed_tab) {
154
170
  parser->offset += 1; // skip over tab
155
171
  // add space characters:
156
172
  chars_to_tab = TAB_STOP - (parser->column % TAB_STOP);
157
173
  for (i = 0; i < chars_to_tab; i++) {
158
- cmark_strbuf_putc(&node->string_content, ' ');
174
+ cmark_strbuf_putc(&node->content, ' ');
159
175
  }
160
176
  }
161
- cmark_strbuf_put(&node->string_content,
162
- ch->data + parser->offset,
163
- ch->len - parser->offset);
177
+ cmark_strbuf_put(&node->content, ch->data + parser->offset,
178
+ ch->len - parser->offset);
164
179
  }
165
180
 
166
181
  static void remove_trailing_blank_lines(cmark_strbuf *ln) {
@@ -195,10 +210,10 @@ static void remove_trailing_blank_lines(cmark_strbuf *ln) {
195
210
  static bool ends_with_blank_line(cmark_node *node) {
196
211
  cmark_node *cur = node;
197
212
  while (cur != NULL) {
198
- if (cur->last_line_blank) {
213
+ if (S_last_line_blank(cur)) {
199
214
  return true;
200
215
  }
201
- if (cur->type == CMARK_NODE_LIST || cur->type == CMARK_NODE_ITEM) {
216
+ if (S_type(cur) == CMARK_NODE_LIST || S_type(cur) == CMARK_NODE_ITEM) {
202
217
  cur = cur->last_child;
203
218
  } else {
204
219
  cur = NULL;
@@ -212,7 +227,7 @@ static int break_out_of_lists(cmark_parser *parser, cmark_node **bptr) {
212
227
  cmark_node *container = *bptr;
213
228
  cmark_node *b = parser->root;
214
229
  // find first containing NODE_LIST:
215
- while (b && b->type != CMARK_NODE_LIST) {
230
+ while (b && S_type(b) != CMARK_NODE_LIST) {
216
231
  b = b->last_child;
217
232
  }
218
233
  if (b) {
@@ -232,37 +247,38 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
232
247
  cmark_node *parent;
233
248
 
234
249
  parent = b->parent;
250
+ assert(b->flags & CMARK_NODE__OPEN); // shouldn't call finalize on closed blocks
251
+ b->flags &= ~CMARK_NODE__OPEN;
235
252
 
236
- assert(b->open); // shouldn't call finalize on closed blocks
237
- b->open = false;
238
-
239
- if (parser->curline->size == 0) {
253
+ if (parser->curline.size == 0) {
240
254
  // end of input - line number has not been incremented
241
255
  b->end_line = parser->line_number;
242
256
  b->end_column = parser->last_line_length;
243
- } else if (b->type == CMARK_NODE_DOCUMENT ||
244
- (b->type == CMARK_NODE_CODE_BLOCK && b->as.code.fenced) ||
245
- (b->type == CMARK_NODE_HEADING && b->as.heading.setext)) {
257
+ } else if (S_type(b) == CMARK_NODE_DOCUMENT ||
258
+ (S_type(b) == CMARK_NODE_CODE_BLOCK && b->as.code.fenced) ||
259
+ (S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext)) {
246
260
  b->end_line = parser->line_number;
247
- b->end_column = parser->curline->size;
248
- if (b->end_column && parser->curline->ptr[b->end_column - 1] == '\n')
261
+ b->end_column = parser->curline.size;
262
+ if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\n')
249
263
  b->end_column -= 1;
250
- if (b->end_column && parser->curline->ptr[b->end_column - 1] == '\r')
264
+ if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\r')
251
265
  b->end_column -= 1;
252
266
  } else {
253
267
  b->end_line = parser->line_number - 1;
254
268
  b->end_column = parser->last_line_length;
255
269
  }
256
270
 
257
- switch (b->type) {
271
+ cmark_strbuf *node_content = &b->content;
272
+
273
+ switch (S_type(b)) {
258
274
  case CMARK_NODE_PARAGRAPH:
259
- while (cmark_strbuf_at(&b->string_content, 0) == '[' &&
260
- (pos = cmark_parse_reference_inline(&b->string_content,
275
+ while (cmark_strbuf_at(node_content, 0) == '[' &&
276
+ (pos = cmark_parse_reference_inline(parser->mem, node_content,
261
277
  parser->refmap))) {
262
278
 
263
- cmark_strbuf_drop(&b->string_content, pos);
279
+ cmark_strbuf_drop(node_content, pos);
264
280
  }
265
- if (is_blank(&b->string_content, 0)) {
281
+ if (is_blank(node_content, 0)) {
266
282
  // remove blank node (former reference def)
267
283
  cmark_node_free(b);
268
284
  }
@@ -270,34 +286,33 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
270
286
 
271
287
  case CMARK_NODE_CODE_BLOCK:
272
288
  if (!b->as.code.fenced) { // indented code
273
- remove_trailing_blank_lines(&b->string_content);
274
- cmark_strbuf_putc(&b->string_content, '\n');
289
+ remove_trailing_blank_lines(node_content);
290
+ cmark_strbuf_putc(node_content, '\n');
275
291
  } else {
276
-
277
292
  // first line of contents becomes info
278
- for (pos = 0; pos < b->string_content.size; ++pos) {
279
- if (S_is_line_end_char(b->string_content.ptr[pos]))
293
+ for (pos = 0; pos < node_content->size; ++pos) {
294
+ if (S_is_line_end_char(node_content->ptr[pos]))
280
295
  break;
281
296
  }
282
- assert(pos < b->string_content.size);
297
+ assert(pos < node_content->size);
283
298
 
284
- cmark_strbuf tmp = GH_BUF_INIT;
285
- houdini_unescape_html_f(&tmp, b->string_content.ptr, pos);
299
+ cmark_strbuf tmp = CMARK_BUF_INIT(parser->mem);
300
+ houdini_unescape_html_f(&tmp, node_content->ptr, pos);
286
301
  cmark_strbuf_trim(&tmp);
287
302
  cmark_strbuf_unescape(&tmp);
288
303
  b->as.code.info = cmark_chunk_buf_detach(&tmp);
289
304
 
290
- if (b->string_content.ptr[pos] == '\r')
305
+ if (node_content->ptr[pos] == '\r')
291
306
  pos += 1;
292
- if (b->string_content.ptr[pos] == '\n')
307
+ if (node_content->ptr[pos] == '\n')
293
308
  pos += 1;
294
- cmark_strbuf_drop(&b->string_content, pos);
309
+ cmark_strbuf_drop(node_content, pos);
295
310
  }
296
- b->as.code.literal = cmark_chunk_buf_detach(&b->string_content);
311
+ b->as.code.literal = cmark_chunk_buf_detach(node_content);
297
312
  break;
298
313
 
299
314
  case CMARK_NODE_HTML_BLOCK:
300
- b->as.literal = cmark_chunk_buf_detach(&b->string_content);
315
+ b->as.literal = cmark_chunk_buf_detach(node_content);
301
316
  break;
302
317
 
303
318
  case CMARK_NODE_LIST: // determine tight/loose status
@@ -306,7 +321,7 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
306
321
 
307
322
  while (item) {
308
323
  // check for non-final non-empty list item ending with blank line:
309
- if (item->last_line_blank && item->next) {
324
+ if (S_last_line_blank(item) && item->next) {
310
325
  b->as.list.tight = false;
311
326
  break;
312
327
  }
@@ -331,6 +346,7 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
331
346
  default:
332
347
  break;
333
348
  }
349
+
334
350
  return parent;
335
351
  }
336
352
 
@@ -341,11 +357,11 @@ static cmark_node *add_child(cmark_parser *parser, cmark_node *parent,
341
357
 
342
358
  // if 'parent' isn't the kind of node that can accept this child,
343
359
  // then back up til we hit a node that can.
344
- while (!can_contain(parent->type, block_type)) {
360
+ while (!can_contain(S_type(parent), block_type)) {
345
361
  parent = finalize(parser, parent);
346
362
  }
347
363
 
348
- cmark_node *child = make_block(block_type, parser->line_number, start_column);
364
+ cmark_node *child = make_block(parser->mem, block_type, parser->line_number, start_column);
349
365
  child->parent = parent;
350
366
 
351
367
  if (parent->last_child) {
@@ -361,7 +377,7 @@ static cmark_node *add_child(cmark_parser *parser, cmark_node *parent,
361
377
 
362
378
  // Walk through node and all children, recursively, parsing
363
379
  // string content into inline content where appropriate.
364
- static void process_inlines(cmark_node *root, cmark_reference_map *refmap,
380
+ static void process_inlines(cmark_mem *mem, cmark_node *root, cmark_reference_map *refmap,
365
381
  int options) {
366
382
  cmark_iter *iter = cmark_iter_new(root);
367
383
  cmark_node *cur;
@@ -370,8 +386,8 @@ static void process_inlines(cmark_node *root, cmark_reference_map *refmap,
370
386
  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
371
387
  cur = cmark_iter_get_node(iter);
372
388
  if (ev_type == CMARK_EVENT_ENTER) {
373
- if (contains_inlines(cur->type)) {
374
- cmark_parse_inlines(cur, refmap, options);
389
+ if (contains_inlines(S_type(cur))) {
390
+ cmark_parse_inlines(mem, cur, refmap, options);
375
391
  }
376
392
  }
377
393
  }
@@ -382,7 +398,7 @@ static void process_inlines(cmark_node *root, cmark_reference_map *refmap,
382
398
  // Attempts to parse a list item marker (bullet or enumerated).
383
399
  // On success, returns length of the marker, and populates
384
400
  // data with the details. On failure, returns 0.
385
- static bufsize_t parse_list_marker(cmark_chunk *input, bufsize_t pos,
401
+ static bufsize_t parse_list_marker(cmark_mem *mem, cmark_chunk *input, bufsize_t pos,
386
402
  cmark_list **dataptr) {
387
403
  unsigned char c;
388
404
  bufsize_t startpos;
@@ -396,17 +412,13 @@ static bufsize_t parse_list_marker(cmark_chunk *input, bufsize_t pos,
396
412
  if (!cmark_isspace(peek_at(input, pos))) {
397
413
  return 0;
398
414
  }
399
- data = (cmark_list *)calloc(1, sizeof(*data));
400
- if (data == NULL) {
401
- return 0;
402
- } else {
403
- data->marker_offset = 0; // will be adjusted later
404
- data->list_type = CMARK_BULLET_LIST;
405
- data->bullet_char = c;
406
- data->start = 1;
407
- data->delimiter = CMARK_PERIOD_DELIM;
408
- data->tight = false;
409
- }
415
+ data = (cmark_list *)mem->calloc(1, sizeof(*data));
416
+ data->marker_offset = 0; // will be adjusted later
417
+ data->list_type = CMARK_BULLET_LIST;
418
+ data->bullet_char = c;
419
+ data->start = 1;
420
+ data->delimiter = CMARK_PERIOD_DELIM;
421
+ data->tight = false;
410
422
  } else if (cmark_isdigit(c)) {
411
423
  int start = 0;
412
424
  int digits = 0;
@@ -426,21 +438,16 @@ static bufsize_t parse_list_marker(cmark_chunk *input, bufsize_t pos,
426
438
  if (!cmark_isspace(peek_at(input, pos))) {
427
439
  return 0;
428
440
  }
429
- data = (cmark_list *)calloc(1, sizeof(*data));
430
- if (data == NULL) {
431
- return 0;
432
- } else {
433
- data->marker_offset = 0; // will be adjusted later
434
- data->list_type = CMARK_ORDERED_LIST;
435
- data->bullet_char = 0;
436
- data->start = start;
437
- data->delimiter = (c == '.' ? CMARK_PERIOD_DELIM : CMARK_PAREN_DELIM);
438
- data->tight = false;
439
- }
441
+ data = (cmark_list *)mem->calloc(1, sizeof(*data));
442
+ data->marker_offset = 0; // will be adjusted later
443
+ data->list_type = CMARK_ORDERED_LIST;
444
+ data->bullet_char = 0;
445
+ data->start = start;
446
+ data->delimiter = (c == '.' ? CMARK_PERIOD_DELIM : CMARK_PAREN_DELIM);
447
+ data->tight = false;
440
448
  } else {
441
449
  return 0;
442
450
  }
443
-
444
451
  } else {
445
452
  return 0;
446
453
  }
@@ -463,7 +470,7 @@ static cmark_node *finalize_document(cmark_parser *parser) {
463
470
  }
464
471
 
465
472
  finalize(parser, parser->root);
466
- process_inlines(parser->root, parser->refmap, parser->options);
473
+ process_inlines(parser->mem, parser->root, parser->refmap, parser->options);
467
474
 
468
475
  return parser->root;
469
476
  }
@@ -529,24 +536,24 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
529
536
  process = true;
530
537
  }
531
538
 
532
- chunk_len = cmark_strbuf_check_bufsize(eol - buffer);
539
+ chunk_len = (eol - buffer);
533
540
  if (process) {
534
- if (parser->linebuf->size > 0) {
535
- cmark_strbuf_put(parser->linebuf, buffer, chunk_len);
536
- S_process_line(parser, parser->linebuf->ptr, parser->linebuf->size);
537
- cmark_strbuf_clear(parser->linebuf);
541
+ if (parser->linebuf.size > 0) {
542
+ cmark_strbuf_put(&parser->linebuf, buffer, chunk_len);
543
+ S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size);
544
+ cmark_strbuf_clear(&parser->linebuf);
538
545
  } else {
539
546
  S_process_line(parser, buffer, chunk_len);
540
547
  }
541
548
  } else {
542
549
  if (eol < end && *eol == '\0') {
543
550
  // omit NULL byte
544
- cmark_strbuf_put(parser->linebuf, buffer, chunk_len);
551
+ cmark_strbuf_put(&parser->linebuf, buffer, chunk_len);
545
552
  // add replacement character
546
- cmark_strbuf_put(parser->linebuf, repl, 3);
553
+ cmark_strbuf_put(&parser->linebuf, repl, 3);
547
554
  chunk_len += 1; // so we advance the buffer past NULL
548
555
  } else {
549
- cmark_strbuf_put(parser->linebuf, buffer, chunk_len);
556
+ cmark_strbuf_put(&parser->linebuf, buffer, chunk_len);
550
557
  }
551
558
  }
552
559
 
@@ -555,7 +562,7 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
555
562
  if (buffer < end && *buffer == '\r') {
556
563
  buffer++;
557
564
  if (buffer == end)
558
- parser->last_buffer_ended_with_cr = true;
565
+ parser->last_buffer_ended_with_cr = true;
559
566
  }
560
567
  if (buffer < end && *buffer == '\n')
561
568
  buffer++;
@@ -627,16 +634,16 @@ static void S_advance_offset(cmark_parser *parser, cmark_chunk *input,
627
634
  if (c == '\t') {
628
635
  chars_to_tab = TAB_STOP - (parser->column % TAB_STOP);
629
636
  if (columns) {
630
- parser->partially_consumed_tab = chars_to_tab > count;
631
- chars_to_advance = MIN(count, chars_to_tab);
632
- parser->column += chars_to_advance;
637
+ parser->partially_consumed_tab = chars_to_tab > count;
638
+ chars_to_advance = MIN(count, chars_to_tab);
639
+ parser->column += chars_to_advance;
633
640
  parser->offset += (parser->partially_consumed_tab ? 0 : 1);
634
- count -= chars_to_advance;
641
+ count -= chars_to_advance;
635
642
  } else {
636
- parser->partially_consumed_tab = false;
637
- parser->column += chars_to_tab;
638
- parser->offset += 1;
639
- count -= 1;
643
+ parser->partially_consumed_tab = false;
644
+ parser->column += chars_to_tab;
645
+ parser->offset += 1;
646
+ count -= 1;
640
647
  }
641
648
  } else {
642
649
  parser->partially_consumed_tab = false;
@@ -648,12 +655,10 @@ static void S_advance_offset(cmark_parser *parser, cmark_chunk *input,
648
655
  }
649
656
 
650
657
  static bool S_last_child_is_open(cmark_node *container) {
651
- return container->last_child && container->last_child->open;
658
+ return container->last_child && (container->last_child->flags & CMARK_NODE__OPEN);
652
659
  }
653
660
 
654
- static bool parse_block_quote_prefix(cmark_parser *parser,
655
- cmark_chunk *input)
656
- {
661
+ static bool parse_block_quote_prefix(cmark_parser *parser, cmark_chunk *input) {
657
662
  bool res = false;
658
663
  bufsize_t matched = 0;
659
664
 
@@ -672,34 +677,30 @@ static bool parse_block_quote_prefix(cmark_parser *parser,
672
677
  return res;
673
678
  }
674
679
 
675
- static bool parse_node_item_prefix(cmark_parser *parser,
676
- cmark_chunk *input,
677
- cmark_node *container)
678
- {
680
+ static bool parse_node_item_prefix(cmark_parser *parser, cmark_chunk *input,
681
+ cmark_node *container) {
679
682
  bool res = false;
680
683
 
681
684
  if (parser->indent >=
682
685
  container->as.list.marker_offset + container->as.list.padding) {
683
686
  S_advance_offset(parser, input, container->as.list.marker_offset +
684
- container->as.list.padding,
687
+ container->as.list.padding,
685
688
  true);
686
689
  res = true;
687
690
  } else if (parser->blank && container->first_child != NULL) {
688
691
  // if container->first_child is NULL, then the opening line
689
692
  // of the list item was blank after the list marker; in this
690
693
  // case, we are done with the list item.
691
- S_advance_offset(parser, input,
692
- parser->first_nonspace - parser->offset, false);
694
+ S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
695
+ false);
693
696
  res = true;
694
697
  }
695
698
  return res;
696
699
  }
697
700
 
698
- static bool parse_code_block_prefix(cmark_parser *parser,
699
- cmark_chunk *input,
700
- cmark_node *container,
701
- bool *should_continue)
702
- {
701
+ static bool parse_code_block_prefix(cmark_parser *parser, cmark_chunk *input,
702
+ cmark_node *container,
703
+ bool *should_continue) {
703
704
  bool res = false;
704
705
 
705
706
  if (!container->as.code.fenced) { // indented
@@ -707,8 +708,8 @@ static bool parse_code_block_prefix(cmark_parser *parser,
707
708
  S_advance_offset(parser, input, CODE_INDENT, true);
708
709
  res = true;
709
710
  } else if (parser->blank) {
710
- S_advance_offset(parser, input,
711
- parser->first_nonspace - parser->offset, false);
711
+ S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
712
+ false);
712
713
  res = true;
713
714
  }
714
715
  } else { // fenced
@@ -741,25 +742,24 @@ static bool parse_code_block_prefix(cmark_parser *parser,
741
742
  }
742
743
 
743
744
  static bool parse_html_block_prefix(cmark_parser *parser,
744
- cmark_node *container)
745
- {
745
+ cmark_node *container) {
746
746
  bool res = false;
747
747
  int html_block_type = container->as.html_block_type;
748
748
 
749
749
  assert(html_block_type >= 1 && html_block_type <= 7);
750
750
  switch (html_block_type) {
751
- case 1:
752
- case 2:
753
- case 3:
754
- case 4:
755
- case 5:
756
- // these types of blocks can accept blanks
757
- res = true;
758
- break;
759
- case 6:
760
- case 7:
761
- res = !parser->blank;
762
- break;
751
+ case 1:
752
+ case 2:
753
+ case 3:
754
+ case 4:
755
+ case 5:
756
+ // these types of blocks can accept blanks
757
+ res = true;
758
+ break;
759
+ case 6:
760
+ case 7:
761
+ res = !parser->blank;
762
+ break;
763
763
  }
764
764
 
765
765
  return res;
@@ -773,10 +773,8 @@ static bool parse_html_block_prefix(cmark_parser *parser,
773
773
  *
774
774
  * Returns: The last matching node, or NULL
775
775
  */
776
- static cmark_node *check_open_blocks(cmark_parser *parser,
777
- cmark_chunk *input,
778
- bool *all_matched)
779
- {
776
+ static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input,
777
+ bool *all_matched) {
780
778
  bool should_continue = true;
781
779
  *all_matched = false;
782
780
  cmark_node *container = parser->root;
@@ -784,36 +782,36 @@ static cmark_node *check_open_blocks(cmark_parser *parser,
784
782
 
785
783
  while (S_last_child_is_open(container)) {
786
784
  container = container->last_child;
787
- cont_type = container->type;
785
+ cont_type = S_type(container);
788
786
 
789
787
  S_find_first_nonspace(parser, input);
790
788
 
791
789
  switch (cont_type) {
792
- case CMARK_NODE_BLOCK_QUOTE:
793
- if (!parse_block_quote_prefix(parser, input))
794
- goto done;
795
- break;
796
- case CMARK_NODE_ITEM:
797
- if (!parse_node_item_prefix(parser, input, container))
798
- goto done;
799
- break;
800
- case CMARK_NODE_CODE_BLOCK:
801
- if (!parse_code_block_prefix(parser, input, container, &should_continue))
802
- goto done;
803
- break;
804
- case CMARK_NODE_HEADING:
805
- // a heading can never contain more than one line
790
+ case CMARK_NODE_BLOCK_QUOTE:
791
+ if (!parse_block_quote_prefix(parser, input))
806
792
  goto done;
807
- case CMARK_NODE_HTML_BLOCK:
808
- if (!parse_html_block_prefix(parser, container))
809
- goto done;
810
- break;
811
- case CMARK_NODE_PARAGRAPH:
812
- if (parser->blank)
813
- goto done;
814
- break;
815
- default:
816
- break;
793
+ break;
794
+ case CMARK_NODE_ITEM:
795
+ if (!parse_node_item_prefix(parser, input, container))
796
+ goto done;
797
+ break;
798
+ case CMARK_NODE_CODE_BLOCK:
799
+ if (!parse_code_block_prefix(parser, input, container, &should_continue))
800
+ goto done;
801
+ break;
802
+ case CMARK_NODE_HEADING:
803
+ // a heading can never contain more than one line
804
+ goto done;
805
+ case CMARK_NODE_HTML_BLOCK:
806
+ if (!parse_html_block_prefix(parser, container))
807
+ goto done;
808
+ break;
809
+ case CMARK_NODE_PARAGRAPH:
810
+ if (parser->blank)
811
+ goto done;
812
+ break;
813
+ default:
814
+ break;
817
815
  }
818
816
  }
819
817
 
@@ -831,15 +829,12 @@ done:
831
829
  return container;
832
830
  }
833
831
 
834
- static void open_new_blocks(cmark_parser *parser,
835
- cmark_node **container,
836
- cmark_chunk *input,
837
- bool all_matched)
838
- {
832
+ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
833
+ cmark_chunk *input, bool all_matched) {
839
834
  bool indented;
840
835
  cmark_list *data = NULL;
841
- bool maybe_lazy = parser->current->type == CMARK_NODE_PARAGRAPH;
842
- cmark_node_type cont_type = (*container)->type;
836
+ bool maybe_lazy = S_type(parser->current) == CMARK_NODE_PARAGRAPH;
837
+ cmark_node_type cont_type = S_type(*container);
843
838
  bufsize_t matched = 0;
844
839
  int lev = 0;
845
840
  bool save_partially_consumed_tab;
@@ -861,7 +856,7 @@ static void open_new_blocks(cmark_parser *parser,
861
856
  S_advance_offset(parser, input, 1, true);
862
857
  }
863
858
  *container = add_child(parser, *container, CMARK_NODE_BLOCK_QUOTE,
864
- parser->offset + 1);
859
+ parser->offset + 1);
865
860
 
866
861
  } else if (!indented && (matched = scan_atx_heading_start(
867
862
  input, parser->first_nonspace))) {
@@ -887,10 +882,10 @@ static void open_new_blocks(cmark_parser *parser,
887
882
  } else if (!indented && (matched = scan_open_code_fence(
888
883
  input, parser->first_nonspace))) {
889
884
  *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK,
890
- parser->first_nonspace + 1);
885
+ parser->first_nonspace + 1);
891
886
  (*container)->as.code.fenced = true;
892
887
  (*container)->as.code.fence_char = peek_at(input, parser->first_nonspace);
893
- (*container)->as.code.fence_length = matched;
888
+ (*container)->as.code.fence_length = (matched > 255) ? 255 : matched;
894
889
  (*container)->as.code.fence_offset =
895
890
  (int8_t)(parser->first_nonspace - parser->offset);
896
891
  (*container)->as.code.info = cmark_chunk_literal("");
@@ -904,27 +899,26 @@ static void open_new_blocks(cmark_parser *parser,
904
899
  (matched = scan_html_block_start_7(
905
900
  input, parser->first_nonspace))))) {
906
901
  *container = add_child(parser, *container, CMARK_NODE_HTML_BLOCK,
907
- parser->first_nonspace + 1);
902
+ parser->first_nonspace + 1);
908
903
  (*container)->as.html_block_type = matched;
909
904
  // note, we don't adjust parser->offset because the tag is part of the
910
905
  // text
911
906
  } else if (!indented && cont_type == CMARK_NODE_PARAGRAPH &&
912
907
  (lev =
913
908
  scan_setext_heading_line(input, parser->first_nonspace))) {
914
- (*container)->type = CMARK_NODE_HEADING;
909
+ (*container)->type = (uint16_t)CMARK_NODE_HEADING;
915
910
  (*container)->as.heading.level = lev;
916
911
  (*container)->as.heading.setext = true;
917
912
  S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
918
913
  } else if (!indented &&
919
914
  !(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) &&
920
- (matched =
921
- scan_thematic_break(input, parser->first_nonspace))) {
915
+ (matched = scan_thematic_break(input, parser->first_nonspace))) {
922
916
  // it's only now that we know the line is not part of a setext heading:
923
917
  *container = add_child(parser, *container, CMARK_NODE_THEMATIC_BREAK,
924
- parser->first_nonspace + 1);
918
+ parser->first_nonspace + 1);
925
919
  S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
926
920
  } else if ((matched =
927
- parse_list_marker(input, parser->first_nonspace, &data)) &&
921
+ parse_list_marker(parser->mem, input, parser->first_nonspace, &data)) &&
928
922
  (!indented || cont_type == CMARK_NODE_LIST)) {
929
923
  // Note that we can have new list items starting with >= 4
930
924
  // spaces indent, as long as the list container is still open.
@@ -940,16 +934,18 @@ static void open_new_blocks(cmark_parser *parser,
940
934
  save_column = parser->column;
941
935
 
942
936
  while (parser->column - save_column <= 5 &&
943
- S_is_space_or_tab(peek_at(input, parser->offset))) {
937
+ S_is_space_or_tab(peek_at(input, parser->offset))) {
944
938
  S_advance_offset(parser, input, 1, true);
945
939
  }
946
940
 
947
941
  i = parser->column - save_column;
948
- if (i >= 5 || i < 1) {
942
+ if (i >= 5 || i < 1 ||
943
+ // only spaces after list marker:
944
+ S_is_line_end_char(peek_at(input, parser->offset))) {
949
945
  data->padding = matched + 1;
950
- parser->offset = save_offset;
951
- parser->column = save_column;
952
- parser->partially_consumed_tab = save_partially_consumed_tab;
946
+ parser->offset = save_offset;
947
+ parser->column = save_column;
948
+ parser->partially_consumed_tab = save_partially_consumed_tab;
953
949
  if (i > 0) {
954
950
  S_advance_offset(parser, input, 1, true);
955
951
  }
@@ -965,21 +961,21 @@ static void open_new_blocks(cmark_parser *parser,
965
961
  if (cont_type != CMARK_NODE_LIST ||
966
962
  !lists_match(&((*container)->as.list), data)) {
967
963
  *container = add_child(parser, *container, CMARK_NODE_LIST,
968
- parser->first_nonspace + 1);
964
+ parser->first_nonspace + 1);
969
965
 
970
966
  memcpy(&((*container)->as.list), data, sizeof(*data));
971
967
  }
972
968
 
973
969
  // add the list item
974
970
  *container = add_child(parser, *container, CMARK_NODE_ITEM,
975
- parser->first_nonspace + 1);
971
+ parser->first_nonspace + 1);
976
972
  /* TODO: static */
977
973
  memcpy(&((*container)->as.list), data, sizeof(*data));
978
974
  free(data);
979
975
  } else if (indented && !maybe_lazy && !parser->blank) {
980
976
  S_advance_offset(parser, input, CODE_INDENT, true);
981
977
  *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK,
982
- parser->offset + 1);
978
+ parser->offset + 1);
983
979
  (*container)->as.code.fenced = false;
984
980
  (*container)->as.code.fence_char = 0;
985
981
  (*container)->as.code.fence_length = 0;
@@ -990,21 +986,19 @@ static void open_new_blocks(cmark_parser *parser,
990
986
  break;
991
987
  }
992
988
 
993
- if (accepts_lines((*container)->type)) {
989
+ if (accepts_lines(S_type(*container))) {
994
990
  // if it's a line container, it can't contain other containers
995
991
  break;
996
992
  }
997
993
 
998
- cont_type = (*container)->type;
994
+ cont_type = S_type(*container);
999
995
  maybe_lazy = false;
1000
996
  }
1001
997
  }
1002
998
 
1003
- static void add_text_to_container (cmark_parser *parser,
1004
- cmark_node *container,
1005
- cmark_node *last_matched_container,
1006
- cmark_chunk *input)
1007
- {
999
+ static void add_text_to_container(cmark_parser *parser, cmark_node *container,
1000
+ cmark_node *last_matched_container,
1001
+ cmark_chunk *input) {
1008
1002
  cmark_node *tmp;
1009
1003
  // what remains at parser->offset is a text line. add the text to the
1010
1004
  // appropriate container.
@@ -1012,24 +1006,26 @@ static void add_text_to_container (cmark_parser *parser,
1012
1006
  S_find_first_nonspace(parser, input);
1013
1007
 
1014
1008
  if (parser->blank && container->last_child)
1015
- container->last_child->last_line_blank = true;
1009
+ S_set_last_line_blank(container->last_child, true);
1016
1010
 
1017
1011
  // block quote lines are never blank as they start with >
1018
1012
  // and we don't count blanks in fenced code for purposes of tight/loose
1019
1013
  // lists or breaking out of lists. we also don't set last_line_blank
1020
1014
  // on an empty list item.
1021
- container->last_line_blank =
1022
- (parser->blank && container->type != CMARK_NODE_BLOCK_QUOTE &&
1023
- container->type != CMARK_NODE_HEADING &&
1024
- container->type != CMARK_NODE_THEMATIC_BREAK &&
1025
- !(container->type == CMARK_NODE_CODE_BLOCK &&
1026
- container->as.code.fenced) &&
1027
- !(container->type == CMARK_NODE_ITEM && container->first_child == NULL &&
1015
+ const cmark_node_type ctype = S_type(container);
1016
+ const bool last_line_blank =
1017
+ (parser->blank && ctype != CMARK_NODE_BLOCK_QUOTE &&
1018
+ ctype != CMARK_NODE_HEADING &&
1019
+ ctype != CMARK_NODE_THEMATIC_BREAK &&
1020
+ !(ctype == CMARK_NODE_CODE_BLOCK && container->as.code.fenced) &&
1021
+ !(ctype == CMARK_NODE_ITEM && container->first_child == NULL &&
1028
1022
  container->start_line == parser->line_number));
1029
1023
 
1024
+ S_set_last_line_blank(container, last_line_blank);
1025
+
1030
1026
  tmp = container;
1031
1027
  while (tmp->parent) {
1032
- tmp->parent->last_line_blank = false;
1028
+ S_set_last_line_blank(tmp->parent, false);
1033
1029
  tmp = tmp->parent;
1034
1030
  }
1035
1031
 
@@ -1040,9 +1036,8 @@ static void add_text_to_container (cmark_parser *parser,
1040
1036
  // then treat this as a "lazy continuation line" and add it to
1041
1037
  // the open paragraph.
1042
1038
  if (parser->current != last_matched_container &&
1043
- container == last_matched_container &&
1044
- !parser->blank &&
1045
- parser->current->type == CMARK_NODE_PARAGRAPH) {
1039
+ container == last_matched_container && !parser->blank &&
1040
+ S_type(parser->current) == CMARK_NODE_PARAGRAPH) {
1046
1041
  add_line(parser->current, input, parser);
1047
1042
  } else { // not a lazy continuation
1048
1043
  // Finalize any blocks that were not matched and set cur to container:
@@ -1051,9 +1046,9 @@ static void add_text_to_container (cmark_parser *parser,
1051
1046
  assert(parser->current != NULL);
1052
1047
  }
1053
1048
 
1054
- if (container->type == CMARK_NODE_CODE_BLOCK) {
1049
+ if (S_type(container) == CMARK_NODE_CODE_BLOCK) {
1055
1050
  add_line(container, input, parser);
1056
- } else if (container->type == CMARK_NODE_HTML_BLOCK) {
1051
+ } else if (S_type(container) == CMARK_NODE_HTML_BLOCK) {
1057
1052
  add_line(container, input, parser);
1058
1053
 
1059
1054
  int matches_end_condition;
@@ -1094,18 +1089,20 @@ static void add_text_to_container (cmark_parser *parser,
1094
1089
  }
1095
1090
  } else if (parser->blank) {
1096
1091
  // ??? do nothing
1097
- } else if (accepts_lines(container->type)) {
1098
- if (container->type == CMARK_NODE_HEADING &&
1092
+ } else if (accepts_lines(S_type(container))) {
1093
+ if (S_type(container) == CMARK_NODE_HEADING &&
1099
1094
  container->as.heading.setext == false) {
1100
1095
  chop_trailing_hashtags(input);
1101
1096
  }
1102
- S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false);
1097
+ S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
1098
+ false);
1103
1099
  add_line(container, input, parser);
1104
1100
  } else {
1105
1101
  // create paragraph container for line
1106
1102
  container = add_child(parser, container, CMARK_NODE_PARAGRAPH,
1107
1103
  parser->first_nonspace + 1);
1108
- S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false);
1104
+ S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
1105
+ false);
1109
1106
  add_line(container, input, parser);
1110
1107
  }
1111
1108
 
@@ -1122,21 +1119,21 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
1122
1119
  cmark_chunk input;
1123
1120
 
1124
1121
  if (parser->options & CMARK_OPT_VALIDATE_UTF8)
1125
- cmark_utf8proc_check(parser->curline, buffer, bytes);
1122
+ cmark_utf8proc_check(&parser->curline, buffer, bytes);
1126
1123
  else
1127
- cmark_strbuf_put(parser->curline, buffer, bytes);
1124
+ cmark_strbuf_put(&parser->curline, buffer, bytes);
1128
1125
 
1129
1126
  // ensure line ends with a newline:
1130
- if (bytes == 0 || !S_is_line_end_char(parser->curline->ptr[bytes - 1]))
1131
- cmark_strbuf_putc(parser->curline, '\n');
1127
+ if (bytes == 0 || !S_is_line_end_char(parser->curline.ptr[bytes - 1]))
1128
+ cmark_strbuf_putc(&parser->curline, '\n');
1132
1129
 
1133
1130
  parser->offset = 0;
1134
1131
  parser->column = 0;
1135
1132
  parser->blank = false;
1136
1133
  parser->partially_consumed_tab = false;
1137
1134
 
1138
- input.data = parser->curline->ptr;
1139
- input.len = parser->curline->size;
1135
+ input.data = parser->curline.ptr;
1136
+ input.len = parser->curline.size;
1140
1137
 
1141
1138
  parser->line_number++;
1142
1139
 
@@ -1148,7 +1145,7 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
1148
1145
  container = last_matched_container;
1149
1146
 
1150
1147
  // check to see if we've hit 2nd blank line, break out of list:
1151
- if (parser->blank && container->last_line_blank)
1148
+ if (parser->blank && S_last_line_blank(container))
1152
1149
  break_out_of_lists(parser, &container);
1153
1150
 
1154
1151
  open_new_blocks(parser, &container, &input, all_matched);
@@ -1164,13 +1161,13 @@ finished:
1164
1161
  input.data[parser->last_line_length - 1] == '\r')
1165
1162
  parser->last_line_length -= 1;
1166
1163
 
1167
- cmark_strbuf_clear(parser->curline);
1164
+ cmark_strbuf_clear(&parser->curline);
1168
1165
  }
1169
1166
 
1170
1167
  cmark_node *cmark_parser_finish(cmark_parser *parser) {
1171
- if (parser->linebuf->size) {
1172
- S_process_line(parser, parser->linebuf->ptr, parser->linebuf->size);
1173
- cmark_strbuf_clear(parser->linebuf);
1168
+ if (parser->linebuf.size) {
1169
+ S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size);
1170
+ cmark_strbuf_clear(&parser->linebuf);
1174
1171
  }
1175
1172
 
1176
1173
  finalize_document(parser);
@@ -1179,7 +1176,7 @@ cmark_node *cmark_parser_finish(cmark_parser *parser) {
1179
1176
  cmark_consolidate_text_nodes(parser->root);
1180
1177
  }
1181
1178
 
1182
- cmark_strbuf_free(parser->curline);
1179
+ cmark_strbuf_free(&parser->curline);
1183
1180
 
1184
1181
  #if CMARK_DEBUG_NODES
1185
1182
  if (cmark_node_check(parser->root, stderr)) {