diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/ast.c | 165 | ||||
-rw-r--r-- | src/ast.h | 170 | ||||
-rw-r--r-- | src/cmark.c | 163 | ||||
-rw-r--r-- | src/cmark.h | 160 | ||||
-rw-r--r-- | src/inlines.c | 1 | ||||
-rw-r--r-- | src/references.c | 1 | ||||
-rw-r--r-- | src/references.h | 2 |
8 files changed, 324 insertions, 340 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3157bd1..e95422c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 2.8) set(LIBRARY "cmark-shared") set(HEADERS cmark.h - ast.h buffer.h chunk.h references.h @@ -16,7 +15,6 @@ set(HEADERS ) set(LIBRARY_SOURCES cmark.c - ast.c blocks.c inlines.c print.c diff --git a/src/ast.c b/src/ast.c deleted file mode 100644 index 6e3f0ee..0000000 --- a/src/ast.c +++ /dev/null @@ -1,165 +0,0 @@ -#include <stdbool.h> -#include <stdio.h> -#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(cmark_node_block *e) -{ - cmark_node_block * next; - while (e != NULL) { - cmark_free_inlines(e->inline_content); - strbuf_free(&e->string_content); - if (e->tag == CMARK_BLOCK_FENCED_CODE) { - strbuf_free(&e->as.code.info); - } else if (e->tag == CMARK_BLOCK_DOCUMENT) { - reference_map_free(e->as.document.refmap); - } - if (e->last_child) { - // Splice children into list - e->last_child->next = e->next; - e->next = e->children; - } - next = e->next; - free(e); - e = next; - } -} - -// Utility function used by free_inlines -static void splice_into_list(cmark_node_inl* e, node_inl* children) { - cmark_node_inl * tmp; - if (children) { - tmp = children; - // Find last child - while (tmp->next) { - tmp = tmp->next; - } - // Splice children into list - tmp->next = e->next; - e->next = children; - } - return ; -} - -// Free an inline list. Avoid recursion to prevent stack overflows -// on deeply nested structures. -void cmark_free_inlines(cmark_node_inl* e) -{ - node_inl * next; - - while (e != NULL) { - switch (e->tag){ - case CMARK_INL_STRING: - case CMARK_INL_RAW_HTML: - case CMARK_INL_CODE: - cmark_chunk_free(&e->content.literal); - break; - case CMARK_INL_LINEBREAK: - case CMARK_INL_SOFTBREAK: - break; - 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 CMARK_INL_EMPH: - case CMARK_INL_STRONG: - splice_into_list(e, e->content.inlines); - break; - default: - fprintf(stderr, "[WARN] (%s:%d) Unknown inline tag %d", - __FILE__, __LINE__, e->tag); - break; - } - next = e->next; - free(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 deleted file mode 100644 index 952be8f..0000000 --- a/src/ast.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef _AST_H_ -#define _AST_H_ - -#include <stdbool.h> -#include <stdio.h> -#include "buffer.h" -#include "chunk.h" -#include "references.h" - -struct cmark_node_inl { - enum { - CMARK_INL_STRING, - CMARK_INL_SOFTBREAK, - CMARK_INL_LINEBREAK, - CMARK_INL_CODE, - CMARK_INL_RAW_HTML, - CMARK_INL_EMPH, - CMARK_INL_STRONG, - CMARK_INL_LINK, - CMARK_INL_IMAGE - } tag; - union { - cmark_chunk literal; - struct cmark_node_inl *inlines; - struct { - struct cmark_node_inl *label; - unsigned char *url; - unsigned char *title; - } linkable; - } content; - struct cmark_node_inl *next; -}; - -typedef struct cmark_node_inl cmark_node_inl; - -// Types for blocks -struct cmark_ListData { - enum { - bullet, - ordered - } list_type; - int marker_offset; - int padding; - int start; - enum { - period, - parens - } delimiter; - unsigned char bullet_char; - bool tight; -}; - -struct cmark_FencedCodeData { - int fence_length; - int fence_offset; - unsigned char fence_char; - cmark_strbuf info; -}; - -struct cmark_node_block { - enum { - CMARK_BLOCK_DOCUMENT, - CMARK_BLOCK_BQUOTE, - CMARK_BLOCK_LIST, - CMARK_BLOCK_LIST_ITEM, - CMARK_BLOCK_FENCED_CODE, - CMARK_BLOCK_INDENTED_CODE, - CMARK_BLOCK_HTML, - CMARK_BLOCK_PARAGRAPH, - CMARK_BLOCK_ATX_HEADER, - CMARK_BLOCK_SETEXT_HEADER, - CMARK_BLOCK_HRULE, - CMARK_BLOCK_REFERENCE_DEF - } tag; - int start_line; - int start_column; - int end_line; - bool open; - bool last_line_blank; - struct cmark_node_block* children; - struct cmark_node_block* last_child; - struct cmark_node_block* parent; - struct cmark_node_block* top; - cmark_strbuf string_content; - cmark_node_inl* inline_content; - - union { - struct cmark_ListData list; - struct cmark_FencedCodeData code; - struct { - int level; - } header; - struct { - cmark_reference_map *refmap; - } document; - } as; - - struct cmark_node_block *next; - struct cmark_node_block *prev; -}; - -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_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 - #define INL_STRING CMARK_INL_STRING - #define INL_SOFTBREAK CMARK_INL_SOFTBREAK - #define INL_LINEBREAK CMARK_INL_LINEBREAK - #define INL_CODE CMARK_INL_CODE - #define INL_RAW_HTML CMARK_INL_RAW_HTML - #define INL_EMPH CMARK_INL_EMPH - #define INL_STRONG CMARK_INL_STRONG - #define INL_LINK CMARK_INL_LINK - #define INL_IMAGE CMARK_INL_IMAGE - #define ListData cmark_ListData - #define FencedCodeData cmark_FencedCodeData - #define node_block cmark_node_block - #define BLOCK_DOCUMENT CMARK_BLOCK_DOCUMENT - #define BLOCK_BQUOTE CMARK_BLOCK_BQUOTE - #define BLOCK_LIST CMARK_BLOCK_LIST - #define BLOCK_LIST_ITEM CMARK_BLOCK_LIST_ITEM - #define BLOCK_FENCED_CODE CMARK_BLOCK_FENCED_CODE - #define BLOCK_INDENTED_CODE CMARK_BLOCK_INDENTED_CODE - #define BLOCK_HTML CMARK_BLOCK_HTML - #define BLOCK_PARAGRAPH CMARK_BLOCK_PARAGRAPH - #define BLOCK_ATX_HEADER CMARK_BLOCK_ATX_HEADER - #define BLOCK_SETEXT_HEADER CMARK_BLOCK_SETEXT_HEADER - #define BLOCK_HRULE CMARK_BLOCK_HRULE - #define BLOCK_REFERENCE_DEF CMARK_BLOCK_REFERENCE_DEF - #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/cmark.c b/src/cmark.c index 8f5c4e8..eacf411 100644 --- a/src/cmark.c +++ b/src/cmark.c @@ -1,7 +1,9 @@ #include <stdlib.h> #include <assert.h> #include <stdio.h> - +#include <stdbool.h> +#include "references.h" +#include "html/houdini.h" #include "cmark.h" #include "buffer.h" @@ -21,3 +23,162 @@ extern unsigned char *cmark_markdown_to_html(unsigned char *text, int len) return result; } + +// Free a node_block list and any children. +void cmark_free_blocks(cmark_node_block *e) +{ + cmark_node_block * next; + while (e != NULL) { + cmark_free_inlines(e->inline_content); + strbuf_free(&e->string_content); + if (e->tag == CMARK_BLOCK_FENCED_CODE) { + strbuf_free(&e->as.code.info); + } else if (e->tag == CMARK_BLOCK_DOCUMENT) { + reference_map_free(e->as.document.refmap); + } + if (e->last_child) { + // Splice children into list + e->last_child->next = e->next; + e->next = e->children; + } + next = e->next; + free(e); + e = next; + } +} + +// Utility function used by free_inlines +static void splice_into_list(cmark_node_inl* e, node_inl* children) { + cmark_node_inl * tmp; + if (children) { + tmp = children; + // Find last child + while (tmp->next) { + tmp = tmp->next; + } + // Splice children into list + tmp->next = e->next; + e->next = children; + } + return ; +} + +// Free an inline list. Avoid recursion to prevent stack overflows +// on deeply nested structures. +void cmark_free_inlines(cmark_node_inl* e) +{ + node_inl * next; + + while (e != NULL) { + switch (e->tag){ + case CMARK_INL_STRING: + case CMARK_INL_RAW_HTML: + case CMARK_INL_CODE: + cmark_chunk_free(&e->content.literal); + break; + case CMARK_INL_LINEBREAK: + case CMARK_INL_SOFTBREAK: + break; + 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 CMARK_INL_EMPH: + case CMARK_INL_STRONG: + splice_into_list(e, e->content.inlines); + break; + default: + fprintf(stderr, "[WARN] (%s:%d) Unknown inline tag %d", + __FILE__, __LINE__, e->tag); + break; + } + next = e->next; + free(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/cmark.h b/src/cmark.h index 7371d33..7ab3995 100644 --- a/src/cmark.h +++ b/src/cmark.h @@ -4,7 +4,8 @@ #include <stdbool.h> #include <stdio.h> #include "buffer.h" -#include "ast.h" +#include "chunk.h" +#include "references.h" #ifdef __cplusplus extern "C" { @@ -15,6 +16,121 @@ extern "C" { #define CMARK_MAX_LINK_LABEL_LENGTH 1000 +struct cmark_node_inl { + enum { + CMARK_INL_STRING, + CMARK_INL_SOFTBREAK, + CMARK_INL_LINEBREAK, + CMARK_INL_CODE, + CMARK_INL_RAW_HTML, + CMARK_INL_EMPH, + CMARK_INL_STRONG, + CMARK_INL_LINK, + CMARK_INL_IMAGE + } tag; + union { + cmark_chunk literal; + struct cmark_node_inl *inlines; + struct { + struct cmark_node_inl *label; + unsigned char *url; + unsigned char *title; + } linkable; + } content; + struct cmark_node_inl *next; +}; + +typedef struct cmark_node_inl cmark_node_inl; + +// Types for blocks +struct cmark_ListData { + enum { + bullet, + ordered + } list_type; + int marker_offset; + int padding; + int start; + enum { + period, + parens + } delimiter; + unsigned char bullet_char; + bool tight; +}; + +struct cmark_FencedCodeData { + int fence_length; + int fence_offset; + unsigned char fence_char; + cmark_strbuf info; +}; + +struct cmark_node_block { + enum { + CMARK_BLOCK_DOCUMENT, + CMARK_BLOCK_BQUOTE, + CMARK_BLOCK_LIST, + CMARK_BLOCK_LIST_ITEM, + CMARK_BLOCK_FENCED_CODE, + CMARK_BLOCK_INDENTED_CODE, + CMARK_BLOCK_HTML, + CMARK_BLOCK_PARAGRAPH, + CMARK_BLOCK_ATX_HEADER, + CMARK_BLOCK_SETEXT_HEADER, + CMARK_BLOCK_HRULE, + CMARK_BLOCK_REFERENCE_DEF + } tag; + int start_line; + int start_column; + int end_line; + bool open; + bool last_line_blank; + struct cmark_node_block* children; + struct cmark_node_block* last_child; + struct cmark_node_block* parent; + struct cmark_node_block* top; + cmark_strbuf string_content; + cmark_node_inl* inline_content; + + union { + struct cmark_ListData list; + struct cmark_FencedCodeData code; + struct { + int level; + } header; + struct { + cmark_reference_map *refmap; + } document; + } as; + + struct cmark_node_block *next; + struct cmark_node_block *prev; +}; + +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_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) + __attribute__((visibility("default"))) cmark_node_block *cmark_parse_document(const unsigned char *buffer, size_t len); @@ -30,10 +146,52 @@ void cmark_render_html(cmark_strbuf *html, cmark_node_block *root); __attribute__((visibility("default"))) unsigned char *cmark_markdown_to_html(unsigned char *text, int len); + + #ifndef CMARK_NO_SHORT_NAMES #define VERSION CMARK_VERSION #define CODE_INDENT CMARK_CODE_INDENT #define MAX_LINK_LABEL_LENGTH CMARK_MAX_LINK_LABEL_LENGTH + #define node_inl cmark_node_inl + #define INL_STRING CMARK_INL_STRING + #define INL_SOFTBREAK CMARK_INL_SOFTBREAK + #define INL_LINEBREAK CMARK_INL_LINEBREAK + #define INL_CODE CMARK_INL_CODE + #define INL_RAW_HTML CMARK_INL_RAW_HTML + #define INL_EMPH CMARK_INL_EMPH + #define INL_STRONG CMARK_INL_STRONG + #define INL_LINK CMARK_INL_LINK + #define INL_IMAGE CMARK_INL_IMAGE + #define ListData cmark_ListData + #define FencedCodeData cmark_FencedCodeData + #define node_block cmark_node_block + #define BLOCK_DOCUMENT CMARK_BLOCK_DOCUMENT + #define BLOCK_BQUOTE CMARK_BLOCK_BQUOTE + #define BLOCK_LIST CMARK_BLOCK_LIST + #define BLOCK_LIST_ITEM CMARK_BLOCK_LIST_ITEM + #define BLOCK_FENCED_CODE CMARK_BLOCK_FENCED_CODE + #define BLOCK_INDENTED_CODE CMARK_BLOCK_INDENTED_CODE + #define BLOCK_HTML CMARK_BLOCK_HTML + #define BLOCK_PARAGRAPH CMARK_BLOCK_PARAGRAPH + #define BLOCK_ATX_HEADER CMARK_BLOCK_ATX_HEADER + #define BLOCK_SETEXT_HEADER CMARK_BLOCK_SETEXT_HEADER + #define BLOCK_HRULE CMARK_BLOCK_HRULE + #define BLOCK_REFERENCE_DEF CMARK_BLOCK_REFERENCE_DEF + #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 #ifdef __cplusplus diff --git a/src/inlines.c b/src/inlines.c index 78ebaf4..0dabbd3 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -8,7 +8,6 @@ #include "html/houdini.h" #include "utf8.h" #include "scanners.h" -#include "ast.h" #include "inlines.h" diff --git a/src/references.c b/src/references.c index def4dd8..e39b836 100644 --- a/src/references.c +++ b/src/references.c @@ -2,6 +2,7 @@ #include "utf8.h" #include "references.h" #include "inlines.h" +#include "chunk.h" static unsigned int refhash(const unsigned char *link_ref) diff --git a/src/references.h b/src/references.h index 1bc187a..c4ca6df 100644 --- a/src/references.h +++ b/src/references.h @@ -3,6 +3,8 @@ #define REFMAP_SIZE 16 +#include "chunk.h" + struct cmark_reference { struct cmark_reference *next; unsigned char *label; |