commit ghc-cmark for openSUSE:Factory

Hello community, here is the log from the commit of package ghc-cmark for openSUSE:Factory checked in at 2016-03-31 13:02:35 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-cmark (Old) and /work/SRC/openSUSE:Factory/.ghc-cmark.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "ghc-cmark" Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-cmark/ghc-cmark.changes 2016-02-05 00:31:25.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.ghc-cmark.new/ghc-cmark.changes 2016-03-31 13:02:37.000000000 +0200 @@ -1,0 +2,7 @@ +Tue Mar 29 06:55:28 UTC 2016 - mimi.vx@gmail.com + +- update to 0.5.2 +* Add flag to allow building with an installed libcmark (Jens Petersen). +* Updated to libcmark 0.25.2. + +------------------------------------------------------------------- Old: ---- cmark-0.5.1.tar.gz New: ---- cmark-0.5.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-cmark.spec ++++++ --- /var/tmp/diff_new_pack.TiilDK/_old 2016-03-31 13:02:38.000000000 +0200 +++ /var/tmp/diff_new_pack.TiilDK/_new 2016-03-31 13:02:38.000000000 +0200 @@ -21,7 +21,7 @@ %bcond_with tests Name: ghc-cmark -Version: 0.5.1 +Version: 0.5.2 Release: 0 Summary: Fast, accurate CommonMark (Markdown) parser and renderer License: BSD-3-Clause and BSD-2-Clause and MIT ++++++ cmark-0.5.1.tar.gz -> cmark-0.5.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/README.md new/cmark-0.5.2/README.md --- old/cmark-0.5.1/README.md 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/README.md 2016-03-26 21:36:02.000000000 +0100 @@ -3,8 +3,8 @@ This package provides Haskell bindings for [libcmark], the reference parser for [CommonMark], a fully specified variant of Markdown. -It includes sources for [libcmark] (version 0.23.0, implementing -version 0.23 of the spec) and does not require prior installation of +It includes sources for [libcmark] (version 0.25.2, implementing +version 0.25 of the spec) and does not require prior installation of the C library. cmark provides the following advantages over existing Markdown diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/blocks.c new/cmark-0.5.2/cbits/blocks.c --- old/cmark-0.5.1/cbits/blocks.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/blocks.c 2016-03-26 21:36:02.000000000 +0100 @@ -1,3 +1,10 @@ +/** + * Block parsing implementation. + * + * For a high-level overview of the block parsing process, + * see http://spec.commonmark.org/0.24/#phase-1-block-structure + */ + #include <stdlib.h> #include <assert.h> #include <stdio.h> @@ -17,12 +24,20 @@ #define CODE_INDENT 4 #define TAB_STOP 4 +#ifndef MIN +#define MIN(x, y) ((x < y) ? x : y) +#endif + #define peek_at(i, n) (i)->data[n] -static inline bool S_is_line_end_char(char c) { +static CMARK_INLINE bool S_is_line_end_char(char c) { return (c == '\n' || c == '\r'); } +static CMARK_INLINE bool S_is_space_or_tab(char c) { + return (c == ' ' || c == '\t'); +} + static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer, size_t len, bool eof); @@ -70,10 +85,12 @@ parser->first_nonspace_column = 0; parser->indent = 0; parser->blank = false; + parser->partially_consumed_tab = false; parser->curline = line; parser->last_line_length = 0; parser->linebuf = buf; parser->options = options; + parser->last_buffer_ended_with_cr = false; return parser; } @@ -110,7 +127,7 @@ return true; } -static inline bool can_contain(cmark_node_type parent_type, +static CMARK_INLINE bool can_contain(cmark_node_type parent_type, cmark_node_type child_type) { return (parent_type == CMARK_NODE_DOCUMENT || parent_type == CMARK_NODE_BLOCK_QUOTE || @@ -118,15 +135,32 @@ (parent_type == CMARK_NODE_LIST && child_type == CMARK_NODE_ITEM)); } -static inline bool accepts_lines(cmark_node_type block_type) { +static CMARK_INLINE bool accepts_lines(cmark_node_type block_type) { return (block_type == CMARK_NODE_PARAGRAPH || block_type == CMARK_NODE_HEADING || block_type == CMARK_NODE_CODE_BLOCK); } -static void add_line(cmark_node *node, cmark_chunk *ch, bufsize_t offset) { +static CMARK_INLINE bool contains_inlines(cmark_node_type block_type) { + return (block_type == CMARK_NODE_PARAGRAPH || + block_type == CMARK_NODE_HEADING); +} + +static void add_line(cmark_node *node, cmark_chunk *ch, cmark_parser *parser) { + int chars_to_tab; + int i; assert(node->open); - cmark_strbuf_put(&node->string_content, ch->data + offset, ch->len - offset); + if (parser->partially_consumed_tab) { + parser->offset += 1; // skip over tab + // add space characters: + chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); + for (i = 0; i < chars_to_tab; i++) { + cmark_strbuf_putc(&node->string_content, ' '); + } + } + cmark_strbuf_put(&node->string_content, + ch->data + parser->offset, + ch->len - parser->offset); } static void remove_trailing_blank_lines(cmark_strbuf *ln) { @@ -336,8 +370,7 @@ while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { cur = cmark_iter_get_node(iter); if (ev_type == CMARK_EVENT_ENTER) { - if (cur->type == CMARK_NODE_PARAGRAPH || - cur->type == CMARK_NODE_HEADING) { + if (contains_inlines(cur->type)) { cmark_parse_inlines(cur, refmap, options); } } @@ -474,6 +507,11 @@ const unsigned char *end = buffer + len; static const uint8_t repl[] = {239, 191, 189}; + if (parser->last_buffer_ended_with_cr && *buffer == '\n') { + // skip NL if last buffer ended with CR ; see #117 + buffer++; + } + parser->last_buffer_ended_with_cr = false; while (buffer < end) { const unsigned char *eol; bufsize_t chunk_len; @@ -514,8 +552,11 @@ buffer += chunk_len; // skip over line ending characters: - if (buffer < end && *buffer == '\r') + if (buffer < end && *buffer == '\r') { buffer++; + if (buffer == end) + parser->last_buffer_ended_with_cr = true; + } if (buffer < end && *buffer == '\n') buffer++; } @@ -532,13 +573,15 @@ n--; // Check for a space before the final #s: - if (n != orig_n && n >= 0 && - (peek_at(ch, n) == ' ' || peek_at(ch, n) == '\t')) { + if (n != orig_n && n >= 0 && S_is_space_or_tab(peek_at(ch, n))) { ch->len = n; cmark_chunk_rtrim(ch); } } +// Find first nonspace character from current offset, setting +// parser->first_nonspace, parser->first_nonspace_column, +// parser->indent, and parser->blank. Does not advance parser->offset. static void S_find_first_nonspace(cmark_parser *parser, cmark_chunk *input) { char c; int chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); @@ -566,17 +609,37 @@ parser->blank = S_is_line_end_char(peek_at(input, parser->first_nonspace)); } +// Advance parser->offset and parser->column. parser->offset is the +// byte position in input; parser->column is a virtual column number +// that takes into account tabs. (Multibyte characters are not taken +// into account, because the Markdown line prefixes we are interested in +// analyzing are entirely ASCII.) The count parameter indicates +// how far to advance the offset. If columns is true, then count +// indicates a number of columns; otherwise, a number of bytes. +// If advancing a certain number of columns partially consumes +// a tab character, parser->partially_consumed_tab is set to true. static void S_advance_offset(cmark_parser *parser, cmark_chunk *input, bufsize_t count, bool columns) { char c; int chars_to_tab; + int chars_to_advance; while (count > 0 && (c = peek_at(input, parser->offset))) { if (c == '\t') { chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); - parser->column += chars_to_tab; - parser->offset += 1; - count -= (columns ? chars_to_tab : 1); + if (columns) { + parser->partially_consumed_tab = chars_to_tab > count; + chars_to_advance = MIN(count, chars_to_tab); + parser->column += chars_to_advance; + parser->offset += (parser->partially_consumed_tab ? 0 : 1); + count -= chars_to_advance; + } else { + parser->partially_consumed_tab = false; + parser->column += chars_to_tab; + parser->offset += 1; + count -= 1; + } } else { + parser->partially_consumed_tab = false; parser->offset += 1; parser->column += 1; // assume ascii; block starts are ascii count -= 1; @@ -584,263 +647,314 @@ } } -static void S_process_line(cmark_parser *parser, const unsigned char *buffer, - bufsize_t bytes) { - cmark_node *last_matched_container; - bufsize_t matched = 0; - int lev = 0; - int i; - cmark_list *data = NULL; - bool all_matched = true; - cmark_node *container; - bool indented; - cmark_chunk input; - bool maybe_lazy; - - if (parser->options & CMARK_OPT_VALIDATE_UTF8) { - cmark_utf8proc_check(parser->curline, buffer, bytes); - } else { - cmark_strbuf_put(parser->curline, buffer, bytes); - } - // ensure line ends with a newline: - if (bytes == 0 || !S_is_line_end_char(parser->curline->ptr[bytes - 1])) { - cmark_strbuf_putc(parser->curline, '\n'); - } - parser->offset = 0; - parser->column = 0; - parser->blank = false; - - input.data = parser->curline->ptr; - input.len = parser->curline->size; - - // container starts at the document root. - container = parser->root; +static bool S_last_child_is_open(cmark_node *container) { + return container->last_child && container->last_child->open; +} - parser->line_number++; +static bool parse_block_quote_prefix(cmark_parser *parser, + cmark_chunk *input) +{ + bool res = false; + bufsize_t matched = 0; - // for each containing node, try to parse the associated line start. - // bail out on failure: container will point to the last matching node. + matched = + parser->indent <= 3 && peek_at(input, parser->first_nonspace) == '>'; + if (matched) { + + S_advance_offset(parser, input, parser->indent + 1, true); + + if (S_is_space_or_tab(peek_at(input, parser->offset))) { + S_advance_offset(parser, input, 1, true); + } + + res = true; + } + return res; +} + +static bool parse_node_item_prefix(cmark_parser *parser, + cmark_chunk *input, + cmark_node *container) +{ + bool res = false; + + if (parser->indent >= + container->as.list.marker_offset + container->as.list.padding) { + S_advance_offset(parser, input, container->as.list.marker_offset + + container->as.list.padding, + true); + res = true; + } else if (parser->blank && container->first_child != NULL) { + // if container->first_child is NULL, then the opening line + // of the list item was blank after the list marker; in this + // case, we are done with the list item. + S_advance_offset(parser, input, + parser->first_nonspace - parser->offset, false); + res = true; + } + return res; +} + +static bool parse_code_block_prefix(cmark_parser *parser, + cmark_chunk *input, + cmark_node *container, + bool *should_continue) +{ + bool res = false; + + if (!container->as.code.fenced) { // indented + if (parser->indent >= CODE_INDENT) { + S_advance_offset(parser, input, CODE_INDENT, true); + res = true; + } else if (parser->blank) { + S_advance_offset(parser, input, + parser->first_nonspace - parser->offset, false); + res = true; + } + } else { // fenced + bufsize_t matched = 0; + + if (parser->indent <= 3 && (peek_at(input, parser->first_nonspace) == + container->as.code.fence_char)) { + matched = scan_close_code_fence(input, parser->first_nonspace); + } + + if (matched >= container->as.code.fence_length) { + // closing fence - and since we're at + // the end of a line, we can stop processing it: + *should_continue = false; + S_advance_offset(parser, input, matched, false); + parser->current = finalize(parser, container); + } else { + // skip opt. spaces of fence parser->offset + int i = container->as.code.fence_offset; - while (container->last_child && container->last_child->open) { - container = container->last_child; + while (i > 0 && S_is_space_or_tab(peek_at(input, parser->offset))) { + S_advance_offset(parser, input, 1, true); + i--; + } + res = true; + } + } - S_find_first_nonspace(parser, &input); + return res; +} - if (container->type == CMARK_NODE_BLOCK_QUOTE) { - matched = - parser->indent <= 3 && peek_at(&input, parser->first_nonspace) == '>'; - if (matched) { - S_advance_offset(parser, &input, parser->indent + 1, true); - if (peek_at(&input, parser->offset) == ' ') - parser->offset++; - } else { - all_matched = false; - } +static bool parse_html_block_prefix(cmark_parser *parser, + cmark_node *container) +{ + bool res = false; + int html_block_type = container->as.html_block_type; - } else if (container->type == CMARK_NODE_ITEM) { - if (parser->indent >= - container->as.list.marker_offset + container->as.list.padding) { - S_advance_offset(parser, &input, container->as.list.marker_offset + - container->as.list.padding, - true); - } else if (parser->blank && container->first_child != NULL) { - // if container->first_child is NULL, then the opening line - // of the list item was blank after the list marker; in this - // case, we are done with the list item. - S_advance_offset(parser, &input, - parser->first_nonspace - parser->offset, false); - } else { - all_matched = false; - } + assert(html_block_type >= 1 && html_block_type <= 7); + switch (html_block_type) { + case 1: + case 2: + case 3: + case 4: + case 5: + // these types of blocks can accept blanks + res = true; + break; + case 6: + case 7: + res = !parser->blank; + break; + } - } else if (container->type == CMARK_NODE_CODE_BLOCK) { + return res; +} - if (!container->as.code.fenced) { // indented - if (parser->indent >= CODE_INDENT) { - S_advance_offset(parser, &input, CODE_INDENT, true); - } else if (parser->blank) { - S_advance_offset(parser, &input, - parser->first_nonspace - parser->offset, false); - } else { - all_matched = false; - } - } else { // fenced - matched = 0; - if (parser->indent <= 3 && (peek_at(&input, parser->first_nonspace) == - container->as.code.fence_char)) { - matched = scan_close_code_fence(&input, parser->first_nonspace); - } - if (matched >= container->as.code.fence_length) { - // closing fence - and since we're at - // the end of a line, we can return: - all_matched = false; - S_advance_offset(parser, &input, matched, false); - parser->current = finalize(parser, container); - goto finished; - } else { - // skip opt. spaces of fence parser->offset - i = container->as.code.fence_offset; - while (i > 0 && peek_at(&input, parser->offset) == ' ') { - S_advance_offset(parser, &input, 1, false); - i--; - } - } - } - } else if (container->type == CMARK_NODE_HEADING) { +/** + * For each containing node, try to parse the associated line start. + * + * Will not close unmatched blocks, as we may have a lazy continuation + * line -> http://spec.commonmark.org/0.24/#lazy-continuation-line + * + * Returns: The last matching node, or NULL + */ +static cmark_node *check_open_blocks(cmark_parser *parser, + cmark_chunk *input, + bool *all_matched) +{ + bool should_continue = true; + *all_matched = false; + cmark_node *container = parser->root; + cmark_node_type cont_type; - // a heading can never contain more than one line - all_matched = false; + while (S_last_child_is_open(container)) { + container = container->last_child; + cont_type = container->type; - } else if (container->type == CMARK_NODE_HTML_BLOCK) { + S_find_first_nonspace(parser, input); - switch (container->as.html_block_type) { - case 1: - case 2: - case 3: - case 4: - case 5: - // these types of blocks can accept blanks + switch (cont_type) { + case CMARK_NODE_BLOCK_QUOTE: + if (!parse_block_quote_prefix(parser, input)) + goto done; break; - case 6: - case 7: - if (parser->blank) { - all_matched = false; - } + case CMARK_NODE_ITEM: + if (!parse_node_item_prefix(parser, input, container)) + goto done; + break; + case CMARK_NODE_CODE_BLOCK: + if (!parse_code_block_prefix(parser, input, container, &should_continue)) + goto done; + break; + case CMARK_NODE_HEADING: + // a heading can never contain more than one line + goto done; + case CMARK_NODE_HTML_BLOCK: + if (!parse_html_block_prefix(parser, container)) + goto done; + break; + case CMARK_NODE_PARAGRAPH: + if (parser->blank) + goto done; break; default: - fprintf(stderr, "Error (%s:%d): Unknown HTML block type %d\n", __FILE__, - __LINE__, container->as.html_block_type); - exit(1); - } + break; + } + } - } else if (container->type == CMARK_NODE_PARAGRAPH) { + *all_matched = true; - if (parser->blank) { - all_matched = false; - } - } +done: + if (!*all_matched) { + container = container->parent; // back up to last matching node + } - if (!all_matched) { - container = container->parent; // back up to last matching node - break; - } + if (!should_continue) { + container = NULL; } - last_matched_container = container; + return container; +} - // check to see if we've hit 2nd blank line, break out of list: - if (parser->blank && container->last_line_blank) { - break_out_of_lists(parser, &container); - } +static void open_new_blocks(cmark_parser *parser, + cmark_node **container, + cmark_chunk *input, + bool all_matched) +{ + bool indented; + cmark_list *data = NULL; + bool maybe_lazy = parser->current->type == CMARK_NODE_PARAGRAPH; + cmark_node_type cont_type = (*container)->type; + bufsize_t matched = 0; + int lev = 0; + bool save_partially_consumed_tab; + int save_offset; + int save_column; - maybe_lazy = parser->current->type == CMARK_NODE_PARAGRAPH; - // try new container starts: - while (container->type != CMARK_NODE_CODE_BLOCK && - container->type != CMARK_NODE_HTML_BLOCK) { + while (cont_type != CMARK_NODE_CODE_BLOCK && + cont_type != CMARK_NODE_HTML_BLOCK) { - S_find_first_nonspace(parser, &input); + S_find_first_nonspace(parser, input); indented = parser->indent >= CODE_INDENT; - if (!indented && peek_at(&input, parser->first_nonspace) == '>') { + if (!indented && peek_at(input, parser->first_nonspace) == '>') { - S_advance_offset(parser, &input, + S_advance_offset(parser, input, parser->first_nonspace + 1 - parser->offset, false); // optional following character - if (peek_at(&input, parser->offset) == ' ') - S_advance_offset(parser, &input, 1, false); - container = add_child(parser, container, CMARK_NODE_BLOCK_QUOTE, + if (S_is_space_or_tab(peek_at(input, parser->offset))) { + S_advance_offset(parser, input, 1, true); + } + *container = add_child(parser, *container, CMARK_NODE_BLOCK_QUOTE, parser->offset + 1); } else if (!indented && (matched = scan_atx_heading_start( - &input, parser->first_nonspace))) { + input, parser->first_nonspace))) { + bufsize_t hashpos; + int level = 0; - S_advance_offset(parser, &input, + S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false); - container = - add_child(parser, container, CMARK_NODE_HEADING, parser->offset + 1); + *container = + add_child(parser, *container, CMARK_NODE_HEADING, parser->offset + 1); - bufsize_t hashpos = - cmark_chunk_strchr(&input, '#', parser->first_nonspace); - int level = 0; + hashpos = cmark_chunk_strchr(input, '#', parser->first_nonspace); - while (peek_at(&input, hashpos) == '#') { + while (peek_at(input, hashpos) == '#') { level++; hashpos++; } - container->as.heading.level = level; - container->as.heading.setext = false; - } else if (!indented && (matched = scan_open_code_fence( - &input, parser->first_nonspace))) { + (*container)->as.heading.level = level; + (*container)->as.heading.setext = false; - container = add_child(parser, container, CMARK_NODE_CODE_BLOCK, + } else if (!indented && (matched = scan_open_code_fence( + input, parser->first_nonspace))) { + *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK, parser->first_nonspace + 1); - container->as.code.fenced = true; - container->as.code.fence_char = peek_at(&input, parser->first_nonspace); - container->as.code.fence_length = matched; - container->as.code.fence_offset = + (*container)->as.code.fenced = true; + (*container)->as.code.fence_char = peek_at(input, parser->first_nonspace); + (*container)->as.code.fence_length = matched; + (*container)->as.code.fence_offset = (int8_t)(parser->first_nonspace - parser->offset); - container->as.code.info = cmark_chunk_literal(""); - S_advance_offset(parser, &input, + (*container)->as.code.info = cmark_chunk_literal(""); + S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false); } else if (!indented && ((matched = scan_html_block_start( - &input, parser->first_nonspace)) || - (container->type != CMARK_NODE_PARAGRAPH && + input, parser->first_nonspace)) || + (cont_type != CMARK_NODE_PARAGRAPH && (matched = scan_html_block_start_7( - &input, parser->first_nonspace))))) { - - container = add_child(parser, container, CMARK_NODE_HTML_BLOCK, + input, parser->first_nonspace))))) { + *container = add_child(parser, *container, CMARK_NODE_HTML_BLOCK, parser->first_nonspace + 1); - container->as.html_block_type = matched; + (*container)->as.html_block_type = matched; // note, we don't adjust parser->offset because the tag is part of the // text - - } else if (!indented && container->type == CMARK_NODE_PARAGRAPH && + } else if (!indented && cont_type == CMARK_NODE_PARAGRAPH && (lev = - scan_setext_heading_line(&input, parser->first_nonspace))) { - - container->type = CMARK_NODE_HEADING; - container->as.heading.level = lev; - container->as.heading.setext = true; - S_advance_offset(parser, &input, input.len - 1 - parser->offset, false); - + scan_setext_heading_line(input, parser->first_nonspace))) { + (*container)->type = CMARK_NODE_HEADING; + (*container)->as.heading.level = lev; + (*container)->as.heading.setext = true; + S_advance_offset(parser, input, input->len - 1 - parser->offset, false); } else if (!indented && - !(container->type == CMARK_NODE_PARAGRAPH && !all_matched) && + !(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) && (matched = - scan_thematic_break(&input, parser->first_nonspace))) { - + scan_thematic_break(input, parser->first_nonspace))) { // it's only now that we know the line is not part of a setext heading: - container = add_child(parser, container, CMARK_NODE_THEMATIC_BREAK, + *container = add_child(parser, *container, CMARK_NODE_THEMATIC_BREAK, parser->first_nonspace + 1); - S_advance_offset(parser, &input, input.len - 1 - parser->offset, false); - + S_advance_offset(parser, input, input->len - 1 - parser->offset, false); } else if ((matched = - parse_list_marker(&input, parser->first_nonspace, &data)) && - (!indented || container->type == CMARK_NODE_LIST)) { + parse_list_marker(input, parser->first_nonspace, &data)) && + (!indented || cont_type == CMARK_NODE_LIST)) { // Note that we can have new list items starting with >= 4 // spaces indent, as long as the list container is still open. + int i = 0; // compute padding: - S_advance_offset(parser, &input, + S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false); - i = 0; - while (i <= 5 && peek_at(&input, parser->offset + i) == ' ') { - i++; - } - // i = number of spaces after marker, up to 5 - if (i >= 5 || i < 1 || - S_is_line_end_char(peek_at(&input, parser->offset))) { + + save_partially_consumed_tab = parser->partially_consumed_tab; + save_offset = parser->offset; + save_column = parser->column; + + while (parser->column - save_column <= 5 && + S_is_space_or_tab(peek_at(input, parser->offset))) { + S_advance_offset(parser, input, 1, true); + } + + i = parser->column - save_column; + if (i >= 5 || i < 1) { data->padding = matched + 1; + parser->offset = save_offset; + parser->column = save_column; + parser->partially_consumed_tab = save_partially_consumed_tab; if (i > 0) { - S_advance_offset(parser, &input, 1, false); + S_advance_offset(parser, input, 1, true); } } else { data->padding = matched + i; - S_advance_offset(parser, &input, i, true); } // check container; if it's a list, see if this list item @@ -848,50 +962,57 @@ data->marker_offset = parser->indent; - if (container->type != CMARK_NODE_LIST || - !lists_match(&container->as.list, data)) { - container = add_child(parser, container, CMARK_NODE_LIST, + if (cont_type != CMARK_NODE_LIST || + !lists_match(&((*container)->as.list), data)) { + *container = add_child(parser, *container, CMARK_NODE_LIST, parser->first_nonspace + 1); - memcpy(&container->as.list, data, sizeof(*data)); + memcpy(&((*container)->as.list), data, sizeof(*data)); } // add the list item - container = add_child(parser, container, CMARK_NODE_ITEM, + *container = add_child(parser, *container, CMARK_NODE_ITEM, parser->first_nonspace + 1); /* TODO: static */ - memcpy(&container->as.list, data, sizeof(*data)); + memcpy(&((*container)->as.list), data, sizeof(*data)); free(data); - } else if (indented && !maybe_lazy && !parser->blank) { - S_advance_offset(parser, &input, CODE_INDENT, true); - container = add_child(parser, container, CMARK_NODE_CODE_BLOCK, + S_advance_offset(parser, input, CODE_INDENT, true); + *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK, parser->offset + 1); - container->as.code.fenced = false; - container->as.code.fence_char = 0; - container->as.code.fence_length = 0; - container->as.code.fence_offset = 0; - container->as.code.info = cmark_chunk_literal(""); + (*container)->as.code.fenced = false; + (*container)->as.code.fence_char = 0; + (*container)->as.code.fence_length = 0; + (*container)->as.code.fence_offset = 0; + (*container)->as.code.info = cmark_chunk_literal(""); } else { break; } - if (accepts_lines(container->type)) { + if (accepts_lines((*container)->type)) { // if it's a line container, it can't contain other containers break; } + + cont_type = (*container)->type; maybe_lazy = false; } +} +static void add_text_to_container (cmark_parser *parser, + cmark_node *container, + cmark_node *last_matched_container, + cmark_chunk *input) +{ + cmark_node *tmp; // what remains at parser->offset is a text line. add the text to the // appropriate container. - S_find_first_nonspace(parser, &input); + S_find_first_nonspace(parser, input); - if (parser->blank && container->last_child) { + if (parser->blank && container->last_child) container->last_child->last_line_blank = true; - } // block quote lines are never blank as they start with > // and we don't count blanks in fenced code for purposes of tight/loose @@ -906,61 +1027,61 @@ !(container->type == CMARK_NODE_ITEM && container->first_child == NULL && container->start_line == parser->line_number)); - cmark_node *cont = container; - while (cont->parent) { - cont->parent->last_line_blank = false; - cont = cont->parent; + tmp = container; + while (tmp->parent) { + tmp->parent->last_line_blank = false; + tmp = tmp->parent; } + // If the last line processed belonged to a paragraph node, + // and we didn't match all of the line prefixes for the open containers, + // and we didn't start any new containers, + // and the line isn't blank, + // then treat this as a "lazy continuation line" and add it to + // the open paragraph. if (parser->current != last_matched_container && - container == last_matched_container && !parser->blank && - parser->current->type == CMARK_NODE_PARAGRAPH && - cmark_strbuf_len(&parser->current->string_content) > 0) { - - add_line(parser->current, &input, parser->offset); - + container == last_matched_container && + !parser->blank && + parser->current->type == CMARK_NODE_PARAGRAPH) { + add_line(parser->current, input, parser); } else { // not a lazy continuation - - // finalize any blocks that were not matched and set cur to container: + // Finalize any blocks that were not matched and set cur to container: while (parser->current != last_matched_container) { parser->current = finalize(parser, parser->current); assert(parser->current != NULL); } if (container->type == CMARK_NODE_CODE_BLOCK) { - - add_line(container, &input, parser->offset); - + add_line(container, input, parser); } else if (container->type == CMARK_NODE_HTML_BLOCK) { - - add_line(container, &input, parser->offset); + add_line(container, input, parser); int matches_end_condition; switch (container->as.html_block_type) { case 1: // </script>, </style>, </pre> matches_end_condition = - scan_html_block_end_1(&input, parser->first_nonspace); + scan_html_block_end_1(input, parser->first_nonspace); break; case 2: // --> matches_end_condition = - scan_html_block_end_2(&input, parser->first_nonspace); + scan_html_block_end_2(input, parser->first_nonspace); break; case 3: // ?> matches_end_condition = - scan_html_block_end_3(&input, parser->first_nonspace); + scan_html_block_end_3(input, parser->first_nonspace); break; case 4: // > matches_end_condition = - scan_html_block_end_4(&input, parser->first_nonspace); + scan_html_block_end_4(input, parser->first_nonspace); break; case 5: // ]]> matches_end_condition = - scan_html_block_end_5(&input, parser->first_nonspace); + scan_html_block_end_5(input, parser->first_nonspace); break; default: matches_end_condition = 0; @@ -971,28 +1092,69 @@ container = finalize(parser, container); assert(parser->current != NULL); } - } else if (parser->blank) { - // ??? do nothing - } else if (accepts_lines(container->type)) { - if (container->type == CMARK_NODE_HEADING && container->as.heading.setext == false) { - chop_trailing_hashtags(&input); + chop_trailing_hashtags(input); } - add_line(container, &input, parser->first_nonspace); - + S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false); + add_line(container, input, parser); } else { // create paragraph container for line container = add_child(parser, container, CMARK_NODE_PARAGRAPH, parser->first_nonspace + 1); - add_line(container, &input, parser->first_nonspace); + S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false); + add_line(container, input, parser); } parser->current = container; } +} + +/* See http://spec.commonmark.org/0.24/#phase-1-block-structure */ +static void S_process_line(cmark_parser *parser, const unsigned char *buffer, + bufsize_t bytes) { + cmark_node *last_matched_container; + bool all_matched = true; + cmark_node *container; + cmark_chunk input; + + if (parser->options & CMARK_OPT_VALIDATE_UTF8) + cmark_utf8proc_check(parser->curline, buffer, bytes); + else + cmark_strbuf_put(parser->curline, buffer, bytes); + + // ensure line ends with a newline: + if (bytes == 0 || !S_is_line_end_char(parser->curline->ptr[bytes - 1])) + cmark_strbuf_putc(parser->curline, '\n'); + + parser->offset = 0; + parser->column = 0; + parser->blank = false; + parser->partially_consumed_tab = false; + + input.data = parser->curline->ptr; + input.len = parser->curline->size; + + parser->line_number++; + + last_matched_container = check_open_blocks(parser, &input, &all_matched); + + if (!last_matched_container) + goto finished; + + container = last_matched_container; + + // check to see if we've hit 2nd blank line, break out of list: + if (parser->blank && container->last_line_blank) + break_out_of_lists(parser, &container); + + open_new_blocks(parser, &container, &input, all_matched); + + add_text_to_container(parser, container, last_matched_container, &input); + finished: parser->last_line_length = input.len; if (parser->last_line_length && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/buffer.c new/cmark-0.5.2/cbits/buffer.c --- old/cmark-0.5.1/cbits/buffer.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/buffer.c 2016-03-26 21:36:02.000000000 +0100 @@ -33,7 +33,7 @@ abort(); } -static inline void S_strbuf_grow_by(cmark_strbuf *buf, size_t add) { +static CMARK_INLINE void S_strbuf_grow_by(cmark_strbuf *buf, size_t add) { size_t target_size = (size_t)buf->size + add; if (target_size < add /* Integer overflow. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/cmark.h new/cmark-0.5.2/cbits/cmark.h --- old/cmark-0.5.1/cbits/cmark.h 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/cmark.h 2016-03-26 21:36:02.000000000 +0100 @@ -20,7 +20,7 @@ */ /** Convert 'text' (assumed to be a UTF-8 encoded string with length - * 'len' from CommonMark Markdown to HTML, returning a null-terminated, + * 'len') from CommonMark Markdown to HTML, returning a null-terminated, * UTF-8-encoded string. */ CMARK_EXPORT @@ -96,7 +96,7 @@ */ CMARK_EXPORT cmark_node *cmark_node_new(cmark_node_type type); -/** Frees the memory allocated for a node. +/** Frees the memory allocated for a node and any children. */ CMARK_EXPORT void cmark_node_free(cmark_node *node); @@ -418,7 +418,7 @@ * Streaming interface: * * cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); - * FILE *fp = fopen("myfile.md", "r"); + * FILE *fp = fopen("myfile.md", "rb"); * while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { * cmark_parser_feed(parser, buffer, bytes); * if (bytes < sizeof(buffer)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/cmark_version.h new/cmark-0.5.2/cbits/cmark_version.h --- old/cmark-0.5.1/cbits/cmark_version.h 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/cmark_version.h 2016-03-26 21:36:02.000000000 +0100 @@ -1,7 +1,7 @@ #ifndef CMARK_VERSION_H #define CMARK_VERSION_H -#define CMARK_VERSION ((0 << 16) | (23 << 8) | 0) -#define CMARK_VERSION_STRING "0.23.0" +#define CMARK_VERSION ((0 << 16) | (25 << 8) | 2) +#define CMARK_VERSION_STRING "0.25.2" #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/commonmark.c new/cmark-0.5.2/cbits/commonmark.c --- old/cmark-0.5.1/cbits/commonmark.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/commonmark.c 2016-03-26 21:36:02.000000000 +0100 @@ -17,16 +17,17 @@ #define LIT(s) renderer->out(renderer, s, false, LITERAL) #define CR() renderer->cr(renderer) #define BLANKLINE() renderer->blankline(renderer) +#define ENCODED_SIZE 20 +#define LISTMARKER_SIZE 20 // Functions to convert cmark_nodes to commonmark strings. -static inline void outc(cmark_renderer *renderer, cmark_escaping escape, +static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape, int32_t c, unsigned char nextc) { bool needs_escaping = false; bool follows_digit = renderer->buffer->size > 0 && cmark_isdigit(renderer->buffer->ptr[renderer->buffer->size - 1]); - const size_t ENCODED_SIZE = 20; char encoded[ENCODED_SIZE]; needs_escaping = @@ -168,7 +169,6 @@ bool entering = (ev_type == CMARK_EVENT_ENTER); const char *info, *code, *title; size_t info_len, code_len; - const size_t LISTMARKER_SIZE = 20; char listmarker[LISTMARKER_SIZE]; char *emph_delim; bufsize_t marker_width; @@ -273,8 +273,8 @@ // begin or end with a blank line, and code isn't // first thing in a list item if (info_len == 0 && - (code_len > 2 && !isspace(code[0]) && - !(isspace(code[code_len - 1]) && isspace(code[code_len - 2]))) && + (code_len > 2 && !isspace((unsigned char)code[0]) && + !(isspace((unsigned char)code[code_len - 1]) && isspace((unsigned char)code[code_len - 2]))) && !(node->prev == NULL && node->parent && node->parent->type == CMARK_NODE_ITEM)) { LIT(" "); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/config.h new/cmark-0.5.2/cbits/config.h --- old/cmark-0.5.1/cbits/config.h 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/config.h 2016-03-26 21:36:02.000000000 +0100 @@ -1,3 +1,10 @@ +#ifndef CMARK_CONFIG_H +#define CMARK_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + #define HAVE_STDBOOL_H #ifdef HAVE_STDBOOL_H @@ -23,3 +30,47 @@ #define CMARK_INLINE inline #endif #endif + +/* snprintf and vsnprintf fallbacks for MSVC before 2015, + due to Valentin Milea http://stackoverflow.com/questions/2915672/ +*/ + +#if defined(_MSC_VER) && _MSC_VER < 1900 + +#include <stdio.h> +#include <stdarg.h> + +#define snprintf c99_snprintf +#define vsnprintf c99_vsnprintf + +CMARK_INLINE int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) +{ + int count = -1; + + if (size != 0) + count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + if (count == -1) + count = _vscprintf(format, ap); + + return count; +} + +CMARK_INLINE int c99_snprintf(char *outBuf, size_t size, const char *format, ...) +{ + int count; + va_list ap; + + va_start(ap, format); + count = c99_vsnprintf(outBuf, size, format, ap); + va_end(ap); + + return count; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/html.c new/cmark-0.5.2/cbits/html.c --- old/cmark-0.5.1/cbits/html.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/html.c 2016-03-26 21:36:02.000000000 +0100 @@ -10,6 +10,8 @@ #include "houdini.h" #include "scanners.h" +#define BUFFER_SIZE 100 + // Functions to convert cmark_nodes to HTML strings. static void escape_html(cmark_strbuf *dest, const unsigned char *source, @@ -17,7 +19,7 @@ houdini_escape_html0(dest, source, length, 0); } -static inline void cr(cmark_strbuf *html) { +static CMARK_INLINE void cr(cmark_strbuf *html) { if (html->size && html->ptr[html->size - 1] != '\n') cmark_strbuf_putc(html, '\n'); } @@ -29,7 +31,6 @@ static void S_render_sourcepos(cmark_node *node, cmark_strbuf *html, int options) { - const size_t BUFFER_SIZE = 100; char buffer[BUFFER_SIZE]; if (CMARK_OPT_SOURCEPOS & options) { snprintf(buffer, BUFFER_SIZE, " data-sourcepos=\"%d:%d-%d:%d\"", @@ -47,7 +48,6 @@ char start_heading[] = "<h0"; char end_heading[] = "</h0"; bool tight; - const size_t BUFFER_SIZE = 100; char buffer[BUFFER_SIZE]; bool entering = (ev_type == CMARK_EVENT_ENTER); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/inlines.c new/cmark-0.5.2/cbits/inlines.c --- old/cmark-0.5.1/cbits/inlines.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/inlines.c 2016-03-26 21:36:02.000000000 +0100 @@ -48,7 +48,7 @@ delimiter *last_delim; } subject; -static inline bool S_is_line_end_char(char c) { +static CMARK_INLINE bool S_is_line_end_char(char c) { return (c == '\n' || c == '\r'); } @@ -62,7 +62,7 @@ static bufsize_t subject_find_special_char(subject *subj, int options); // Create an inline with a literal string value. -static inline cmark_node *make_literal(cmark_node_type t, cmark_chunk s) { +static CMARK_INLINE cmark_node *make_literal(cmark_node_type t, cmark_chunk s) { cmark_node *e = (cmark_node *)calloc(1, sizeof(*e)); if (e != NULL) { e->type = t; @@ -81,7 +81,7 @@ } // Create an inline with no value. -static inline cmark_node *make_simple(cmark_node_type t) { +static CMARK_INLINE cmark_node *make_simple(cmark_node_type t) { cmark_node *e = (cmark_node *)calloc(1, sizeof(*e)); if (e != NULL) { e->type = t; @@ -141,7 +141,7 @@ return cmark_chunk_buf_detach(&buf); } -static inline cmark_node *make_autolink(cmark_chunk url, int is_email) { +static CMARK_INLINE cmark_node *make_autolink(cmark_chunk url, int is_email) { cmark_node *link = make_simple(CMARK_NODE_LINK); link->as.link.url = cmark_clean_autolink(&url, is_email); link->as.link.title = cmark_chunk_literal(""); @@ -159,28 +159,28 @@ e->last_delim = NULL; } -static inline int isbacktick(int c) { return (c == '`'); } +static CMARK_INLINE int isbacktick(int c) { return (c == '`'); } -static inline unsigned char peek_char(subject *subj) { +static CMARK_INLINE unsigned char peek_char(subject *subj) { // NULL bytes should have been stripped out by now. If they're // present, it's a programming error: assert(!(subj->pos < subj->input.len && subj->input.data[subj->pos] == 0)); return (subj->pos < subj->input.len) ? subj->input.data[subj->pos] : 0; } -static inline unsigned char peek_at(subject *subj, bufsize_t pos) { +static CMARK_INLINE unsigned char peek_at(subject *subj, bufsize_t pos) { return subj->input.data[pos]; } // Return true if there are more characters in the subject. -static inline int is_eof(subject *subj) { +static CMARK_INLINE int is_eof(subject *subj) { return (subj->pos >= subj->input.len); } // Advance the subject. Doesn't check for eof. #define advance(subj) (subj)->pos += 1 -static inline bool skip_spaces(subject *subj) { +static CMARK_INLINE bool skip_spaces(subject *subj) { bool skipped = false; while (peek_char(subj) == ' ' || peek_char(subj) == '\t') { advance(subj); @@ -189,7 +189,7 @@ return skipped; } -static inline bool skip_line_end(subject *subj) { +static CMARK_INLINE bool skip_line_end(subject *subj) { bool seen_line_end_char = false; if (peek_char(subj) == '\r') { advance(subj); @@ -203,7 +203,7 @@ } // Take characters while a predicate holds, and return a string. -static inline cmark_chunk take_while(subject *subj, int (*f)(int)) { +static CMARK_INLINE cmark_chunk take_while(subject *subj, int (*f)(int)) { unsigned char c; bufsize_t startpos = subj->pos; bufsize_t len = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/latex.c new/cmark-0.5.2/cbits/latex.c --- old/cmark-0.5.1/cbits/latex.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/latex.c 2016-03-26 21:36:02.000000000 +0100 @@ -17,8 +17,9 @@ #define LIT(s) renderer->out(renderer, s, false, LITERAL) #define CR() renderer->cr(renderer) #define BLANKLINE() renderer->blankline(renderer) +#define LIST_NUMBER_STRING_SIZE 20 -static inline void outc(cmark_renderer *renderer, cmark_escaping escape, +static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape, int32_t c, unsigned char nextc) { if (escape == LITERAL) { cmark_render_code_point(renderer, c); @@ -217,7 +218,6 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node, cmark_event_type ev_type, int options) { int list_number; - const size_t LIST_NUMBER_STRING_SIZE = 20; char list_number_string[LIST_NUMBER_STRING_SIZE]; bool entering = (ev_type == CMARK_EVENT_ENTER); cmark_list_type list_type; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/man.c new/cmark-0.5.2/cbits/man.c --- old/cmark-0.5.1/cbits/man.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/man.c 2016-03-26 21:36:02.000000000 +0100 @@ -14,6 +14,7 @@ #define LIT(s) renderer->out(renderer, s, false, LITERAL) #define CR() renderer->cr(renderer) #define BLANKLINE() renderer->blankline(renderer) +#define LIST_NUMBER_SIZE 20 // Functions to convert cmark_nodes to groff man strings. static void S_outc(cmark_renderer *renderer, cmark_escaping escape, int32_t c, @@ -110,7 +111,6 @@ tmp = tmp->prev; list_number += 1; } - const size_t LIST_NUMBER_SIZE = 20; char list_number_s[LIST_NUMBER_SIZE]; snprintf(list_number_s, LIST_NUMBER_SIZE, "\"%d.\" 4", list_number); LIT(list_number_s); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/node.c new/cmark-0.5.2/cbits/node.c --- old/cmark-0.5.1/cbits/node.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/node.c 2016-03-26 21:36:02.000000000 +0100 @@ -6,7 +6,7 @@ static void S_node_unlink(cmark_node *node); -static inline bool S_is_block(cmark_node *node) { +static CMARK_INLINE bool S_is_block(cmark_node *node) { if (node == NULL) { return false; } @@ -14,7 +14,7 @@ node->type <= CMARK_NODE_LAST_BLOCK; } -static inline bool S_is_inline(cmark_node *node) { +static CMARK_INLINE bool S_is_inline(cmark_node *node) { if (node == NULL) { return false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/parser.h new/cmark-0.5.2/cbits/parser.h --- old/cmark-0.5.1/cbits/parser.h 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/parser.h 2016-03-26 21:36:02.000000000 +0100 @@ -22,10 +22,12 @@ bufsize_t first_nonspace_column; int indent; bool blank; + bool partially_consumed_tab; cmark_strbuf *curline; bufsize_t last_line_length; cmark_strbuf *linebuf; int options; + bool last_buffer_ended_with_cr; }; #ifdef __cplusplus diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/render.c new/cmark-0.5.2/cbits/render.c --- old/cmark-0.5.1/cbits/render.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/render.c 2016-03-26 21:36:02.000000000 +0100 @@ -5,13 +5,13 @@ #include "utf8.h" #include "render.h" -static inline void S_cr(cmark_renderer *renderer) { +static CMARK_INLINE void S_cr(cmark_renderer *renderer) { if (renderer->need_cr < 1) { renderer->need_cr = 1; } } -static inline void S_blankline(cmark_renderer *renderer) { +static CMARK_INLINE void S_blankline(cmark_renderer *renderer) { if (renderer->need_cr < 2) { renderer->need_cr = 2; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cbits/xml.c new/cmark-0.5.2/cbits/xml.c --- old/cmark-0.5.1/cbits/xml.c 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cbits/xml.c 2016-03-26 21:36:02.000000000 +0100 @@ -9,6 +9,8 @@ #include "buffer.h" #include "houdini.h" +#define BUFFER_SIZE 100 + // Functions to convert cmark_nodes to XML strings. static void escape_xml(cmark_strbuf *dest, const unsigned char *source, @@ -21,7 +23,7 @@ int indent; }; -static inline void indent(struct render_state *state) { +static CMARK_INLINE void indent(struct render_state *state) { int i; for (i = 0; i < state->indent; i++) { cmark_strbuf_putc(state->xml, ' '); @@ -34,7 +36,6 @@ bool literal = false; cmark_delim_type delim; bool entering = (ev_type == CMARK_EVENT_ENTER); - const size_t BUFFER_SIZE = 100; char buffer[BUFFER_SIZE]; if (entering) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/changelog new/cmark-0.5.2/changelog --- old/cmark-0.5.1/changelog 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/changelog 2016-03-26 21:36:02.000000000 +0100 @@ -1,3 +1,8 @@ +cmark 0.5.2 (26 Mar 2016) + + * Add flag to allow building with an installed libcmark (Jens Petersen). + * Updated to libcmark 0.25.2. + cmark 0.5.1 (21 Jan 2016) * Updated to libcmark 0.24.1. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cmark-0.5.1/cmark.cabal new/cmark-0.5.2/cmark.cabal --- old/cmark-0.5.1/cmark.cabal 2016-01-23 06:14:38.000000000 +0100 +++ new/cmark-0.5.2/cmark.cabal 2016-03-26 21:36:02.000000000 +0100 @@ -1,12 +1,12 @@ name: cmark -version: 0.5.1 +version: 0.5.2 synopsis: Fast, accurate CommonMark (Markdown) parser and renderer description: This package provides Haskell bindings for <https://github.com/jgm/cmark libcmark>, the reference parser for <http://commonmark.org CommonMark>, a fully specified variant of Markdown. It includes sources for - libcmark (0.24.1) and does not require prior installation of the + libcmark (0.25.2) and does not require prior installation of the C library. homepage: https://github.com/jgm/commonmark-hs @@ -16,7 +16,7 @@ maintainer: jgm@berkeley.edu copyright: (C) 2015 John MacFarlane category: Text -tested-with: GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.2 +tested-with: GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.2, GHC == 7.10.3 build-type: Simple extra-source-files: README.md changelog @@ -48,6 +48,10 @@ type: git location: git://github.com/jgm/cmark-hs.git +flag pkgconfig + default: False + description: Use system libcmark via pkgconfig + library exposed-modules: CMark build-depends: base >=4.5 && < 4.9, @@ -57,10 +61,13 @@ build-depends: ghc-prim >= 0.2 default-language: Haskell2010 ghc-options: -Wall -fno-warn-unused-do-bind - cc-options: -Wall -std=c99 - Include-dirs: cbits - Includes: cmark.h - c-sources: cbits/houdini_html_u.c + if flag(pkgconfig) + pkgconfig-depends: libcmark + else + cc-options: -Wall -std=c99 + Include-dirs: cbits + Includes: cmark.h + c-sources: cbits/houdini_html_u.c cbits/references.c cbits/utf8.c cbits/inlines.c
participants (1)
-
root@hilbert.suse.de