summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/md4c/md4c.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/md4c/md4c.c')
-rw-r--r--src/3rdparty/md4c/md4c.c92
1 files changed, 78 insertions, 14 deletions
diff --git a/src/3rdparty/md4c/md4c.c b/src/3rdparty/md4c/md4c.c
index 01e63a5fd2..3745cf3e46 100644
--- a/src/3rdparty/md4c/md4c.c
+++ b/src/3rdparty/md4c/md4c.c
@@ -127,7 +127,7 @@ struct MD_CTX_tag {
#endif
/* For resolving of inline spans. */
- MD_MARKCHAIN mark_chains[11];
+ MD_MARKCHAIN mark_chains[12];
#define PTR_CHAIN ctx->mark_chains[0]
#define TABLECELLBOUNDARIES ctx->mark_chains[1]
#define ASTERISK_OPENERS_extraword_mod3_0 ctx->mark_chains[2]
@@ -139,8 +139,9 @@ struct MD_CTX_tag {
#define UNDERSCORE_OPENERS ctx->mark_chains[8]
#define TILDE_OPENERS ctx->mark_chains[9]
#define BRACKET_OPENERS ctx->mark_chains[10]
+#define DOLLAR_OPENERS ctx->mark_chains[11]
#define OPENERS_CHAIN_FIRST 2
-#define OPENERS_CHAIN_LAST 10
+#define OPENERS_CHAIN_LAST 11
int n_table_cell_boundaries;
@@ -1128,7 +1129,7 @@ md_is_html_comment(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF
if(off+1 < lines[0].end && CH(off) == _T('-') && CH(off+1) == _T('>'))
return FALSE;
- /* HTML comment must not contyain "--", so we scan just for "--" instead
+ /* HTML comment must not contain "--", so we scan just for "--" instead
* of "-->" and verify manually that '>' follows. */
if(md_scan_for_html_closer(ctx, _T("--"), 2,
lines, n_lines, off, max_end, p_end, &ctx->html_comment_horizon))
@@ -1686,7 +1687,7 @@ md_build_ref_def_hashtable(MD_CTX* ctx)
}
/* Make the bucket capable of holding more ref. defs. */
- list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 4 * sizeof(MD_REF_DEF));
+ list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 4 * sizeof(MD_REF_DEF*));
if(list == NULL) {
MD_LOG("malloc() failed.");
goto abort;
@@ -1703,7 +1704,7 @@ md_build_ref_def_hashtable(MD_CTX* ctx)
list = (MD_REF_DEF_LIST*) bucket;
if(list->n_ref_defs >= list->alloc_ref_defs) {
MD_REF_DEF_LIST* list_tmp = (MD_REF_DEF_LIST*) realloc(list,
- sizeof(MD_REF_DEF_LIST) + 2 * list->alloc_ref_defs * sizeof(MD_REF_DEF));
+ sizeof(MD_REF_DEF_LIST) + 2 * list->alloc_ref_defs * sizeof(MD_REF_DEF*));
if(list_tmp == NULL) {
MD_LOG("realloc() failed.");
goto abort;
@@ -2683,6 +2684,9 @@ md_build_mark_char_map(MD_CTX* ctx)
if(ctx->parser.flags & MD_FLAG_STRIKETHROUGH)
ctx->mark_char_map['~'] = 1;
+ if(ctx->parser.flags & MD_FLAG_LATEXMATHSPANS)
+ ctx->mark_char_map['$'] = 1;
+
if(ctx->parser.flags & MD_FLAG_PERMISSIVEEMAILAUTOLINKS)
ctx->mark_char_map['@'] = 1;
@@ -3251,6 +3255,21 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode)
continue;
}
+ /* A potential equation start/end */
+ if(ch == _T('$')) {
+ /* We can have at most two consecutive $ signs,
+ * where two dollar signs signify a display equation. */
+ OFF tmp = off+1;
+
+ while(tmp < line_end && CH(tmp) == _T('$'))
+ tmp++;
+
+ if (tmp - off <= 2)
+ PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER);
+ off = tmp;
+ continue;
+ }
+
/* Turn non-trivial whitespace into single space. */
if(ISWHITESPACE_(ch)) {
OFF tmp = off+1;
@@ -3631,6 +3650,36 @@ md_analyze_tilde(MD_CTX* ctx, int mark_index)
}
static void
+md_analyze_dollar(MD_CTX* ctx, int mark_index)
+{
+ /* This should mimic the way inline equations work in LaTeX, so there
+ * can only ever be one item in the chain (i.e. the dollars can't be
+ * nested). This is basically the same as the md_analyze_tilde function,
+ * except that we require matching openers and closers to be of the same
+ * length.
+ *
+ * E.g.: $abc$$def$$ => abc (display equation) def (end equation) */
+ if(DOLLAR_OPENERS.head >= 0) {
+ /* If the potential closer has a non-matching number of $, discard */
+ MD_MARK* open = &ctx->marks[DOLLAR_OPENERS.head];
+ MD_MARK* close = &ctx->marks[mark_index];
+
+ int opener_index = DOLLAR_OPENERS.head;
+ md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_ALL);
+ if (open->end - open->beg == close->end - close->beg) {
+ /* We are the matching closer */
+ md_resolve_range(ctx, &DOLLAR_OPENERS, opener_index, mark_index);
+ } else {
+ /* We don't match the opener, so discard old opener and insert as opener */
+ md_mark_chain_append(ctx, &DOLLAR_OPENERS, mark_index);
+ }
+ } else {
+ /* No unmatched openers, so we are opener */
+ md_mark_chain_append(ctx, &DOLLAR_OPENERS, mark_index);
+ }
+}
+
+static void
md_analyze_permissive_url_autolink(MD_CTX* ctx, int mark_index)
{
MD_MARK* opener = &ctx->marks[mark_index];
@@ -3785,6 +3834,7 @@ md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
case '_': /* Pass through. */
case '*': md_analyze_emph(ctx, i); break;
case '~': md_analyze_tilde(ctx, i); break;
+ case '$': md_analyze_dollar(ctx, i); break;
case '.': /* Pass through. */
case ':': md_analyze_permissive_url_autolink(ctx, i); break;
case '@': md_analyze_permissive_email_autolink(ctx, i); break;
@@ -3841,7 +3891,7 @@ static void
md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
int mark_beg, int mark_end)
{
- md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, _T("*_~@:."));
+ md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, _T("*_~$@:."));
ASTERISK_OPENERS_extraword_mod3_0.head = -1;
ASTERISK_OPENERS_extraword_mod3_0.tail = -1;
ASTERISK_OPENERS_extraword_mod3_1.head = -1;
@@ -3858,6 +3908,8 @@ md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
UNDERSCORE_OPENERS.tail = -1;
TILDE_OPENERS.head = -1;
TILDE_OPENERS.tail = -1;
+ DOLLAR_OPENERS.head = -1;
+ DOLLAR_OPENERS.tail = -1;
}
static int
@@ -3974,6 +4026,16 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
MD_LEAVE_SPAN(MD_SPAN_DEL, NULL);
break;
+ case '$':
+ if(mark->flags & MD_MARK_OPENER) {
+ MD_ENTER_SPAN((mark->end - off) % 2 ? MD_SPAN_LATEXMATH : MD_SPAN_LATEXMATH_DISPLAY, NULL);
+ text_type = MD_TEXT_LATEXMATH;
+ } else {
+ MD_LEAVE_SPAN((mark->end - off) % 2 ? MD_SPAN_LATEXMATH : MD_SPAN_LATEXMATH_DISPLAY, NULL);
+ text_type = MD_TEXT_NORMAL;
+ }
+ break;
+
case '[': /* Link, image. */
case '!':
case ']':
@@ -4072,12 +4134,12 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
if(off >= end)
break;
- if(text_type == MD_TEXT_CODE) {
+ if(text_type == MD_TEXT_CODE || text_type == MD_TEXT_LATEXMATH) {
OFF tmp;
MD_ASSERT(prev_mark != NULL);
- MD_ASSERT(prev_mark->ch == '`' && (prev_mark->flags & MD_MARK_OPENER));
- MD_ASSERT(mark->ch == '`' && (mark->flags & MD_MARK_CLOSER));
+ MD_ASSERT(ISANYOF2_(prev_mark->ch, '`', '$') && (prev_mark->flags & MD_MARK_OPENER));
+ MD_ASSERT(ISANYOF2_(mark->ch, '`', '$') && (mark->flags & MD_MARK_CLOSER));
/* Inside a code span, trailing line whitespace has to be
* outputted. */
@@ -4085,12 +4147,11 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
while(off < ctx->size && ISBLANK(off))
off++;
if(off > tmp)
- MD_TEXT(MD_TEXT_CODE, STR(tmp), off-tmp);
+ MD_TEXT(text_type, STR(tmp), off-tmp);
/* and new lines are transformed into single spaces. */
if(prev_mark->end < off && off < mark->beg)
- MD_TEXT(MD_TEXT_CODE, _T(" "), 1);
-
+ MD_TEXT(text_type, _T(" "), 1);
} else if(text_type == MD_TEXT_HTML) {
/* Inside raw HTML, we output the new line verbatim, including
* any trailing spaces. */
@@ -5425,7 +5486,10 @@ md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTA
p_container->start = p_container->start * 10 + CH(off) - _T('0');
off++;
}
- if(off+1 < ctx->size && (CH(off) == _T('.') || CH(off) == _T(')')) && (ISBLANK(off+1) || ISNEWLINE(off+1))) {
+ if(off > beg && off+1 < ctx->size &&
+ (CH(off) == _T('.') || CH(off) == _T(')')) &&
+ (ISBLANK(off+1) || ISNEWLINE(off+1)))
+ {
p_container->ch = CH(off);
p_container->is_loose = FALSE;
p_container->is_task = FALSE;
@@ -5700,7 +5764,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end,
md_is_container_mark(ctx, line->indent, off, &off, &container))
{
if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers &&
- (off >= ctx->size || ISNEWLINE(off)))
+ (off >= ctx->size || ISNEWLINE(off)) && container.ch != _T('>'))
{
/* Noop. List mark followed by a blank line cannot interrupt a paragraph. */
} else if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers &&