cmark

My personal build of CMark ✏️

Commit
c589d7345a311b54d5a642759820a254e129e4ff
Parent
5d2203a948944d980d580ceab7c9c373fd9d657d
Author
John MacFarlane <jgm@berkeley.edu>
Date

Moved ast-manipulating functions from inlines to ast.

Diffstat

4 files changed, 158 insertions, 135 deletions

Status File Name N° Changes Insertions Deletions
Modified src/ast.c 120 102 18
Modified src/ast.h 37 35 2
Modified src/inlines.c 130 19 111
Modified src/inlines.h 6 2 4
diff --git a/src/ast.c b/src/ast.c
@@ -3,17 +3,18 @@
 #include "buffer.h"
 #include "ast.h"
 #include "references.h"
+#include "html/houdini.h"
 
 // Free a node_block list and any children.
-void cmark_free_blocks(node_block *e)
+void cmark_free_blocks(cmark_node_block *e)
 {
-	node_block * next;
+	cmark_node_block * next;
 	while (e != NULL) {
-		free_inlines(e->inline_content);
+		cmark_free_inlines(e->inline_content);
 		strbuf_free(&e->string_content);
-		if (e->tag == BLOCK_FENCED_CODE) {
+		if (e->tag == CMARK_BLOCK_FENCED_CODE) {
 			strbuf_free(&e->as.code.info);
-		} else if (e->tag == BLOCK_DOCUMENT) {
+		} else if (e->tag == CMARK_BLOCK_DOCUMENT) {
 			reference_map_free(e->as.document.refmap);
 		}
 		if (e->last_child) {
@@ -28,8 +29,8 @@ void cmark_free_blocks(node_block *e)
 }
 
 // Utility function used by free_inlines
-static void splice_into_list(node_inl* e, node_inl* children) {
-	node_inl * tmp;
+static void splice_into_list(cmark_node_inl* e, node_inl* children) {
+	cmark_node_inl * tmp;
 	if (children) {
 		tmp = children;
 		// Find last child
@@ -45,28 +46,28 @@ static void splice_into_list(node_inl* e, node_inl* children) {
 
 // Free an inline list.  Avoid recursion to prevent stack overflows
 // on deeply nested structures.
-extern void free_inlines(node_inl* e)
+void cmark_free_inlines(cmark_node_inl* e)
 {
 	node_inl * next;
 
 	while (e != NULL) {
 		switch (e->tag){
-		case INL_STRING:
-		case INL_RAW_HTML:
-		case INL_CODE:
-			chunk_free(&e->content.literal);
+		case CMARK_INL_STRING:
+		case CMARK_INL_RAW_HTML:
+		case CMARK_INL_CODE:
+			cmark_chunk_free(&e->content.literal);
 			break;
-		case INL_LINEBREAK:
-		case INL_SOFTBREAK:
+		case CMARK_INL_LINEBREAK:
+		case CMARK_INL_SOFTBREAK:
 			break;
-		case INL_LINK:
-		case INL_IMAGE:
+		case CMARK_INL_LINK:
+		case CMARK_INL_IMAGE:
 			free(e->content.linkable.url);
 			free(e->content.linkable.title);
 			splice_into_list(e, e->content.linkable.label);
 			break;
-		case INL_EMPH:
-		case INL_STRONG:
+		case CMARK_INL_EMPH:
+		case CMARK_INL_STRONG:
 		        splice_into_list(e, e->content.inlines);
 			break;
 		default:
@@ -79,3 +80,86 @@ extern void free_inlines(node_inl* e)
 		e = next;
 	}
 }
+
+inline cmark_node_inl *cmark_make_link(cmark_node_inl *label, unsigned char *url, unsigned char *title)
+{
+	cmark_node_inl* e = calloc(1, sizeof(*e));
+	if(e != NULL) {
+		e->tag = CMARK_INL_LINK;
+		e->content.linkable.label = label;
+		e->content.linkable.url   = url;
+		e->content.linkable.title = title;
+		e->next = NULL;
+	}
+	return e;
+}
+
+unsigned char *clean_autolink(chunk *url, int is_email)
+{
+	strbuf buf = GH_BUF_INIT;
+
+	chunk_trim(url);
+
+	if (url->len == 0)
+		return NULL;
+
+	if (is_email)
+		strbuf_puts(&buf, "mailto:");
+
+	houdini_unescape_html_f(&buf, url->data, url->len);
+	return strbuf_detach(&buf);
+}
+
+cmark_node_inl* cmark_make_autolink(cmark_node_inl* label, chunk url, int is_email)
+{
+	return cmark_make_link(label, clean_autolink(&url, is_email), NULL);
+}
+
+inline cmark_node_inl* cmark_make_inlines(int t, cmark_node_inl* contents)
+{
+	cmark_node_inl * e = calloc(1, sizeof(*e));
+	if(e != NULL) {
+		e->tag = t;
+		e->content.inlines = contents;
+		e->next = NULL;
+	}
+	return e;
+}
+
+// Create an inline with a literal string value.
+inline cmark_node_inl* cmark_make_literal(int t, cmark_chunk s)
+{
+	cmark_node_inl * e = calloc(1, sizeof(*e));
+	if(e != NULL) {
+		e->tag = t;
+		e->content.literal = s;
+		e->next = NULL;
+	}
+	return e;
+}
+
+// Create an inline with no value.
+inline cmark_node_inl* cmark_make_simple(int t)
+{
+	cmark_node_inl* e = calloc(1, sizeof(*e));
+	if(e != NULL) {
+		e->tag = t;
+		e->next = NULL;
+	}
+	return e;
+}
+
+// Append inline list b to the end of inline list a.
+// Return pointer to head of new list.
+inline cmark_node_inl* cmark_append_inlines(cmark_node_inl* a, cmark_node_inl* b)
+{
+	if (a == NULL) {  // NULL acts like an empty list
+		return b;
+	}
+	cmark_node_inl* cur = a;
+	while (cur->next) {
+		cur = cur->next;
+	}
+	cur->next = b;
+	return a;
+}
diff --git a/src/ast.h b/src/ast.h
@@ -102,7 +102,27 @@ struct cmark_node_block {
 typedef struct cmark_node_block cmark_node_block;
 
 void cmark_free_blocks(cmark_node_block *e);
-void cmark_free_inlines(cmark_node_inl *e);
+void cmark_free_inlines(cmark_node_inl* e);
+void cmark_free_simple(cmark_node_inl *e);
+cmark_node_inl* cmark_append_inlines(cmark_node_inl* a, cmark_node_inl* b);
+
+cmark_node_inl *cmark_make_link(cmark_node_inl *label, unsigned char *url, unsigned char *title);
+cmark_node_inl* cmark_make_autolink(cmark_node_inl* label, cmark_chunk url, int is_email);
+
+cmark_node_inl* cmark_make_inlines(int t, cmark_node_inl* contents);
+cmark_node_inl* cmark_make_literal(int t, cmark_chunk s);
+cmark_node_inl* cmark_make_simple(int t);
+
+// Macros for creating various kinds of simple.
+#define cmark_make_str(s) cmark_make_literal(INL_STRING, s)
+#define cmark_make_code(s) cmark_make_literal(INL_CODE, s)
+#define cmark_make_raw_html(s) cmark_make_literal(INL_RAW_HTML, s)
+#define cmark_make_linebreak() cmark_make_simple(INL_LINEBREAK)
+#define cmark_make_softbreak() cmark_make_simple(INL_SOFTBREAK)
+#define cmark_make_emph(contents) cmark_make_inlines(INL_EMPH, contents)
+#define cmark_make_strong(contents) cmark_make_inlines(INL_STRONG, contents)
+
+
 
 #ifndef CMARK_NO_SHORT_NAMES
   #define node_inl                  cmark_node_inl
@@ -130,8 +150,21 @@ void cmark_free_inlines(cmark_node_inl *e);
   #define BLOCK_SETEXT_HEADER       CMARK_BLOCK_SETEXT_HEADER
   #define BLOCK_HRULE               CMARK_BLOCK_HRULE
   #define BLOCK_REFERENCE_DEF       CMARK_BLOCK_REFERENCE_DEF
-  #define free_inlines              cmark_free_inlines
+  #define free_simple               cmark_free_simple
   #define free_blocks               cmark_free_blocks
+  #define append_simple             cmark_append_simple
+  #define make_link                 cmark_make_link
+  #define make_autolink             cmark_make_autolink
+  #define make_str                  cmark_make_str
+  #define make_code                 cmark_make_code
+  #define make_raw_html             cmark_make_raw_html
+  #define make_linebreak            cmark_make_linebreak
+  #define make_softbreak            cmark_make_softbreak
+  #define make_emph                 cmark_make_emph
+  #define make_strong               cmark_make_strong
+  #define make_simple              cmark_make_simple
+  #define make_simple              cmark_make_simple
+  #define make_simple              cmark_make_simple
 #endif
 
 #endif
diff --git a/src/inlines.c b/src/inlines.c
@@ -8,6 +8,7 @@
 #include "html/houdini.h"
 #include "utf8.h"
 #include "scanners.h"
+#include "ast.h"
 #include "inlines.h"
 
 
@@ -50,82 +51,6 @@ static unsigned char *bufdup(const unsigned char *buf)
 	return new;
 }
 
-static inline node_inl *make_link_(node_inl *label, unsigned char *url, unsigned char *title)
-{
-	node_inl* e = calloc(1, sizeof(*e));
-	if(e != NULL) {
-		e->tag = INL_LINK;
-		e->content.linkable.label = label;
-		e->content.linkable.url   = url;
-		e->content.linkable.title = title;
-		e->next = NULL;
-	}
-	return e;
-}
-
-static inline node_inl* make_autolink(node_inl* label, chunk url, int is_email)
-{
-	return make_link_(label, clean_autolink(&url, is_email), NULL);
-}
-
-static inline node_inl* make_inlines(int t, node_inl* contents)
-{
-	node_inl * e = calloc(1, sizeof(*e));
-	if(e != NULL) {
-		e->tag = t;
-		e->content.inlines = contents;
-		e->next = NULL;
-	}
-	return e;
-}
-
-// Create an inline with a literal string value.
-static inline node_inl* make_literal(int t, chunk s)
-{
-	node_inl * e = calloc(1, sizeof(*e));
-	if(e != NULL) {
-		e->tag = t;
-		e->content.literal = s;
-		e->next = NULL;
-	}
-	return e;
-}
-
-// Create an inline with no value.
-static inline node_inl* make_simple(int t)
-{
-	node_inl* e = calloc(1, sizeof(*e));
-	if(e != NULL) {
-		e->tag = t;
-		e->next = NULL;
-	}
-	return e;
-}
-
-// Macros for creating various kinds of inlines.
-#define make_str(s) make_literal(INL_STRING, s)
-#define make_code(s) make_literal(INL_CODE, s)
-#define make_raw_html(s) make_literal(INL_RAW_HTML, s)
-#define make_linebreak() make_simple(INL_LINEBREAK)
-#define make_softbreak() make_simple(INL_SOFTBREAK)
-#define make_emph(contents) make_inlines(INL_EMPH, contents)
-#define make_strong(contents) make_inlines(INL_STRONG, contents)
-
-// Append inline list b to the end of inline list a.
-// Return pointer to head of new list.
-static inline node_inl* append_inlines(node_inl* a, node_inl* b)
-{
-	if (a == NULL) {  // NULL acts like an empty list
-		return b;
-	}
-	node_inl* cur = a;
-	while (cur->next) {
-		cur = cur->next;
-	}
-	cur->next = b;
-	return a;
-}
-
 static void subject_from_buf(subject *e, strbuf *buffer, reference_map *refmap)
 {
 	e->input.data = buffer->ptr;
@@ -402,7 +327,7 @@ static void process_emphasis(subject *subj, delimiter_stack *stack_bottom)
 					tmp = closer->first_inline;
 					emph->next = tmp->next;
 					tmp->next = NULL;
-					free_inlines(tmp);
+					cmark_free_inlines(tmp);
 					// remove closer from stack
 					tempstack = closer->next;
 					remove_delimiter(subj, closer);
@@ -492,45 +417,28 @@ unsigned char *clean_url(chunk *url)
 	return strbuf_detach(&buf);
 }
 
-unsigned char *clean_autolink(chunk *url, int is_email)
-{
-	strbuf buf = GH_BUF_INIT;
-
-	chunk_trim(url);
-
-	if (url->len == 0)
-		return NULL;
-
-	if (is_email)
-		strbuf_puts(&buf, "mailto:");
-
-	houdini_unescape_html_f(&buf, url->data, url->len);
-	return strbuf_detach(&buf);
-}
-
-// Clean a title: remove surrounding quotes and remove \ that escape punctuation.
 unsigned char *clean_title(chunk *title)
 {
-	strbuf buf = GH_BUF_INIT;
-	unsigned char first, last;
+       strbuf buf = GH_BUF_INIT;
+       unsigned char first, last;
 
-	if (title->len == 0)
-		return NULL;
+       if (title->len == 0)
+               return NULL;
 
-	first = title->data[0];
-	last = title->data[title->len - 1];
+       first = title->data[0];
+       last = title->data[title->len - 1];
 
-	// remove surrounding quotes if any:
-	if ((first == '\'' && last == '\'') ||
-	    (first == '(' && last == ')') ||
-	    (first == '"' && last == '"')) {
-		houdini_unescape_html_f(&buf, title->data + 1, title->len - 2);
-	} else {
-		houdini_unescape_html_f(&buf, title->data, title->len);
-	}
+       // remove surrounding quotes if any:
+       if ((first == '\'' && last == '\'') ||
+           (first == '(' && last == ')') ||
+           (first == '"' && last == '"')) {
+               houdini_unescape_html_f(&buf, title->data + 1, title->len - 2);
+       } else {
+               houdini_unescape_html_f(&buf, title->data, title->len);
+       }
 
-	strbuf_unescape(&buf);
-	return strbuf_detach(&buf);
+       strbuf_unescape(&buf);
+       return strbuf_detach(&buf);
 }
 
 // Parse an autolink or HTML tag.
@@ -880,7 +788,7 @@ static int parse_inline(subject* subj, node_inl ** last)
 	if (*last == NULL) {
 		*last = new;
 	} else if (new) {
-		append_inlines(*last, new);
+		cmark_append_inlines(*last, new);
 		*last = new;
 	}
 
diff --git a/src/inlines.h b/src/inlines.h
@@ -2,7 +2,6 @@
 #define _INLINES_H_
 
 unsigned char *cmark_clean_url(cmark_chunk *url);
-unsigned char *cmark_clean_autolink(cmark_chunk *url, int is_email);
 unsigned char *cmark_clean_title(cmark_chunk *title);
 
 cmark_node_inl* cmark_parse_inlines(cmark_strbuf *input, cmark_reference_map *refmap);
@@ -10,11 +9,10 @@ cmark_node_inl* cmark_parse_inlines(cmark_strbuf *input, cmark_reference_map *re
 int cmark_parse_reference_inline(cmark_strbuf *input, cmark_reference_map *refmap);
 
 #ifndef CMARK_NO_SHORT_NAMES
-  #define clean_url                 cmark_clean_url
-  #define clean_autolink            cmark_clean_autolink
-  #define clean_title               cmark_clean_title
   #define parse_inlines             cmark_parse_inlines
   #define parse_reference_inline    cmark_parse_reference_inline
+  #define clean_url                 cmark_clean_url
+  #define clean_title               cmark_clean_title
 #endif
 
 #endif