rmultimarkdown 6.4.0.3 → 6.7.0.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.
- checksums.yaml +5 -5
- data/Rakefile +7 -13
- data/ext/Makefile +67 -55
- data/ext/extconf.rb +8 -6
- data/ext/mmd/aho-corasick.c +8 -8
- data/ext/mmd/aho-corasick.h +3 -3
- data/ext/mmd/argtable3.c +6537 -0
- data/ext/mmd/argtable3.h +273 -0
- data/ext/mmd/beamer.c +12 -1
- data/ext/mmd/char.c +120 -27
- data/ext/mmd/char.h +23 -23
- data/ext/mmd/critic_markup.c +7 -6
- data/ext/mmd/d_string.c +88 -32
- data/ext/mmd/{include/d_string.h → d_string.h} +50 -38
- data/ext/mmd/epub.c +36 -12
- data/ext/mmd/epub.h +2 -2
- data/ext/mmd/file.c +50 -40
- data/ext/mmd/file.h +2 -2
- data/ext/mmd/html.c +164 -99
- data/ext/mmd/html.h +3 -2
- data/ext/mmd/i18n.h +15 -11
- data/ext/mmd/itmz-lexer.c +16978 -0
- data/ext/mmd/itmz-lexer.h +132 -0
- data/ext/mmd/itmz-parser.c +1189 -0
- data/ext/mmd/itmz-parser.h +11 -0
- data/ext/mmd/itmz-reader.c +388 -0
- data/ext/mmd/itmz-reader.h +111 -0
- data/ext/mmd/itmz.c +567 -0
- data/ext/mmd/itmz.h +117 -0
- data/ext/mmd/latex.c +93 -41
- data/ext/mmd/lexer.c +3506 -2774
- data/ext/mmd/{include/libMultiMarkdown.h → libMultiMarkdown.h} +49 -2
- data/ext/mmd/main.c +612 -0
- data/ext/mmd/memoir.c +4 -1
- data/ext/mmd/miniz.c +6905 -6680
- data/ext/mmd/miniz.h +456 -476
- data/ext/mmd/mmd.c +399 -94
- data/ext/mmd/mmd.h +25 -25
- data/ext/mmd/object_pool.h +3 -3
- data/ext/mmd/opendocument-content.c +137 -69
- data/ext/mmd/opendocument-content.h +2 -2
- data/ext/mmd/opendocument.c +35 -14
- data/ext/mmd/opendocument.h +2 -2
- data/ext/mmd/opml-lexer.c +259 -637
- data/ext/mmd/opml-lexer.h +1 -17
- data/ext/mmd/opml-parser.c +194 -188
- data/ext/mmd/opml-reader.c +72 -142
- data/ext/mmd/opml-reader.h +1 -1
- data/ext/mmd/opml.c +13 -13
- data/ext/mmd/opml.h +1 -1
- data/ext/mmd/parser.c +1623 -1244
- data/ext/mmd/rng.c +8 -3
- data/ext/mmd/scanners.c +66625 -103198
- data/ext/mmd/scanners.h +1 -0
- data/ext/mmd/stack.c +62 -20
- data/ext/mmd/stack.h +10 -21
- data/ext/mmd/textbundle.c +23 -7
- data/ext/mmd/textbundle.h +2 -2
- data/ext/mmd/token.c +42 -16
- data/ext/mmd/{include/token.h → token.h} +22 -8
- data/ext/mmd/token_pairs.c +0 -16
- data/ext/mmd/transclude.c +6 -2
- data/ext/mmd/uthash.h +745 -745
- data/ext/mmd/version.h +8 -8
- data/ext/mmd/writer.c +225 -63
- data/ext/mmd/writer.h +50 -36
- data/ext/mmd/xml.c +855 -0
- data/ext/mmd/xml.h +134 -0
- data/ext/mmd/zip.c +71 -4
- data/ext/mmd/zip.h +7 -1
- data/ext/ruby_multi_markdown.c +9 -18
- data/lib/multi_markdown/version.rb +1 -1
- data/lib/multi_markdown.bundle +0 -0
- data/rmultimarkdown.gemspec +0 -2
- metadata +22 -28
- data/ext/mmd/char_lookup.c +0 -212
data/ext/mmd/scanners.h
CHANGED
|
@@ -76,6 +76,7 @@ size_t scan_atx(const char * c);
|
|
|
76
76
|
size_t scan_definition(const char * c);
|
|
77
77
|
size_t scan_destination(const char * c);
|
|
78
78
|
size_t scan_email(const char * c);
|
|
79
|
+
size_t scan_empty_meta_line(const char * c);
|
|
79
80
|
size_t scan_fence_start(const char * c);
|
|
80
81
|
size_t scan_fence_end(const char * c);
|
|
81
82
|
size_t scan_html(const char * c);
|
data/ext/mmd/stack.c
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
libCoreUtilities -- Reusable component libraries
|
|
4
4
|
|
|
5
5
|
@file stack.c
|
|
6
6
|
|
|
@@ -14,23 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
/*
|
|
16
16
|
|
|
17
|
-
Copyright © 2016
|
|
17
|
+
Copyright © 2016-2020 Fletcher T. Penney.
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
MIT License
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
https://github.com/fletcher/MultiMarkdown-4/
|
|
25
|
-
|
|
26
|
-
MMD 4 is released under both the MIT License and GPL.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
CuTest is released under the zlib/libpng license. See CuTest.c for the text
|
|
30
|
-
of the license.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## The MIT License ##
|
|
22
|
+
Copyright (c) 2016-2020 Fletcher T. Penney
|
|
34
23
|
|
|
35
24
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
36
25
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -39,24 +28,28 @@
|
|
|
39
28
|
copies of the Software, and to permit persons to whom the Software is
|
|
40
29
|
furnished to do so, subject to the following conditions:
|
|
41
30
|
|
|
42
|
-
The above copyright notice and this permission notice shall be included in
|
|
43
|
-
|
|
31
|
+
The above copyright notice and this permission notice shall be included in all
|
|
32
|
+
copies or substantial portions of the Software.
|
|
44
33
|
|
|
45
34
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
46
35
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
47
36
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
48
37
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
49
38
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
50
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
51
|
-
|
|
39
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
40
|
+
SOFTWARE.
|
|
52
41
|
|
|
53
|
-
|
|
42
|
+
*/
|
|
54
43
|
|
|
55
44
|
#include <stdlib.h>
|
|
56
45
|
#include <string.h>
|
|
57
46
|
|
|
58
47
|
#include "stack.h"
|
|
59
48
|
|
|
49
|
+
#ifdef TEST
|
|
50
|
+
#include "CuTest.h"
|
|
51
|
+
#endif
|
|
52
|
+
|
|
60
53
|
#define kStackStartingSize 64
|
|
61
54
|
|
|
62
55
|
|
|
@@ -94,6 +87,26 @@ void stack_free(stack * s) {
|
|
|
94
87
|
}
|
|
95
88
|
|
|
96
89
|
|
|
90
|
+
#ifdef TEST
|
|
91
|
+
void Test_stack_new(CuTest * tc) {
|
|
92
|
+
stack * s = stack_new(0);
|
|
93
|
+
CuAssertIntEquals(tc, kStackStartingSize, s->capacity);
|
|
94
|
+
CuAssertIntEquals(tc, 0, s->size);
|
|
95
|
+
stack_free(s);
|
|
96
|
+
|
|
97
|
+
s = stack_new(-1);
|
|
98
|
+
CuAssertIntEquals(tc, kStackStartingSize, s->capacity);
|
|
99
|
+
CuAssertIntEquals(tc, 0, s->size);
|
|
100
|
+
stack_free(s);
|
|
101
|
+
|
|
102
|
+
s = stack_new(10);
|
|
103
|
+
CuAssertIntEquals(tc, 10, s->capacity);
|
|
104
|
+
CuAssertIntEquals(tc, 0, s->size);
|
|
105
|
+
stack_free(s);
|
|
106
|
+
}
|
|
107
|
+
#endif
|
|
108
|
+
|
|
109
|
+
|
|
97
110
|
/// Add a new pointer to the stack
|
|
98
111
|
void stack_push(stack * s, void * element) {
|
|
99
112
|
if (s->size == s->capacity) {
|
|
@@ -137,6 +150,35 @@ void * stack_peek_index(stack * s, size_t index) {
|
|
|
137
150
|
}
|
|
138
151
|
|
|
139
152
|
|
|
153
|
+
#ifdef TEST
|
|
154
|
+
void Test_stack_push_pop(CuTest * tc) {
|
|
155
|
+
stack * s = stack_new(1);
|
|
156
|
+
|
|
157
|
+
char * s1 = "foo";
|
|
158
|
+
char * s2 = "bar";
|
|
159
|
+
char * s3 = "bat";
|
|
160
|
+
|
|
161
|
+
stack_push(s, s1);
|
|
162
|
+
stack_push(s, s2);
|
|
163
|
+
stack_push(s, s3);
|
|
164
|
+
|
|
165
|
+
CuAssertIntEquals(tc, 3, s->size);
|
|
166
|
+
CuAssertIntEquals(tc, 4, s->capacity);
|
|
167
|
+
|
|
168
|
+
CuAssertStrEquals(tc, "bat", stack_peek(s));
|
|
169
|
+
CuAssertStrEquals(tc, "foo", stack_peek_index(s, 0));
|
|
170
|
+
|
|
171
|
+
CuAssertStrEquals(tc, "bat", stack_pop(s));
|
|
172
|
+
CuAssertStrEquals(tc, "bar", stack_pop(s));
|
|
173
|
+
CuAssertStrEquals(tc, "foo", stack_pop(s));
|
|
174
|
+
|
|
175
|
+
CuAssertIntEquals(tc, 0, s->size);
|
|
176
|
+
|
|
177
|
+
stack_free(s);
|
|
178
|
+
}
|
|
179
|
+
#endif
|
|
180
|
+
|
|
181
|
+
|
|
140
182
|
/// Sort array using specified compare_function
|
|
141
183
|
void stack_sort(stack * s, void * compare_function) {
|
|
142
184
|
qsort(s->element, s->size, sizeof(void *), compare_function);
|
data/ext/mmd/stack.h
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
libCoreUtilities -- Reusable component libraries
|
|
4
4
|
|
|
5
5
|
@file stack.h
|
|
6
6
|
|
|
@@ -14,23 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
/*
|
|
16
16
|
|
|
17
|
-
Copyright © 2016
|
|
17
|
+
Copyright © 2016-2020 Fletcher T. Penney.
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
MIT License
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
https://github.com/fletcher/MultiMarkdown-4/
|
|
25
|
-
|
|
26
|
-
MMD 4 is released under both the MIT License and GPL.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
CuTest is released under the zlib/libpng license. See CuTest.c for the text
|
|
30
|
-
of the license.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## The MIT License ##
|
|
22
|
+
Copyright (c) 2016-2020 Fletcher T. Penney
|
|
34
23
|
|
|
35
24
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
36
25
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -39,18 +28,18 @@
|
|
|
39
28
|
copies of the Software, and to permit persons to whom the Software is
|
|
40
29
|
furnished to do so, subject to the following conditions:
|
|
41
30
|
|
|
42
|
-
The above copyright notice and this permission notice shall be included in
|
|
43
|
-
|
|
31
|
+
The above copyright notice and this permission notice shall be included in all
|
|
32
|
+
copies or substantial portions of the Software.
|
|
44
33
|
|
|
45
34
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
46
35
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
47
36
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
48
37
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
49
38
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
50
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
51
|
-
|
|
39
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
40
|
+
SOFTWARE.
|
|
52
41
|
|
|
53
|
-
|
|
42
|
+
*/
|
|
54
43
|
|
|
55
44
|
|
|
56
45
|
#ifndef STACK_SMART_STRING_H
|
|
@@ -62,7 +51,7 @@
|
|
|
62
51
|
struct stack {
|
|
63
52
|
size_t size; //!< Number of objects currently in stack
|
|
64
53
|
size_t capacity; //!< Total current capacity for stack
|
|
65
|
-
void
|
|
54
|
+
void ** element; //!< Array of pointers to objects in stack
|
|
66
55
|
};
|
|
67
56
|
|
|
68
57
|
typedef struct stack stack;
|
data/ext/mmd/textbundle.c
CHANGED
|
@@ -105,13 +105,30 @@
|
|
|
105
105
|
#include <stdlib.h>
|
|
106
106
|
#include <sys/stat.h>
|
|
107
107
|
|
|
108
|
+
#ifdef __APPLE__
|
|
109
|
+
#include "TargetConditionals.h"
|
|
110
|
+
#if TARGET_IPHONE_SIMULATOR
|
|
111
|
+
// iOS Simulator
|
|
112
|
+
#undef USE_CURL
|
|
113
|
+
#elif TARGET_OS_IPHONE
|
|
114
|
+
// iOS device
|
|
115
|
+
#undef USE_CURL
|
|
116
|
+
#elif TARGET_OS_MAC
|
|
117
|
+
// Other kinds of Mac OS
|
|
118
|
+
#else
|
|
119
|
+
# error "Unknown Apple platform"
|
|
120
|
+
#endif
|
|
121
|
+
#endif
|
|
122
|
+
|
|
108
123
|
#ifdef USE_CURL
|
|
109
124
|
#include <curl/curl.h>
|
|
110
125
|
#endif
|
|
111
126
|
|
|
112
127
|
#include "file.h"
|
|
113
128
|
#include "miniz.h"
|
|
129
|
+
#include "stack.h"
|
|
114
130
|
#include "textbundle.h"
|
|
131
|
+
#include "token.h"
|
|
115
132
|
#include "writer.h"
|
|
116
133
|
#include "zip.h"
|
|
117
134
|
|
|
@@ -222,7 +239,7 @@ static void add_assets(mz_zip_archive * pZip, mmd_engine * e, const char * direc
|
|
|
222
239
|
if (res != CURLE_OK) {
|
|
223
240
|
// Attempt to add asset from local file
|
|
224
241
|
if (!add_asset_from_file(pZip, a, destination, directory)) {
|
|
225
|
-
fprintf(stderr, "Unable to store '%s' in
|
|
242
|
+
fprintf(stderr, "Unable to store '%s' in TextBundle\n", a->url);
|
|
226
243
|
}
|
|
227
244
|
} else {
|
|
228
245
|
// Store downloaded file in zip
|
|
@@ -252,7 +269,7 @@ static void add_assets(mz_zip_archive * pZip, mmd_engine * e, const char * direc
|
|
|
252
269
|
|
|
253
270
|
// Attempt to add asset from local file
|
|
254
271
|
if (!add_asset_from_file(pZip, a, destination, directory)) {
|
|
255
|
-
fprintf(stderr, "Unable to store '%s' in
|
|
272
|
+
fprintf(stderr, "Unable to store '%s' in TextBundle\n", a->url);
|
|
256
273
|
}
|
|
257
274
|
}
|
|
258
275
|
}
|
|
@@ -273,7 +290,7 @@ void traverse_for_images(token * t, DString * text, mmd_engine * e, long * offse
|
|
|
273
290
|
|
|
274
291
|
memcpy(url, &text->str[t->start + *offset + 1], t->len - 2);
|
|
275
292
|
url[t->len - 2] = '\0';
|
|
276
|
-
clean = clean_string(url, false);
|
|
293
|
+
clean = clean_string(url, false, true);
|
|
277
294
|
|
|
278
295
|
HASH_FIND_STR(e->asset_hash, clean, a);
|
|
279
296
|
|
|
@@ -367,7 +384,7 @@ void sub_asset_paths(DString * text, mmd_engine * e) {
|
|
|
367
384
|
}
|
|
368
385
|
|
|
369
386
|
|
|
370
|
-
DString * textbundle_create(
|
|
387
|
+
DString * textbundle_create(DString * body, mmd_engine * e, const char * directory) {
|
|
371
388
|
DString * result = d_string_new("");
|
|
372
389
|
scratch_pad * scratch = scratch_pad_new(e, FORMAT_TEXTBUNDLE_COMPRESSED);
|
|
373
390
|
|
|
@@ -409,8 +426,7 @@ DString * textbundle_create(const char * body, mmd_engine * e, const char * dire
|
|
|
409
426
|
}
|
|
410
427
|
|
|
411
428
|
// Add html version document
|
|
412
|
-
|
|
413
|
-
status = mz_zip_writer_add_mem(&zip, "text.html", body, len, MZ_BEST_COMPRESSION);
|
|
429
|
+
status = mz_zip_writer_add_mem(&zip, "text.html", body->str, body->currentStringLength, MZ_BEST_COMPRESSION);
|
|
414
430
|
|
|
415
431
|
if (!status) {
|
|
416
432
|
fprintf(stderr, "Error adding content to zip.\n");
|
|
@@ -436,7 +452,7 @@ DString * textbundle_create(const char * body, mmd_engine * e, const char * dire
|
|
|
436
452
|
|
|
437
453
|
|
|
438
454
|
// Use the miniz library to create a zip archive for the TEXTBUNDLE_COMPRESSED document
|
|
439
|
-
void textbundle_write_wrapper(const char * filepath,
|
|
455
|
+
void textbundle_write_wrapper(const char * filepath, DString * body, mmd_engine * e, const char * directory) {
|
|
440
456
|
FILE * output_stream;
|
|
441
457
|
|
|
442
458
|
DString * result = textbundle_create(body, e, directory);
|
data/ext/mmd/textbundle.h
CHANGED
|
@@ -108,8 +108,8 @@
|
|
|
108
108
|
#include "d_string.h"
|
|
109
109
|
#include "mmd.h"
|
|
110
110
|
|
|
111
|
-
void textbundle_write_wrapper(const char * filepath,
|
|
111
|
+
void textbundle_write_wrapper(const char * filepath, DString * body, mmd_engine * e, const char * directory);
|
|
112
112
|
|
|
113
|
-
DString * textbundle_create(
|
|
113
|
+
DString * textbundle_create(DString * body, mmd_engine * e, const char * directory);
|
|
114
114
|
|
|
115
115
|
#endif
|
data/ext/mmd/token.c
CHANGED
|
@@ -115,17 +115,20 @@ void token_pool_free(void) {
|
|
|
115
115
|
token * token_new(unsigned short type, size_t start, size_t len) {
|
|
116
116
|
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
#ifdef kUseObjectPool
|
|
119
119
|
token * t = pool_allocate_object(token_pool);
|
|
120
|
-
|
|
120
|
+
#else
|
|
121
121
|
token * t = malloc(sizeof(token));
|
|
122
|
-
|
|
122
|
+
#endif
|
|
123
123
|
|
|
124
124
|
if (t) {
|
|
125
125
|
t->type = type;
|
|
126
126
|
t->start = start;
|
|
127
127
|
t->len = len;
|
|
128
128
|
|
|
129
|
+
t->out_start = 0;
|
|
130
|
+
t->out_len = 0;
|
|
131
|
+
|
|
129
132
|
t->next = NULL;
|
|
130
133
|
t->prev = NULL;
|
|
131
134
|
t->child = NULL;
|
|
@@ -145,11 +148,11 @@ token * token_new(unsigned short type, size_t start, size_t len) {
|
|
|
145
148
|
|
|
146
149
|
/// Duplicate an existing token
|
|
147
150
|
token * token_copy(token * original) {
|
|
148
|
-
|
|
151
|
+
#ifdef kUseObjectPool
|
|
149
152
|
token * t = pool_allocate_object(token_pool);
|
|
150
|
-
|
|
153
|
+
#else
|
|
151
154
|
token * t = malloc(sizeof(token));
|
|
152
|
-
|
|
155
|
+
#endif
|
|
153
156
|
|
|
154
157
|
if (t) {
|
|
155
158
|
* t = * original;
|
|
@@ -276,9 +279,28 @@ void token_remove_tail(token * head) {
|
|
|
276
279
|
}
|
|
277
280
|
|
|
278
281
|
|
|
282
|
+
/// Fix tail at head of token chain (e.g. after pruning)
|
|
283
|
+
void fix_token_chain_tail(token * t) {
|
|
284
|
+
if (t) {
|
|
285
|
+
token * head = t;
|
|
286
|
+
|
|
287
|
+
// Find head of chain
|
|
288
|
+
while (head->prev) {
|
|
289
|
+
head = head->prev;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Find tail
|
|
293
|
+
while (t->next) {
|
|
294
|
+
t = t->next;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Fix tail
|
|
298
|
+
head->tail = t;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
279
302
|
/// Pop token out of it's chain, connecting head and tail of chain back together.
|
|
280
303
|
/// Token must be freed if it is no longer needed.
|
|
281
|
-
/// \todo: If t is the tail token of a chain, the tail is no longer correct on the start of chain.
|
|
282
304
|
void token_pop_link_from_chain(token * t) {
|
|
283
305
|
if (t == NULL) {
|
|
284
306
|
return;
|
|
@@ -293,6 +315,8 @@ void token_pop_link_from_chain(token * t) {
|
|
|
293
315
|
|
|
294
316
|
if (prev) {
|
|
295
317
|
prev->next = next;
|
|
318
|
+
|
|
319
|
+
fix_token_chain_tail(prev);
|
|
296
320
|
}
|
|
297
321
|
|
|
298
322
|
if (next) {
|
|
@@ -312,6 +336,8 @@ void tokens_prune(token * first, token * last) {
|
|
|
312
336
|
|
|
313
337
|
if (prev != NULL) {
|
|
314
338
|
prev->next = next;
|
|
339
|
+
|
|
340
|
+
fix_token_chain_tail(prev);
|
|
315
341
|
}
|
|
316
342
|
|
|
317
343
|
if (next != NULL) {
|
|
@@ -387,9 +413,9 @@ token * token_prune_graft(token * first, token * last, unsigned short container_
|
|
|
387
413
|
|
|
388
414
|
/// Free token
|
|
389
415
|
void token_free(token * t) {
|
|
390
|
-
|
|
416
|
+
#ifdef kUseObjectPool
|
|
391
417
|
return;
|
|
392
|
-
|
|
418
|
+
#else
|
|
393
419
|
|
|
394
420
|
if (t == NULL) {
|
|
395
421
|
return;
|
|
@@ -398,15 +424,15 @@ void token_free(token * t) {
|
|
|
398
424
|
token_tree_free(t->child);
|
|
399
425
|
|
|
400
426
|
free(t);
|
|
401
|
-
|
|
427
|
+
#endif
|
|
402
428
|
}
|
|
403
429
|
|
|
404
430
|
|
|
405
431
|
/// Free token chain
|
|
406
432
|
void token_tree_free(token * t) {
|
|
407
|
-
|
|
433
|
+
#ifdef kUseObjectPool
|
|
408
434
|
return;
|
|
409
|
-
|
|
435
|
+
#else
|
|
410
436
|
token * n;
|
|
411
437
|
|
|
412
438
|
while (t != NULL) {
|
|
@@ -416,7 +442,7 @@ void token_tree_free(token * t) {
|
|
|
416
442
|
t = n;
|
|
417
443
|
}
|
|
418
444
|
|
|
419
|
-
|
|
445
|
+
#endif
|
|
420
446
|
}
|
|
421
447
|
|
|
422
448
|
|
|
@@ -592,7 +618,7 @@ void token_trim_leading_whitespace(token * t, const char * string) {
|
|
|
592
618
|
|
|
593
619
|
|
|
594
620
|
void token_trim_trailing_whitespace(token * t, const char * string) {
|
|
595
|
-
while (t->len &&
|
|
621
|
+
while (t->len && char_is_whitespace_or_line_ending(string[t->start + t->len - 1])) {
|
|
596
622
|
t->len--;
|
|
597
623
|
}
|
|
598
624
|
}
|
|
@@ -606,7 +632,7 @@ void token_trim_whitespace(token * t, const char * string) {
|
|
|
606
632
|
|
|
607
633
|
/// Check whether first token in the chain matches the given type.
|
|
608
634
|
/// If so, return and advance the chain.
|
|
609
|
-
token * token_chain_accept(token ** t, short type) {
|
|
635
|
+
token * token_chain_accept(token ** t, unsigned short type) {
|
|
610
636
|
token * result = NULL;
|
|
611
637
|
|
|
612
638
|
if (t && *t && ((*t)->type == type)) {
|
|
@@ -639,7 +665,7 @@ token * token_chain_accept_multiple(token ** t, int n, ...) {
|
|
|
639
665
|
}
|
|
640
666
|
|
|
641
667
|
|
|
642
|
-
void token_skip_until_type(token ** t, short type) {
|
|
668
|
+
void token_skip_until_type(token ** t, unsigned short type) {
|
|
643
669
|
while ((*t) && ((*t)->type != type)) {
|
|
644
670
|
*t = (*t)->next;
|
|
645
671
|
}
|
|
@@ -58,7 +58,12 @@
|
|
|
58
58
|
#define TOKEN_PARSER_TEMPLATE_H
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
#
|
|
61
|
+
#ifdef DISABLE_OBJECT_POOL
|
|
62
|
+
#undef kUseObjectPool
|
|
63
|
+
#else
|
|
64
|
+
#define kUseObjectPool 1
|
|
65
|
+
#endif
|
|
66
|
+
//!< Use an object pool to allocate tokens to improve
|
|
62
67
|
//!< performance in memory allocation. Frees all
|
|
63
68
|
//!< tokens at once, however, at end of parsing.
|
|
64
69
|
|
|
@@ -66,6 +71,12 @@
|
|
|
66
71
|
/// This allows us to know when the pool is no longer being used and it is safe
|
|
67
72
|
/// to free.
|
|
68
73
|
|
|
74
|
+
/// This is easy with a command line utility, but complex in a multithreaded
|
|
75
|
+
/// application. Unless you *really* know what you're doing, fully understand
|
|
76
|
+
/// threads and C memory management, you should probably disable object pools
|
|
77
|
+
/// when creating a long-running GUI application. (I disable them in
|
|
78
|
+
/// MultiMarkdown Composer, for example.)
|
|
79
|
+
|
|
69
80
|
#ifdef kUseObjectPool
|
|
70
81
|
void token_pool_init(void); //!< Initialize object pool for allocating tokens
|
|
71
82
|
void token_pool_drain(void); //!< Drain pool to free memory when parse complete
|
|
@@ -85,13 +96,16 @@ struct token {
|
|
|
85
96
|
size_t start; //!< Starting offset in the source string
|
|
86
97
|
size_t len; //!< Length of the token in the source string
|
|
87
98
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
size_t out_start;
|
|
100
|
+
size_t out_len;
|
|
101
|
+
|
|
102
|
+
struct token * next; //!< Pointer to next token in the chain
|
|
103
|
+
struct token * prev; //!< Pointer to previous marker in the chain
|
|
104
|
+
struct token * child; //!< Pointer to child chain
|
|
91
105
|
|
|
92
|
-
struct token
|
|
106
|
+
struct token * tail; //!< Pointer to last token in the chain
|
|
93
107
|
|
|
94
|
-
struct token
|
|
108
|
+
struct token * mate; //!< Pointer to other token in matched pair
|
|
95
109
|
};
|
|
96
110
|
|
|
97
111
|
typedef struct token token;
|
|
@@ -217,11 +231,11 @@ void token_trim_whitespace(token * t, const char * string);
|
|
|
217
231
|
|
|
218
232
|
|
|
219
233
|
///
|
|
220
|
-
token * token_chain_accept(token ** t, short type);
|
|
234
|
+
token * token_chain_accept(token ** t, unsigned short type);
|
|
221
235
|
|
|
222
236
|
token * token_chain_accept_multiple(token ** t, int n, ...);
|
|
223
237
|
|
|
224
|
-
void token_skip_until_type(token ** t, short type);
|
|
238
|
+
void token_skip_until_type(token ** t, unsigned short type);
|
|
225
239
|
|
|
226
240
|
void token_skip_until_type_multiple(token ** t, int n, ...);
|
|
227
241
|
|
data/ext/mmd/token_pairs.c
CHANGED
|
@@ -213,9 +213,6 @@ close:
|
|
|
213
213
|
opener_count[peek->type]--;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
#ifndef NDEBUG
|
|
217
|
-
fprintf(stderr, "stack now sized %lu\n", s->size);
|
|
218
|
-
#endif
|
|
219
216
|
// Prune matched section
|
|
220
217
|
|
|
221
218
|
if (e->should_prune[pair_type]) {
|
|
@@ -230,12 +227,6 @@ close:
|
|
|
230
227
|
break;
|
|
231
228
|
}
|
|
232
229
|
|
|
233
|
-
#ifndef NDEBUG
|
|
234
|
-
else {
|
|
235
|
-
fprintf(stderr, "token type %d failed to match stack element\n", walker->type);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
#endif
|
|
239
230
|
i--;
|
|
240
231
|
}
|
|
241
232
|
}
|
|
@@ -246,18 +237,11 @@ open:
|
|
|
246
237
|
if (walker->can_open && e->can_open_pair[walker->type] && walker->unmatched) {
|
|
247
238
|
stack_push(s, walker);
|
|
248
239
|
opener_count[walker->type]++;
|
|
249
|
-
#ifndef NDEBUG
|
|
250
|
-
fprintf(stderr, "push token type %d to stack (%lu elements)\n", walker->type, s->size);
|
|
251
|
-
#endif
|
|
252
240
|
}
|
|
253
241
|
|
|
254
242
|
walker = walker->next;
|
|
255
243
|
}
|
|
256
244
|
|
|
257
|
-
#ifndef NDEBUG
|
|
258
|
-
fprintf(stderr, "token stack has %lu elements (of %lu)\n", s->size, s->capacity);
|
|
259
|
-
#endif
|
|
260
|
-
|
|
261
245
|
// Remove unused tokens from stack and return to parent
|
|
262
246
|
s->size = start_counter;
|
|
263
247
|
}
|
data/ext/mmd/transclude.c
CHANGED
|
@@ -122,7 +122,7 @@ void mmd_transclude_source(DString * source, const char * search_path, const cha
|
|
|
122
122
|
// Make sure we use a parse tree for children
|
|
123
123
|
stack * parse_stack = parsed;
|
|
124
124
|
|
|
125
|
-
if (
|
|
125
|
+
if (parse_stack == NULL) {
|
|
126
126
|
// Create temporary stack
|
|
127
127
|
parse_stack = stack_new(0);
|
|
128
128
|
}
|
|
@@ -172,12 +172,14 @@ void mmd_transclude_source(DString * source, const char * search_path, const cha
|
|
|
172
172
|
|
|
173
173
|
// Adjust file wildcard extension for output format
|
|
174
174
|
// e.g. `foo.*`
|
|
175
|
-
if ((format != FORMAT_MMD) && strncmp(&text[stop - start - 4], ".*", 2) == 0) {
|
|
175
|
+
if ((stop - start > 3) && (format != FORMAT_MMD) && strncmp(&text[stop - start - 4], ".*", 2) == 0) {
|
|
176
176
|
// Trim '.*'
|
|
177
177
|
d_string_erase(file_path, file_path->currentStringLength - 2, 2);
|
|
178
178
|
|
|
179
179
|
switch (format) {
|
|
180
180
|
case FORMAT_HTML:
|
|
181
|
+
case FORMAT_HTML_WITH_ASSETS:
|
|
182
|
+
case FORMAT_EPUB:
|
|
181
183
|
d_string_append(file_path, ".html");
|
|
182
184
|
break;
|
|
183
185
|
|
|
@@ -188,6 +190,8 @@ void mmd_transclude_source(DString * source, const char * search_path, const cha
|
|
|
188
190
|
break;
|
|
189
191
|
|
|
190
192
|
case FORMAT_FODT:
|
|
193
|
+
case FORMAT_ODT:
|
|
194
|
+
// `.fodt` is the extension for historical reasons
|
|
191
195
|
d_string_append(file_path, ".fodt");
|
|
192
196
|
break;
|
|
193
197
|
|