summaryrefslogtreecommitdiff
path: root/src/inlines.c
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2015-06-11 10:11:37 -0700
committerJohn MacFarlane <jgm@berkeley.edu>2015-06-11 10:15:39 -0700
commit39b40151afa1af92c2d585c86930393be7e8ac73 (patch)
treee02ef08f18cceecba6c548d9a9fed0fdf5277307 /src/inlines.c
parent4224dc159cdd0b4429a566a14792c0abc0f5f62a (diff)
Fixed `process_emphasis` to handle new pathological cases.
Now we have an array of pointers (`potential_openers`), keyed to the delim char. When we've failed to match a potential opener prior to point X in the delimiter stack, we reset `potential_openers` for that opener type to X, and thus avoid having to look again through all the openers we've already rejected. See jgm/commonmark#43.
Diffstat (limited to 'src/inlines.c')
-rw-r--r--src/inlines.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/inlines.c b/src/inlines.c
index 7b51be9..0a75e38 100644
--- a/src/inlines.c
+++ b/src/inlines.c
@@ -441,6 +441,13 @@ static void process_emphasis(subject *subj, delimiter *start_delim)
delimiter *opener;
delimiter *old_closer;
bool opener_found;
+ delimiter *potential_openers[128];
+
+ // initialize potential_openers:
+ potential_openers['*'] = start_delim;
+ potential_openers['_'] = start_delim;
+ potential_openers['\''] = start_delim;
+ potential_openers['"'] = start_delim;
// move back to first relevant delim.
while (closer != NULL && closer->previous != start_delim) {
@@ -455,7 +462,7 @@ static void process_emphasis(subject *subj, delimiter *start_delim)
// Now look backwards for first matching opener:
opener = closer->previous;
opener_found = false;
- while (opener != NULL && opener != start_delim) {
+ while (opener != NULL && opener != potential_openers[closer->delim_char]) {
if (opener->delim_char == closer->delim_char &&
opener->can_open) {
opener_found = true;
@@ -464,7 +471,13 @@ static void process_emphasis(subject *subj, delimiter *start_delim)
opener = opener->previous;
}
old_closer = closer;
- if (closer->delim_char == '*' || closer->delim_char == '_') {
+ if (closer->delim_char == '*') {
+ if (opener_found) {
+ closer = S_insert_emph(subj, opener, closer);
+ } else {
+ closer = closer->next;
+ }
+ } else if (closer->delim_char == '_') {
if (opener_found) {
closer = S_insert_emph(subj, opener, closer);
} else {
@@ -492,6 +505,8 @@ static void process_emphasis(subject *subj, delimiter *start_delim)
closer = closer->next;
}
if (!opener_found && !old_closer->can_open) {
+ // set lower bound for future searches for openers:
+ potential_openers[old_closer->delim_char] = closer;
// we can remove a closer that can't be an
// opener, once we've seen there's no
// matching opener: