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...@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:          j...@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


Reply via email to