rpeg-markdown 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. data/README +25 -1
  2. data/Rakefile +85 -16
  3. data/ext/extconf.h +3 -0
  4. data/ext/extconf.rb +13 -2
  5. data/ext/markdown.c +27 -71
  6. data/ext/markdown_lib.c +181 -0
  7. data/ext/markdown_lib.h +19 -0
  8. data/ext/markdown_output.c +313 -327
  9. data/ext/markdown_parser.c +2817 -2920
  10. data/ext/markdown_peg.h +10 -24
  11. data/ext/parsing_functions.c +104 -0
  12. data/ext/utility_functions.c +220 -0
  13. data/lib/markdown.rb +22 -2
  14. data/test/MarkdownTest_1.0/MarkdownTest.pl +157 -0
  15. data/test/MarkdownTest_1.0/Tests/Amps and angle encoding.html +17 -0
  16. data/test/MarkdownTest_1.0/Tests/Amps and angle encoding.text +21 -0
  17. data/test/MarkdownTest_1.0/Tests/Auto links.html +18 -0
  18. data/test/MarkdownTest_1.0/Tests/Auto links.text +13 -0
  19. data/test/MarkdownTest_1.0/Tests/Backslash escapes.html +102 -0
  20. data/test/MarkdownTest_1.0/Tests/Backslash escapes.text +104 -0
  21. data/test/MarkdownTest_1.0/Tests/Blockquotes with code blocks.html +15 -0
  22. data/test/MarkdownTest_1.0/Tests/Blockquotes with code blocks.text +11 -0
  23. data/test/MarkdownTest_1.0/Tests/Hard-wrapped paragraphs with list-like lines.html +8 -0
  24. data/test/MarkdownTest_1.0/Tests/Hard-wrapped paragraphs with list-like lines.text +8 -0
  25. data/test/MarkdownTest_1.0/Tests/Horizontal rules.html +71 -0
  26. data/test/MarkdownTest_1.0/Tests/Horizontal rules.text +67 -0
  27. data/test/MarkdownTest_1.0/Tests/Inline HTML (Advanced).html +14 -0
  28. data/test/MarkdownTest_1.0/Tests/Inline HTML (Advanced).text +14 -0
  29. data/test/MarkdownTest_1.0/Tests/Inline HTML (Simple).html +72 -0
  30. data/test/MarkdownTest_1.0/Tests/Inline HTML (Simple).text +69 -0
  31. data/test/MarkdownTest_1.0/Tests/Inline HTML comments.html +13 -0
  32. data/test/MarkdownTest_1.0/Tests/Inline HTML comments.text +13 -0
  33. data/test/MarkdownTest_1.0/Tests/Links, inline style.html +9 -0
  34. data/test/MarkdownTest_1.0/Tests/Links, inline style.text +9 -0
  35. data/test/MarkdownTest_1.0/Tests/Links, reference style.html +18 -0
  36. data/test/MarkdownTest_1.0/Tests/Links, reference style.text +31 -0
  37. data/test/MarkdownTest_1.0/Tests/Literal quotes in titles.html +3 -0
  38. data/test/MarkdownTest_1.0/Tests/Literal quotes in titles.text +7 -0
  39. data/test/MarkdownTest_1.0/Tests/Markdown Documentation - Basics.html +314 -0
  40. data/test/MarkdownTest_1.0/Tests/Markdown Documentation - Basics.text +306 -0
  41. data/test/MarkdownTest_1.0/Tests/Markdown Documentation - Syntax.html +942 -0
  42. data/test/MarkdownTest_1.0/Tests/Markdown Documentation - Syntax.text +888 -0
  43. data/test/MarkdownTest_1.0/Tests/Nested blockquotes.html +9 -0
  44. data/test/MarkdownTest_1.0/Tests/Nested blockquotes.text +5 -0
  45. data/test/MarkdownTest_1.0/Tests/Ordered and unordered lists.html +137 -0
  46. data/test/MarkdownTest_1.0/Tests/Ordered and unordered lists.text +122 -0
  47. data/test/MarkdownTest_1.0/Tests/Strong and em together.html +7 -0
  48. data/test/MarkdownTest_1.0/Tests/Strong and em together.text +7 -0
  49. data/test/MarkdownTest_1.0/Tests/Tabs.html +25 -0
  50. data/test/MarkdownTest_1.0/Tests/Tabs.text +21 -0
  51. data/test/MarkdownTest_1.0/Tests/Tidyness.html +8 -0
  52. data/test/MarkdownTest_1.0/Tests/Tidyness.text +5 -0
  53. data/test/MarkdownTest_1.0.3/MarkdownTest.pl +176 -0
  54. data/test/MarkdownTest_1.0.3/Tests/Amps and angle encoding.html +17 -0
  55. data/test/MarkdownTest_1.0.3/Tests/Amps and angle encoding.text +21 -0
  56. data/test/MarkdownTest_1.0.3/Tests/Auto links.html +18 -0
  57. data/test/MarkdownTest_1.0.3/Tests/Auto links.text +13 -0
  58. data/test/MarkdownTest_1.0.3/Tests/Backslash escapes.html +118 -0
  59. data/test/MarkdownTest_1.0.3/Tests/Backslash escapes.text +120 -0
  60. data/test/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html +15 -0
  61. data/test/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text +11 -0
  62. data/test/MarkdownTest_1.0.3/Tests/Code Blocks.html +18 -0
  63. data/test/MarkdownTest_1.0.3/Tests/Code Blocks.text +14 -0
  64. data/test/MarkdownTest_1.0.3/Tests/Code Spans.html +6 -0
  65. data/test/MarkdownTest_1.0.3/Tests/Code Spans.text +6 -0
  66. data/test/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html +8 -0
  67. data/test/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text +8 -0
  68. data/test/MarkdownTest_1.0.3/Tests/Horizontal rules.html +71 -0
  69. data/test/MarkdownTest_1.0.3/Tests/Horizontal rules.text +67 -0
  70. data/test/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html +15 -0
  71. data/test/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text +15 -0
  72. data/test/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html +72 -0
  73. data/test/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text +69 -0
  74. data/test/MarkdownTest_1.0.3/Tests/Inline HTML comments.html +13 -0
  75. data/test/MarkdownTest_1.0.3/Tests/Inline HTML comments.text +13 -0
  76. data/test/MarkdownTest_1.0.3/Tests/Links, inline style.html +11 -0
  77. data/test/MarkdownTest_1.0.3/Tests/Links, inline style.text +12 -0
  78. data/test/MarkdownTest_1.0.3/Tests/Links, reference style.html +52 -0
  79. data/test/MarkdownTest_1.0.3/Tests/Links, reference style.text +71 -0
  80. data/test/MarkdownTest_1.0.3/Tests/Links, shortcut references.html +9 -0
  81. data/test/MarkdownTest_1.0.3/Tests/Links, shortcut references.text +20 -0
  82. data/test/MarkdownTest_1.0.3/Tests/Literal quotes in titles.html +3 -0
  83. data/test/MarkdownTest_1.0.3/Tests/Literal quotes in titles.text +7 -0
  84. data/test/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html +314 -0
  85. data/test/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text +306 -0
  86. data/test/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html +942 -0
  87. data/test/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text +888 -0
  88. data/test/MarkdownTest_1.0.3/Tests/Nested blockquotes.html +9 -0
  89. data/test/MarkdownTest_1.0.3/Tests/Nested blockquotes.text +5 -0
  90. data/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html +148 -0
  91. data/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text +131 -0
  92. data/test/MarkdownTest_1.0.3/Tests/Strong and em together.html +7 -0
  93. data/test/MarkdownTest_1.0.3/Tests/Strong and em together.text +7 -0
  94. data/test/MarkdownTest_1.0.3/Tests/Tabs.html +25 -0
  95. data/test/MarkdownTest_1.0.3/Tests/Tabs.text +21 -0
  96. data/test/MarkdownTest_1.0.3/Tests/Tidyness.html +8 -0
  97. data/test/MarkdownTest_1.0.3/Tests/Tidyness.text +5 -0
  98. data/test/benchmark.rb +49 -0
  99. data/test/markdown_test.rb +78 -0
  100. metadata +96 -6
  101. data/ext/markdown_buffer.c +0 -46
  102. data/ext/markdown_buffer.h +0 -6
  103. data/test.rb +0 -25
@@ -20,26 +20,20 @@
20
20
  #include <stdlib.h>
21
21
  #include <string.h>
22
22
  #include <assert.h>
23
+ #include <glib.h>
23
24
  #include "markdown_peg.h"
24
25
 
25
- /***********************************************************************/
26
- #include "markdown_buffer.h"
27
- #define printf rb_markdown_buffer_printf
28
- #define putchar rb_markdown_buffer_putchar
29
- /***********************************************************************/
30
-
31
- /* TODO remove */
32
- static extensions = 0;
33
-
34
- static void print_html_string(char *str, bool obfuscate);
35
- static void print_html_element_list(element *list, bool obfuscate);
36
- static void print_html_element(element elt, bool obfuscate);
37
- static void print_latex_string(char *str);
38
- static void print_latex_element_list(element *list);
39
- static void print_latex_element(element elt);
40
- static void print_groff_string(char *str);
41
- static void print_groff_mm_element_list(element *list);
42
- static void print_groff_mm_element(element elt, int count);
26
+ static int extensions;
27
+
28
+ static void print_html_string(GString *out, char *str, bool obfuscate);
29
+ static void print_html_element_list(GString *out, element *list, bool obfuscate);
30
+ static void print_html_element(GString *out, element *elt, bool obfuscate);
31
+ static void print_latex_string(GString *out, char *str);
32
+ static void print_latex_element_list(GString *out, element *list);
33
+ static void print_latex_element(GString *out, element *elt);
34
+ static void print_groff_string(GString *out, char *str);
35
+ static void print_groff_mm_element_list(GString *out, element *list);
36
+ static void print_groff_mm_element(GString *out, element *elt, int count);
43
37
 
44
38
  /**********************************************************************
45
39
 
@@ -51,13 +45,13 @@ static int padded = 2; /* Number of newlines after last output.
51
45
  Starts at 2 so no newlines are needed at start.
52
46
  */
53
47
 
54
- static element *endnotes; /* List of endnotes to print after main content. */
48
+ static GSList *endnotes = NULL; /* List of endnotes to print after main content. */
55
49
  static int notenumber = 0; /* Number of footnote. */
56
50
 
57
51
  /* pad - add newlines if needed */
58
- static void pad(int num) {
52
+ static void pad(GString *out, int num) {
59
53
  while (num-- > padded)
60
- printf("\n");;
54
+ g_string_append_printf(out, "\n");;
61
55
  padded = num;
62
56
  }
63
57
 
@@ -69,207 +63,206 @@ static void pad(int num) {
69
63
 
70
64
  /* print_html_string - print string, escaping for HTML
71
65
  * If obfuscate selected, convert characters to hex or decimal entities at random */
72
- static void print_html_string(char *str, bool obfuscate) {
66
+ static void print_html_string(GString *out, char *str, bool obfuscate) {
73
67
  while (*str != '\0') {
74
68
  switch (*str) {
75
69
  case '&':
76
- printf("&amp;");;;
70
+ g_string_append_printf(out, "&amp;");
77
71
  break;
78
72
  case '<':
79
- printf("&lt;");;;
73
+ g_string_append_printf(out, "&lt;");
80
74
  break;
81
75
  case '>':
82
- printf("&gt;");;;
76
+ g_string_append_printf(out, "&gt;");
83
77
  break;
84
78
  case '"':
85
- printf("&quot;");;;
79
+ g_string_append_printf(out, "&quot;");
86
80
  break;
87
81
  default:
88
82
  if (obfuscate) {
89
83
  if (rand() % 2 == 0)
90
- printf("&#%d;", (int) *str);
84
+ g_string_append_printf(out, "&#%d;", (int) *str);
91
85
  else
92
- printf("&#x%x;", (unsigned int) *str);
86
+ g_string_append_printf(out, "&#x%x;", (unsigned int) *str);
93
87
  }
94
88
  else
95
- putchar(*str);
89
+ g_string_append_c(out, *str);
96
90
  }
97
91
  str++;
98
92
  }
99
93
  }
100
94
 
101
95
  /* print_html_element_list - print a list of elements as HTML */
102
- static void print_html_element_list(element *list, bool obfuscate) {
96
+ static void print_html_element_list(GString *out, element *list, bool obfuscate) {
103
97
  while (list != NULL) {
104
- print_html_element(*list, obfuscate);
98
+ print_html_element(out, list, obfuscate);
105
99
  list = list->next;
106
100
  }
107
101
  }
108
102
 
103
+ /* add_endnote - add an endnote to global endnotes list. */
104
+ static void add_endnote(element *elt) {
105
+ endnotes = g_slist_prepend(endnotes, elt);
106
+ }
107
+
109
108
  /* print_html_element - print an element as HTML */
110
- static void print_html_element(element elt, bool obfuscate) {
109
+ static void print_html_element(GString *out, element *elt, bool obfuscate) {
111
110
  int lev;
112
- char *contents;
113
- switch (elt.key) {
111
+ switch (elt->key) {
114
112
  case SPACE:
115
- printf("%s", elt.contents.str);
113
+ g_string_append_printf(out, "%s", elt->contents.str);
116
114
  break;
117
115
  case LINEBREAK:
118
- printf("<br/>");;;
116
+ g_string_append_printf(out, "<br/>");
119
117
  break;
120
118
  case STR:
121
- print_html_string(elt.contents.str, obfuscate);
119
+ print_html_string(out, elt->contents.str, obfuscate);
122
120
  break;
123
121
  case ELLIPSIS:
124
- printf("&hellip;");;;
122
+ g_string_append_printf(out, "&hellip;");
125
123
  break;
126
124
  case EMDASH:
127
- printf("&mdash;");;;
125
+ g_string_append_printf(out, "&mdash;");
128
126
  break;
129
127
  case ENDASH:
130
- printf("&ndash;");;;
128
+ g_string_append_printf(out, "&ndash;");
131
129
  break;
132
130
  case APOSTROPHE:
133
- printf("&rsquo;");;;
131
+ g_string_append_printf(out, "&rsquo;");
134
132
  break;
135
133
  case SINGLEQUOTED:
136
- printf("&lsquo;");;;
137
- print_html_element_list(elt.children, obfuscate);
138
- printf("&rsquo;");;;
134
+ g_string_append_printf(out, "&lsquo;");
135
+ print_html_element_list(out, elt->children, obfuscate);
136
+ g_string_append_printf(out, "&rsquo;");
139
137
  break;
140
138
  case DOUBLEQUOTED:
141
- printf("&ldquo;");;;
142
- print_html_element_list(elt.children, obfuscate);
143
- printf("&rdquo;");;;
139
+ g_string_append_printf(out, "&ldquo;");
140
+ print_html_element_list(out, elt->children, obfuscate);
141
+ g_string_append_printf(out, "&rdquo;");
144
142
  break;
145
143
  case CODE:
146
- printf("<code>");;;
147
- print_html_string(elt.contents.str, obfuscate);
148
- printf("</code>");;;
144
+ g_string_append_printf(out, "<code>");
145
+ print_html_string(out, elt->contents.str, obfuscate);
146
+ g_string_append_printf(out, "</code>");
149
147
  break;
150
148
  case HTML:
151
- printf("%s", elt.contents.str);
149
+ g_string_append_printf(out, "%s", elt->contents.str);
152
150
  break;
153
151
  case LINK:
154
- if (strstr(elt.contents.link.url, "mailto:") == elt.contents.link.url)
152
+ if (strstr(elt->contents.link->url, "mailto:") == elt->contents.link->url)
155
153
  obfuscate = true; /* obfuscate mailto: links */
156
- printf("<a href=\"");
157
- print_html_string(elt.contents.link.url, obfuscate);
158
- printf("\"");
159
- if (strlen(elt.contents.link.title) > 0) {
160
- printf(" title=\"");
161
- print_html_string(elt.contents.link.title, obfuscate);
162
- printf("\"");
154
+ g_string_append_printf(out, "<a href=\"");
155
+ print_html_string(out, elt->contents.link->url, obfuscate);
156
+ g_string_append_printf(out, "\"");
157
+ if (strlen(elt->contents.link->title) > 0) {
158
+ g_string_append_printf(out, " title=\"");
159
+ print_html_string(out, elt->contents.link->title, obfuscate);
160
+ g_string_append_printf(out, "\"");
163
161
  }
164
- printf(">");;;
165
- print_html_element_list(elt.contents.link.label, obfuscate);
166
- printf("</a>");;;
162
+ g_string_append_printf(out, ">");
163
+ print_html_element_list(out, elt->contents.link->label, obfuscate);
164
+ g_string_append_printf(out, "</a>");
167
165
  break;
168
166
  case IMAGE:
169
- printf("<img src=\"");
170
- print_html_string(elt.contents.link.url, obfuscate);
171
- printf("\" alt=\"");
172
- print_html_element_list(elt.contents.link.label, obfuscate);
173
- printf("\"");
174
- if (strlen(elt.contents.link.title) > 0) {
175
- printf(" title=\"");
176
- print_html_string(elt.contents.link.title, obfuscate);
177
- printf("\"");
167
+ g_string_append_printf(out, "<img src=\"");
168
+ print_html_string(out, elt->contents.link->url, obfuscate);
169
+ g_string_append_printf(out, "\" alt=\"");
170
+ print_html_element_list(out, elt->contents.link->label, obfuscate);
171
+ g_string_append_printf(out, "\"");
172
+ if (strlen(elt->contents.link->title) > 0) {
173
+ g_string_append_printf(out, " title=\"");
174
+ print_html_string(out, elt->contents.link->title, obfuscate);
175
+ g_string_append_printf(out, "\"");
178
176
  }
179
- printf(" />");;;
177
+ g_string_append_printf(out, " />");
180
178
  break;
181
179
  case EMPH:
182
- printf("<em>");;;
183
- print_html_element_list(elt.children, obfuscate);
184
- printf("</em>");;;
180
+ g_string_append_printf(out, "<em>");
181
+ print_html_element_list(out, elt->children, obfuscate);
182
+ g_string_append_printf(out, "</em>");
185
183
  break;
186
184
  case STRONG:
187
- printf("<strong>");;;
188
- print_html_element_list(elt.children, obfuscate);
189
- printf("</strong>");;;
185
+ g_string_append_printf(out, "<strong>");
186
+ print_html_element_list(out, elt->children, obfuscate);
187
+ g_string_append_printf(out, "</strong>");
190
188
  break;
191
189
  case LIST:
192
- print_html_element_list(elt.children, obfuscate);
190
+ print_html_element_list(out, elt->children, obfuscate);
193
191
  break;
194
192
  case RAW:
195
- /* \001 is used to indicate boundaries between nested lists when there
196
- * is no blank line. We split the string by \001 and parse
197
- * each chunk separately. */
198
- contents = strtok(elt.contents.str, "\001");
199
- print_html_element(markdown(contents, extensions), obfuscate);
200
- while ((contents = strtok(NULL, "\001")))
201
- print_html_element(markdown(contents, extensions), obfuscate);
193
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
194
+ assert(elt->key != RAW);
202
195
  break;
203
196
  case H1: case H2: case H3: case H4: case H5: case H6:
204
- lev = elt.key - H1 + 1; /* assumes H1 ... H6 are in order */
205
- pad(2);
206
- printf("<h%1d>", lev);
207
- print_html_element_list(elt.children, obfuscate);
208
- printf("</h%1d>", lev);
197
+ lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */
198
+ pad(out, 2);
199
+ g_string_append_printf(out, "<h%1d>", lev);
200
+ print_html_element_list(out, elt->children, obfuscate);
201
+ g_string_append_printf(out, "</h%1d>", lev);
209
202
  padded = 0;
210
203
  break;
211
204
  case PLAIN:
212
- pad(1);
213
- print_html_element_list(elt.children, obfuscate);
205
+ pad(out, 1);
206
+ print_html_element_list(out, elt->children, obfuscate);
214
207
  padded = 0;
215
208
  break;
216
209
  case PARA:
217
- pad(2);
218
- printf("<p>");;;
219
- print_html_element_list(elt.children, obfuscate);
220
- printf("</p>");;;
210
+ pad(out, 2);
211
+ g_string_append_printf(out, "<p>");
212
+ print_html_element_list(out, elt->children, obfuscate);
213
+ g_string_append_printf(out, "</p>");
221
214
  padded = 0;
222
215
  break;
223
216
  case HRULE:
224
- pad(2);
225
- printf("<hr />");;;
217
+ pad(out, 2);
218
+ g_string_append_printf(out, "<hr />");
226
219
  padded = 0;
227
220
  break;
228
221
  case HTMLBLOCK:
229
- pad(2);
230
- printf("%s", elt.contents.str);
222
+ pad(out, 2);
223
+ g_string_append_printf(out, "%s", elt->contents.str);
231
224
  padded = 0;
232
225
  break;
233
226
  case VERBATIM:
234
- pad(2);
235
- printf("%s", "<pre><code>");
236
- print_html_string(elt.contents.str, obfuscate);
237
- printf("%s", "</code></pre>");
227
+ pad(out, 2);
228
+ g_string_append_printf(out, "%s", "<pre><code>");
229
+ print_html_string(out, elt->contents.str, obfuscate);
230
+ g_string_append_printf(out, "%s", "</code></pre>");
238
231
  padded = 0;
239
232
  break;
240
233
  case BULLETLIST:
241
- pad(2);
242
- printf("%s", "<ul>");
234
+ pad(out, 2);
235
+ g_string_append_printf(out, "%s", "<ul>");
243
236
  padded = 0;
244
- print_html_element_list(elt.children, obfuscate);
245
- pad(1);
246
- printf("%s", "</ul>");
237
+ print_html_element_list(out, elt->children, obfuscate);
238
+ pad(out, 1);
239
+ g_string_append_printf(out, "%s", "</ul>");
247
240
  padded = 0;
248
241
  break;
249
242
  case ORDEREDLIST:
250
- pad(2);
251
- printf("%s", "<ol>");
243
+ pad(out, 2);
244
+ g_string_append_printf(out, "%s", "<ol>");
252
245
  padded = 0;
253
- print_html_element_list(elt.children, obfuscate);
254
- pad(1);
255
- printf("</ol>");;;
246
+ print_html_element_list(out, elt->children, obfuscate);
247
+ pad(out, 1);
248
+ g_string_append_printf(out, "</ol>");
256
249
  padded = 0;
257
250
  break;
258
251
  case LISTITEM:
259
- pad(1);
260
- printf("<li>");;;
252
+ pad(out, 1);
253
+ g_string_append_printf(out, "<li>");
261
254
  padded = 2;
262
- print_html_element_list(elt.children, obfuscate);
263
- printf("</li>");;;
255
+ print_html_element_list(out, elt->children, obfuscate);
256
+ g_string_append_printf(out, "</li>");
264
257
  padded = 0;
265
258
  break;
266
259
  case BLOCKQUOTE:
267
- pad(2);
268
- printf("<blockquote>\n");;;
260
+ pad(out, 2);
261
+ g_string_append_printf(out, "<blockquote>\n");
269
262
  padded = 2;
270
- print_html_element_list(elt.children, obfuscate);
271
- pad(1);
272
- printf("</blockquote>");;;
263
+ print_html_element_list(out, elt->children, obfuscate);
264
+ pad(out, 1);
265
+ g_string_append_printf(out, "</blockquote>");
273
266
  padded = 0;
274
267
  break;
275
268
  case REFERENCE:
@@ -278,39 +271,42 @@ static void print_html_element(element elt, bool obfuscate) {
278
271
  case NOTE:
279
272
  /* if contents.str == 0, then print note; else ignore, since this
280
273
  * is a note block that has been incorporated into the notes list */
281
- if (elt.contents.str == 0) {
282
- endnotes = cons(elt, endnotes);
274
+ if (elt->contents.str == 0) {
275
+ add_endnote(elt);
283
276
  ++notenumber;
284
- printf("<a class=\"noteref\" id=\"fnref%d\" href=\"#fn%d\" title=\"Jump to note %d\">[%d]</a>",
277
+ g_string_append_printf(out, "<a class=\"noteref\" id=\"fnref%d\" href=\"#fn%d\" title=\"Jump to note %d\">[%d]</a>",
285
278
  notenumber, notenumber, notenumber, notenumber);
286
279
  }
287
280
  break;
288
281
  default:
289
- fprintf(stderr, "print_html_element encountered unknown element key = %d\n", elt.key);
282
+ fprintf(stderr, "print_html_element encountered unknown element key = %d\n", elt->key);
290
283
  exit(EXIT_FAILURE);
291
284
  }
292
285
  }
293
286
 
294
- static void print_html_endnotes(void) {
287
+ static void print_html_endnotes(GString *out) {
295
288
  int counter = 0;
296
- if (endnotes == NULL) {
289
+ GSList *note;
290
+ element *note_elt;
291
+ if (endnotes == NULL)
297
292
  return;
298
- }
299
- printf("<hr/>\n<ol id=\"notes\">");
300
- endnotes = reverse(endnotes);
301
- while (endnotes != NULL) {
293
+ note = g_slist_reverse(endnotes);
294
+ g_string_append_printf(out, "<hr/>\n<ol id=\"notes\">");
295
+ while (note != NULL) {
296
+ note_elt = note->data;
302
297
  counter++;
303
- pad(1);
304
- printf("<li id=\"fn%d\">\n", counter);
298
+ pad(out, 1);
299
+ g_string_append_printf(out, "<li id=\"fn%d\">\n", counter);
305
300
  padded = 2;
306
- print_html_element_list(endnotes->children, false);
307
- printf(" <a href=\"#fnref%d\" title=\"Jump back to reference\">[back]</a>", counter);
308
- pad(1);
309
- printf("</li>");;
310
- endnotes = endnotes->next;
301
+ print_html_element_list(out, note_elt->children, false);
302
+ g_string_append_printf(out, " <a href=\"#fnref%d\" title=\"Jump back to reference\">[back]</a>", counter);
303
+ pad(out, 1);
304
+ g_string_append_printf(out, "</li>");
305
+ note = note->next;
311
306
  }
312
- pad(1);
313
- printf("</ol>");;;
307
+ pad(out, 1);
308
+ g_string_append_printf(out, "</ol>");
309
+ g_slist_free(endnotes);
314
310
  }
315
311
 
316
312
  /**********************************************************************
@@ -320,205 +316,200 @@ static void print_html_endnotes(void) {
320
316
  ***********************************************************************/
321
317
 
322
318
  /* print_latex_string - print string, escaping for LaTeX */
323
- static void print_latex_string(char *str) {
319
+ static void print_latex_string(GString *out, char *str) {
324
320
  while (*str != '\0') {
325
321
  switch (*str) {
326
322
  case '{': case '}': case '$': case '%':
327
323
  case '&': case '_': case '#':
328
- printf("\\%c", *str);
324
+ g_string_append_printf(out, "\\%c", *str);
329
325
  break;
330
326
  case '^':
331
- printf("\\^{}");;;
327
+ g_string_append_printf(out, "\\^{}");
332
328
  break;
333
329
  case '\\':
334
- printf("\\textbackslash{}");;;
330
+ g_string_append_printf(out, "\\textbackslash{}");
335
331
  break;
336
332
  case '~':
337
- printf("\\ensuremath{\\sim}");;;
333
+ g_string_append_printf(out, "\\ensuremath{\\sim}");
338
334
  break;
339
335
  case '|':
340
- printf("\\textbar{}");;;
336
+ g_string_append_printf(out, "\\textbar{}");
341
337
  break;
342
338
  case '<':
343
- printf("\\textless{}");;;
339
+ g_string_append_printf(out, "\\textless{}");
344
340
  break;
345
341
  case '>':
346
- printf("\\textgreater{}");;;
342
+ g_string_append_printf(out, "\\textgreater{}");
347
343
  break;
348
344
  default:
349
- putchar(*str);
345
+ g_string_append_c(out, *str);
350
346
  }
351
347
  str++;
352
348
  }
353
349
  }
354
350
 
355
351
  /* print_latex_element_list - print a list of elements as LaTeX */
356
- static void print_latex_element_list(element *list) {
352
+ static void print_latex_element_list(GString *out, element *list) {
357
353
  while (list != NULL) {
358
- print_latex_element(*list);
354
+ print_latex_element(out, list);
359
355
  list = list->next;
360
356
  }
361
357
  }
362
358
 
363
359
  /* print_latex_element - print an element as LaTeX */
364
- static void print_latex_element(element elt) {
360
+ static void print_latex_element(GString *out, element *elt) {
365
361
  int lev;
366
362
  int i;
367
- char *contents;
368
- switch (elt.key) {
363
+ switch (elt->key) {
369
364
  case SPACE:
370
- printf("%s", elt.contents.str);
365
+ g_string_append_printf(out, "%s", elt->contents.str);
371
366
  break;
372
367
  case LINEBREAK:
373
- printf("\\\\\n");;;
368
+ g_string_append_printf(out, "\\\\\n");
374
369
  break;
375
370
  case STR:
376
- print_latex_string(elt.contents.str);
371
+ print_latex_string(out, elt->contents.str);
377
372
  break;
378
373
  case ELLIPSIS:
379
- printf("\\ldots{}");;;
374
+ g_string_append_printf(out, "\\ldots{}");
380
375
  break;
381
376
  case EMDASH:
382
- printf("---");;;
377
+ g_string_append_printf(out, "---");
383
378
  break;
384
379
  case ENDASH:
385
- printf("--");;;
380
+ g_string_append_printf(out, "--");
386
381
  break;
387
382
  case APOSTROPHE:
388
- printf("'");;;
383
+ g_string_append_printf(out, "'");
389
384
  break;
390
385
  case SINGLEQUOTED:
391
- printf("`");;;
392
- print_latex_element_list(elt.children);
393
- printf("'");;;
386
+ g_string_append_printf(out, "`");
387
+ print_latex_element_list(out, elt->children);
388
+ g_string_append_printf(out, "'");
394
389
  break;
395
390
  case DOUBLEQUOTED:
396
- printf("``");;;
397
- print_latex_element_list(elt.children);
398
- printf("''");;;
391
+ g_string_append_printf(out, "``");
392
+ print_latex_element_list(out, elt->children);
393
+ g_string_append_printf(out, "''");
399
394
  break;
400
395
  case CODE:
401
- printf("\\texttt{");;;
402
- print_latex_string(elt.contents.str);
403
- printf("}");;;
396
+ g_string_append_printf(out, "\\texttt{");
397
+ print_latex_string(out, elt->contents.str);
398
+ g_string_append_printf(out, "}");
404
399
  break;
405
400
  case HTML:
406
401
  /* don't print HTML */
407
402
  break;
408
403
  case LINK:
409
- printf("\\href{%s}{", elt.contents.link.url);
410
- print_latex_element_list(elt.contents.link.label);
411
- printf("}");;;
404
+ g_string_append_printf(out, "\\href{%s}{", elt->contents.link->url);
405
+ print_latex_element_list(out, elt->contents.link->label);
406
+ g_string_append_printf(out, "}");
412
407
  break;
413
408
  case IMAGE:
414
- printf("\\includegraphics{%s}", elt.contents.link.url);
409
+ g_string_append_printf(out, "\\includegraphics{%s}", elt->contents.link->url);
415
410
  break;
416
411
  case EMPH:
417
- printf("\\emph{");;;
418
- print_latex_element_list(elt.children);
419
- printf("}");;;
412
+ g_string_append_printf(out, "\\emph{");
413
+ print_latex_element_list(out, elt->children);
414
+ g_string_append_printf(out, "}");
420
415
  break;
421
416
  case STRONG:
422
- printf("\\textbf{");;;
423
- print_latex_element_list(elt.children);
424
- printf("}");;;
417
+ g_string_append_printf(out, "\\textbf{");
418
+ print_latex_element_list(out, elt->children);
419
+ g_string_append_printf(out, "}");
425
420
  break;
426
421
  case LIST:
427
- print_latex_element_list(elt.children);
422
+ print_latex_element_list(out, elt->children);
428
423
  break;
429
424
  case RAW:
430
- /* \001 is used to indicate boundaries between nested lists when there
431
- * is no blank line. We split the string by \001 and parse
432
- * each chunk separately. */
433
- contents = strtok(elt.contents.str, "\001");
434
- print_latex_element(markdown(contents, extensions));
435
- while ((contents = strtok(NULL, "\001")))
436
- print_latex_element(markdown(contents, extensions));
425
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
426
+ assert(elt->key != RAW);
437
427
  break;
438
428
  case H1: case H2: case H3:
439
- pad(2);
440
- lev = elt.key - H1 + 1; /* assumes H1 ... H6 are in order */
441
- printf("\\");;;
442
- for (i = elt.key; i > H1; i--)
443
- printf("sub");;;
444
- printf("section{");;;
445
- print_latex_element_list(elt.children);
446
- printf("}");;;
429
+ pad(out, 2);
430
+ lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */
431
+ g_string_append_printf(out, "\\");
432
+ for (i = elt->key; i > H1; i--)
433
+ g_string_append_printf(out, "sub");
434
+ g_string_append_printf(out, "section{");
435
+ print_latex_element_list(out, elt->children);
436
+ g_string_append_printf(out, "}");
447
437
  padded = 0;
448
438
  break;
449
439
  case H4: case H5: case H6:
450
- pad(2);
451
- printf("\\noindent\\textbf{");;;
452
- print_latex_element_list(elt.children);
453
- printf("}");;;
440
+ pad(out, 2);
441
+ g_string_append_printf(out, "\\noindent\\textbf{");
442
+ print_latex_element_list(out, elt->children);
443
+ g_string_append_printf(out, "}");
454
444
  padded = 0;
455
445
  break;
456
446
  case PLAIN:
457
- pad(1);
458
- print_latex_element_list(elt.children);
447
+ pad(out, 1);
448
+ print_latex_element_list(out, elt->children);
459
449
  padded = 0;
460
450
  break;
461
451
  case PARA:
462
- pad(2);
463
- print_latex_element_list(elt.children);
452
+ pad(out, 2);
453
+ print_latex_element_list(out, elt->children);
464
454
  padded = 0;
465
455
  break;
466
456
  case HRULE:
467
- pad(2);
468
- printf("\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n");;;
457
+ pad(out, 2);
458
+ g_string_append_printf(out, "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n");
469
459
  padded = 0;
470
460
  break;
471
461
  case HTMLBLOCK:
472
462
  /* don't print HTML block */
473
463
  break;
474
464
  case VERBATIM:
475
- pad(1);
476
- printf("\\begin{verbatim}\n");;;
477
- print_latex_string(elt.contents.str);
478
- printf("\n\\end{verbatim}");;;
465
+ pad(out, 1);
466
+ g_string_append_printf(out, "\\begin{verbatim}\n");
467
+ print_latex_string(out, elt->contents.str);
468
+ g_string_append_printf(out, "\n\\end{verbatim}");
479
469
  padded = 0;
480
470
  break;
481
471
  case BULLETLIST:
482
- pad(1);
483
- printf("\\begin{itemize}");;;
472
+ pad(out, 1);
473
+ g_string_append_printf(out, "\\begin{itemize}");
484
474
  padded = 0;
485
- print_latex_element_list(elt.children);
486
- pad(1);
487
- printf("\\end{itemize}");;;
475
+ print_latex_element_list(out, elt->children);
476
+ pad(out, 1);
477
+ g_string_append_printf(out, "\\end{itemize}");
488
478
  padded = 0;
489
479
  break;
490
480
  case ORDEREDLIST:
491
- pad(1);
492
- printf("\\begin{enumerate}");;;
481
+ pad(out, 1);
482
+ g_string_append_printf(out, "\\begin{enumerate}");
493
483
  padded = 0;
494
- print_latex_element_list(elt.children);
495
- pad(1);
496
- printf("\\end{enumerate}");;;
484
+ print_latex_element_list(out, elt->children);
485
+ pad(out, 1);
486
+ g_string_append_printf(out, "\\end{enumerate}");
497
487
  padded = 0;
498
488
  break;
499
489
  case LISTITEM:
500
- pad(1);
501
- printf("\\item ");;;
490
+ pad(out, 1);
491
+ g_string_append_printf(out, "\\item ");
502
492
  padded = 2;
503
- print_latex_element_list(elt.children);
504
- printf("\n");;;
493
+ print_latex_element_list(out, elt->children);
494
+ g_string_append_printf(out, "\n");
505
495
  break;
506
496
  case BLOCKQUOTE:
507
- pad(1);
508
- printf("\\begin{quote}");;;
497
+ pad(out, 1);
498
+ g_string_append_printf(out, "\\begin{quote}");
509
499
  padded = 0;
510
- print_latex_element(markdown(elt.contents.str, extensions));
511
- printf("\\end{quote}");;;
500
+ print_latex_element_list(out, elt->children);
501
+ pad(out, 1);
502
+ g_string_append_printf(out, "\\end{quote}");
512
503
  padded = 0;
513
504
  break;
514
505
  case NOTE:
515
506
  /* if contents.str == 0, then print note; else ignore, since this
516
507
  * is a note block that has been incorporated into the notes list */
517
- if (elt.contents.str == 0) {
518
- printf("\\footnote{");;;
508
+ if (elt->contents.str == 0) {
509
+ g_string_append_printf(out, "\\footnote{");
519
510
  padded = 2;
520
- print_latex_element_list(elt.children);
521
- printf("}");;;
511
+ print_latex_element_list(out, elt->children);
512
+ g_string_append_printf(out, "}");
522
513
  padded = 0;
523
514
  }
524
515
  break;
@@ -526,7 +517,7 @@ static void print_latex_element(element elt) {
526
517
  /* Nonprinting */
527
518
  break;
528
519
  default:
529
- fprintf(stderr, "print_latex_element encountered unknown element key = %d\n", elt.key);
520
+ fprintf(stderr, "print_latex_element encountered unknown element key = %d\n", elt->key);
530
521
  exit(EXIT_FAILURE);
531
522
  }
532
523
  }
@@ -540,195 +531,189 @@ static void print_latex_element(element elt) {
540
531
  static bool in_list_item = false; /* True if we're parsing contents of a list item. */
541
532
 
542
533
  /* print_groff_string - print string, escaping for groff */
543
- static void print_groff_string(char *str) {
534
+ static void print_groff_string(GString *out, char *str) {
544
535
  while (*str != '\0') {
545
536
  switch (*str) {
546
537
  case '\\':
547
- printf("\\e");;;
538
+ g_string_append_printf(out, "\\e");
548
539
  break;
549
540
  default:
550
- putchar(*str);
541
+ g_string_append_c(out, *str);
551
542
  }
552
543
  str++;
553
544
  }
554
545
  }
555
546
 
556
547
  /* print_groff_mm_element_list - print a list of elements as groff ms */
557
- static void print_groff_mm_element_list(element *list) {
548
+ static void print_groff_mm_element_list(GString *out, element *list) {
558
549
  int count = 1;
559
550
  while (list != NULL) {
560
- print_groff_mm_element(*list, count);
551
+ print_groff_mm_element(out, list, count);
561
552
  list = list->next;
562
553
  count++;
563
554
  }
564
555
  }
565
556
 
566
557
  /* print_groff_mm_element - print an element as groff ms */
567
- static void print_groff_mm_element(element elt, int count) {
558
+ static void print_groff_mm_element(GString *out, element *elt, int count) {
568
559
  int lev;
569
- char *contents;
570
- switch (elt.key) {
560
+ switch (elt->key) {
571
561
  case SPACE:
572
- printf("%s", elt.contents.str);
562
+ g_string_append_printf(out, "%s", elt->contents.str);
573
563
  padded = 0;
574
564
  break;
575
565
  case LINEBREAK:
576
- pad(1);
577
- printf(".br");;;
566
+ pad(out, 1);
567
+ g_string_append_printf(out, ".br");
578
568
  padded = 0;
579
569
  break;
580
570
  case STR:
581
- print_groff_string(elt.contents.str);
571
+ print_groff_string(out, elt->contents.str);
582
572
  padded = 0;
583
573
  break;
584
574
  case ELLIPSIS:
585
- printf("...");;;
575
+ g_string_append_printf(out, "...");
586
576
  break;
587
577
  case EMDASH:
588
- printf("\\[em]");;;
578
+ g_string_append_printf(out, "\\[em]");
589
579
  break;
590
580
  case ENDASH:
591
- printf("\\[en]");;;
581
+ g_string_append_printf(out, "\\[en]");
592
582
  break;
593
583
  case APOSTROPHE:
594
- printf("'");;;
584
+ g_string_append_printf(out, "'");
595
585
  break;
596
586
  case SINGLEQUOTED:
597
- printf("`");;;
598
- print_groff_mm_element_list(elt.children);
599
- printf("'");;;
587
+ g_string_append_printf(out, "`");
588
+ print_groff_mm_element_list(out, elt->children);
589
+ g_string_append_printf(out, "'");
600
590
  break;
601
591
  case DOUBLEQUOTED:
602
- printf("\\[lq]");;;
603
- print_groff_mm_element_list(elt.children);
604
- printf("\\[rq]");;;
592
+ g_string_append_printf(out, "\\[lq]");
593
+ print_groff_mm_element_list(out, elt->children);
594
+ g_string_append_printf(out, "\\[rq]");
605
595
  break;
606
596
  case CODE:
607
- printf("\\fC");;;
608
- print_groff_string(elt.contents.str);
609
- printf("\\fR");;;
597
+ g_string_append_printf(out, "\\fC");
598
+ print_groff_string(out, elt->contents.str);
599
+ g_string_append_printf(out, "\\fR");
610
600
  padded = 0;
611
601
  break;
612
602
  case HTML:
613
603
  /* don't print HTML */
614
604
  break;
615
605
  case LINK:
616
- print_groff_mm_element_list(elt.contents.link.label);
617
- printf(" (%s)", elt.contents.link.url);
606
+ print_groff_mm_element_list(out, elt->contents.link->label);
607
+ g_string_append_printf(out, " (%s)", elt->contents.link->url);
618
608
  padded = 0;
619
609
  break;
620
610
  case IMAGE:
621
- printf("[IMAGE: ");;;
622
- print_groff_mm_element_list(elt.contents.link.label);
623
- printf("]");;;
611
+ g_string_append_printf(out, "[IMAGE: ");
612
+ print_groff_mm_element_list(out, elt->contents.link->label);
613
+ g_string_append_printf(out, "]");
624
614
  padded = 0;
625
615
  /* not supported */
626
616
  break;
627
617
  case EMPH:
628
- printf("\\fI");;;
629
- print_groff_mm_element_list(elt.children);
630
- printf("\\fR");;;
618
+ g_string_append_printf(out, "\\fI");
619
+ print_groff_mm_element_list(out, elt->children);
620
+ g_string_append_printf(out, "\\fR");
631
621
  padded = 0;
632
622
  break;
633
623
  case STRONG:
634
- printf("\\fB");;;
635
- print_groff_mm_element_list(elt.children);
636
- printf("\\fR");;;
624
+ g_string_append_printf(out, "\\fB");
625
+ print_groff_mm_element_list(out, elt->children);
626
+ g_string_append_printf(out, "\\fR");
637
627
  padded = 0;
638
628
  break;
639
629
  case LIST:
640
- print_groff_mm_element_list(elt.children);
630
+ print_groff_mm_element_list(out, elt->children);
641
631
  padded = 0;
642
632
  break;
643
633
  case RAW:
644
- /* \001 is used to indicate boundaries between nested lists when there
645
- * is no blank line. We split the string by \001 and parse
646
- * each chunk separately. */
647
- contents = strtok(elt.contents.str, "\001");
648
- print_groff_mm_element(markdown(contents, extensions), count);
649
- while ((contents = strtok(NULL, "\001")))
650
- print_groff_mm_element(markdown(contents, extensions), count);
634
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
635
+ assert(elt->key != RAW);
651
636
  break;
652
637
  case H1: case H2: case H3: case H4: case H5: case H6:
653
- lev = elt.key - H1 + 1;
654
- pad(1);
655
- printf(".H %d \"", lev);
656
- print_groff_mm_element_list(elt.children);
657
- printf("\"");
638
+ lev = elt->key - H1 + 1;
639
+ pad(out, 1);
640
+ g_string_append_printf(out, ".H %d \"", lev);
641
+ print_groff_mm_element_list(out, elt->children);
642
+ g_string_append_printf(out, "\"");
658
643
  padded = 0;
659
644
  break;
660
645
  case PLAIN:
661
- pad(1);
662
- print_groff_mm_element_list(elt.children);
646
+ pad(out, 1);
647
+ print_groff_mm_element_list(out, elt->children);
663
648
  padded = 0;
664
649
  break;
665
650
  case PARA:
666
- pad(1);
651
+ pad(out, 1);
667
652
  if (!in_list_item || count != 1)
668
- printf(".P\n");;;
669
- print_groff_mm_element_list(elt.children);
653
+ g_string_append_printf(out, ".P\n");
654
+ print_groff_mm_element_list(out, elt->children);
670
655
  padded = 0;
671
656
  break;
672
657
  case HRULE:
673
- pad(1);
674
- printf("\\l'\\n(.lu*8u/10u'");;;
658
+ pad(out, 1);
659
+ g_string_append_printf(out, "\\l'\\n(.lu*8u/10u'");
675
660
  padded = 0;
676
661
  break;
677
662
  case HTMLBLOCK:
678
663
  /* don't print HTML block */
679
664
  break;
680
665
  case VERBATIM:
681
- pad(1);
682
- printf(".VERBON 2\n");;;
683
- print_groff_string(elt.contents.str);
684
- printf(".VERBOFF");;;
666
+ pad(out, 1);
667
+ g_string_append_printf(out, ".VERBON 2\n");
668
+ print_groff_string(out, elt->contents.str);
669
+ g_string_append_printf(out, ".VERBOFF");
685
670
  padded = 0;
686
671
  break;
687
672
  case BULLETLIST:
688
- pad(1);
689
- printf(".BL");;;
673
+ pad(out, 1);
674
+ g_string_append_printf(out, ".BL");
690
675
  padded = 0;
691
- print_groff_mm_element_list(elt.children);
692
- pad(1);
693
- printf(".LE 1");;;
676
+ print_groff_mm_element_list(out, elt->children);
677
+ pad(out, 1);
678
+ g_string_append_printf(out, ".LE 1");
694
679
  padded = 0;
695
680
  break;
696
681
  case ORDEREDLIST:
697
- pad(1);
698
- printf(".AL");;;
682
+ pad(out, 1);
683
+ g_string_append_printf(out, ".AL");
699
684
  padded = 0;
700
- print_groff_mm_element_list(elt.children);
701
- pad(1);
702
- printf(".LE 1");;;
685
+ print_groff_mm_element_list(out, elt->children);
686
+ pad(out, 1);
687
+ g_string_append_printf(out, ".LE 1");
703
688
  padded = 0;
704
689
  break;
705
690
  case LISTITEM:
706
- pad(1);
707
- printf(".LI\n");;;
691
+ pad(out, 1);
692
+ g_string_append_printf(out, ".LI\n");
708
693
  in_list_item = true;
709
694
  padded = 2;
710
- print_groff_mm_element_list(elt.children);
695
+ print_groff_mm_element_list(out, elt->children);
711
696
  in_list_item = false;
712
697
  break;
713
698
  case BLOCKQUOTE:
714
- pad(1);
715
- printf(".DS I\n");;;
699
+ pad(out, 1);
700
+ g_string_append_printf(out, ".DS I\n");
716
701
  padded = 2;
717
- print_groff_mm_element(markdown(elt.contents.str, extensions), 1);
718
- pad(1);
719
- printf(".DE");;;
702
+ print_groff_mm_element_list(out, elt->children);
703
+ pad(out, 1);
704
+ g_string_append_printf(out, ".DE");
720
705
  padded = 0;
721
706
  break;
722
707
  case NOTE:
723
708
  /* if contents.str == 0, then print note; else ignore, since this
724
709
  * is a note block that has been incorporated into the notes list */
725
- if (elt.contents.str == 0) {
726
- printf("\\*F\n");;;
727
- printf(".FS\n");;;
710
+ if (elt->contents.str == 0) {
711
+ g_string_append_printf(out, "\\*F\n");
712
+ g_string_append_printf(out, ".FS\n");
728
713
  padded = 2;
729
- print_groff_mm_element_list(elt.children);
730
- pad(1);
731
- printf(".FE\n");;;
714
+ print_groff_mm_element_list(out, elt->children);
715
+ pad(out, 1);
716
+ g_string_append_printf(out, ".FE\n");
732
717
  padded = 1;
733
718
  }
734
719
  break;
@@ -736,7 +721,7 @@ static void print_groff_mm_element(element elt, int count) {
736
721
  /* Nonprinting */
737
722
  break;
738
723
  default:
739
- fprintf(stderr, "print_groff_mm_element encountered unknown element key = %d\n", elt.key);
724
+ fprintf(stderr, "print_groff_mm_element encountered unknown element key = %d\n", elt->key);
740
725
  exit(EXIT_FAILURE);
741
726
  }
742
727
  }
@@ -747,20 +732,21 @@ static void print_groff_mm_element(element elt, int count) {
747
732
 
748
733
  ***********************************************************************/
749
734
 
750
- void print_element(element elt, int format) {
735
+ void print_element_list(GString *out, element *elt, int format, int exts) {
736
+ extensions = exts;
751
737
  switch (format) {
752
738
  case HTML_FORMAT:
753
- print_html_element(elt, false);
739
+ print_html_element_list(out, elt, false);
754
740
  if (endnotes != NULL) {
755
- pad(2);
756
- print_html_endnotes();
741
+ pad(out, 2);
742
+ print_html_endnotes(out);
757
743
  }
758
744
  break;
759
745
  case LATEX_FORMAT:
760
- print_latex_element(elt);
746
+ print_latex_element_list(out, elt);
761
747
  break;
762
748
  case GROFF_MM_FORMAT:
763
- print_groff_mm_element(elt, 1);
749
+ print_groff_mm_element_list(out, elt);
764
750
  break;
765
751
  default:
766
752
  fprintf(stderr, "print_element - unknown format = %d\n", format);