aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast.c120
-rw-r--r--src/ast.h37
-rw-r--r--src/inlines.c130
-rw-r--r--src/inlines.h6
4 files changed, 158 insertions, 135 deletions
diff --git a/src/ast.c b/src/ast.c
index 2a9ca8f..6e3f0ee 100644
--- 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
index 5c3d298..952be8f 100644
--- 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
index 5b7b8ea..78ebaf4 100644
--- 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
index fa61c8a..57daea2 100644
--- 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