summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--src/blocks.c173
-rw-r--r--src/buffer.c26
-rw-r--r--src/buffer.h2
-rw-r--r--src/html/houdini_href_e.c10
-rw-r--r--src/html/houdini_html_e.c10
-rw-r--r--src/html/html.c4
-rw-r--r--src/inlines.c235
-rw-r--r--src/print.c2
-rw-r--r--src/scanners.h28
-rw-r--r--src/scanners.re85
-rw-r--r--src/stmd.h16
12 files changed, 261 insertions, 334 deletions
diff --git a/Makefile b/Makefile
index d14a928..89ec68c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-CFLAGS=-ggdb3 -O0 -Wall -Wextra -std=c99 -Isrc $(OPTFLAGS)
-LDFLAGS=-ggdb3 -O0 -Wall -Werror
+CFLAGS=-ggdb3 -O0 -Wall -Wextra -Wno-unused-variable -std=c99 -Isrc $(OPTFLAGS)
+LDFLAGS=-ggdb3 -O0 -Wall -Wno-unused-variable # -Werror
SRCDIR=src
DATADIR=data
diff --git a/src/blocks.c b/src/blocks.c
index 42f20db..94ff986 100644
--- a/src/blocks.c
+++ b/src/blocks.c
@@ -8,6 +8,8 @@
#include "scanners.h"
#include "uthash.h"
+#define peek_at(i, n) (i)->data[n]
+
static void incorporate_line(gh_buf *ln, int line_number, block** curptr);
static void finalize(block* b, int line_number);
@@ -27,7 +29,6 @@ static block* make_block(int tag, int start_line, int start_column)
e->top = NULL;
e->attributes.refmap = NULL;
gh_buf_init(&e->string_content, 32);
- e->string_pos = 0;
e->inline_content = NULL;
e->next = NULL;
e->prev = NULL;
@@ -80,10 +81,10 @@ static inline bool accepts_lines(int block_type)
block_type == fenced_code);
}
-static void add_line(block* block, gh_buf *ln, int offset)
+static void add_line(block* block, chunk *ch, int offset)
{
assert(block->open);
- gh_buf_put(&block->string_content, ln->ptr + offset, ln->size - offset);
+ gh_buf_put(&block->string_content, ch->data + offset, ch->len - offset);
}
static void remove_trailing_blank_lines(gh_buf *ln)
@@ -104,7 +105,7 @@ static void remove_trailing_blank_lines(gh_buf *ln)
i = gh_buf_strchr(ln, '\n', i);
if (i >= 0)
- gh_buf_truncate(ln, i + 1);
+ gh_buf_truncate(ln, i);
}
// Check to see if a block ends with a blank line, descending
@@ -162,12 +163,12 @@ static void finalize(block* b, int line_number)
switch (b->tag) {
case paragraph:
pos = 0;
- while (gh_buf_at(&b->string_content, b->string_pos) == '[' &&
- (pos = parse_reference(&b->string_content, b->string_pos,
- b->top->attributes.refmap))) {
- b->string_pos = pos;
+ while (gh_buf_at(&b->string_content, 0) == '[' &&
+ (pos = parse_reference(&b->string_content, b->top->attributes.refmap))) {
+
+ gh_buf_drop(&b->string_content, pos);
}
- if (is_blank(&b->string_content, b->string_pos)) {
+ if (is_blank(&b->string_content, 0)) {
b->tag = reference_def;
}
break;
@@ -179,14 +180,16 @@ static void finalize(block* b, int line_number)
case fenced_code:
// first line of contents becomes info
- firstlinelen = gh_buf_strchr(&b->string_content, '\n', b->string_pos);
+ firstlinelen = gh_buf_strchr(&b->string_content, '\n', 0);
+
+ gh_buf_init(&b->attributes.fenced_code_data.info, 0);
gh_buf_set(
&b->attributes.fenced_code_data.info,
- b->string_content.ptr + b->string_pos,
+ b->string_content.ptr,
firstlinelen
);
- b->string_pos = firstlinelen + 1;
+ gh_buf_drop(&b->string_content, firstlinelen + 1);
gh_buf_trim(&b->attributes.fenced_code_data.info);
unescape_buffer(&b->attributes.fenced_code_data.info);
@@ -281,7 +284,7 @@ void process_inlines(block* cur, reference** refmap)
case paragraph:
case atx_header:
case setext_header:
- cur->inline_content = parse_inlines(&cur->string_content, cur->string_pos, refmap);
+ cur->inline_content = parse_inlines(&cur->string_content, refmap);
// MEM
// gh_buf_free(&cur->string_content);
break;
@@ -300,19 +303,18 @@ void process_inlines(block* cur, reference** refmap)
// Attempts to parse a list item marker (bullet or enumerated).
// On success, returns length of the marker, and populates
// data with the details. On failure, returns 0.
-static int parse_list_marker(gh_buf *ln, int pos,
- struct ListData ** dataptr)
+static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr)
{
- char c;
+ unsigned char c;
int startpos;
struct ListData * data;
startpos = pos;
- c = gh_buf_at(ln, pos);
+ c = peek_at(input, pos);
- if ((c == '*' || c == '-' || c == '+') && !scan_hrule(ln, pos)) {
+ if ((c == '*' || c == '-' || c == '+') && !scan_hrule(input, pos)) {
pos++;
- if (!isspace(gh_buf_at(ln, pos))) {
+ if (!isspace(peek_at(input, pos))) {
return 0;
}
data = malloc(sizeof(struct ListData));
@@ -327,14 +329,14 @@ static int parse_list_marker(gh_buf *ln, int pos,
int start = 0;
do {
- start = (10 * start) + (gh_buf_at(ln, pos) - '0');
+ start = (10 * start) + (peek_at(input, pos) - '0');
pos++;
- } while (isdigit(gh_buf_at(ln, pos)));
+ } while (isdigit(peek_at(input, pos)));
- c = gh_buf_at(ln, pos);
+ c = peek_at(input, pos);
if (c == '.' || c == ')') {
pos++;
- if (!isspace(gh_buf_at(ln, pos))) {
+ if (!isspace(peek_at(input, pos))) {
return 0;
}
data = malloc(sizeof(struct ListData));
@@ -449,8 +451,26 @@ extern block *stmd_parse_document(const unsigned char *buffer, size_t len)
return finalize_document(document, linenum);
}
+static void chop_trailing_hashtags(chunk *ch)
+{
+ int n;
+
+ chunk_rtrim(ch);
+ n = ch->len - 1;
+
+ // if string ends in #s, remove these:
+ while (n >= 0 && peek_at(ch, n) == '#')
+ n--;
+
+ // the last # was escaped, so we include it.
+ if (n >= 0 && peek_at(ch, n) == '\\')
+ n++;
+
+ ch->len = n + 1;
+}
+
// Process one line at a time, modifying a block.
-static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
+static void incorporate_line(gh_buf *line, int line_number, block** curptr)
{
block* last_matched_container;
int offset = 0;
@@ -464,6 +484,10 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
bool blank = false;
int first_nonspace;
int indent;
+ chunk input;
+
+ input.data = line->ptr;
+ input.len = line->size;
// container starts at the document root.
container = cur->top;
@@ -475,21 +499,19 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
container = container->last_child;
first_nonspace = offset;
- while (gh_buf_at(ln, first_nonspace) == ' ') {
+ while (peek_at(&input, first_nonspace) == ' ') {
first_nonspace++;
}
indent = first_nonspace - offset;
- blank = gh_buf_at(ln, first_nonspace) == '\n';
+ blank = peek_at(&input, first_nonspace) == '\n';
if (container->tag == block_quote) {
-
- matched = indent <= 3 && gh_buf_at(ln, first_nonspace) == '>';
+ matched = indent <= 3 && peek_at(&input, first_nonspace) == '>';
if (matched) {
offset = first_nonspace + 1;
- if (gh_buf_at(ln, offset) == ' ') {
+ if (peek_at(&input, offset) == ' ')
offset++;
- }
} else {
all_matched = false;
}
@@ -526,7 +548,7 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
// skip optional spaces of fence offset
i = container->attributes.fenced_code_data.fence_offset;
- while (i > 0 && gh_buf_at(ln, offset) == ' ') {
+ while (i > 0 && peek_at(&input, offset) == ' ') {
offset++;
i--;
}
@@ -564,15 +586,13 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
container->tag != html_block) {
first_nonspace = offset;
- while (gh_buf_at(ln, first_nonspace) == ' ') {
+ while (peek_at(&input, first_nonspace) == ' ')
first_nonspace++;
- }
indent = first_nonspace - offset;
- blank = gh_buf_at(ln, first_nonspace) == '\n';
+ blank = peek_at(&input, first_nonspace) == '\n';
if (indent >= CODE_INDENT) {
-
if (cur->tag != paragraph && !blank) {
offset += CODE_INDENT;
container = add_child(container, indented_code, line_number, offset + 1);
@@ -580,76 +600,70 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
break;
}
- } else if (gh_buf_at(ln, first_nonspace) == '>') {
+ } else if (peek_at(&input, first_nonspace) == '>') {
offset = first_nonspace + 1;
// optional following character
- if (gh_buf_at(ln, offset) == ' ') {
+ if (peek_at(&input, offset) == ' ')
offset++;
- }
container = add_child(container, block_quote, line_number, offset + 1);
- } else if ((matched = scan_atx_header_start(ln, first_nonspace))) {
+ } else if ((matched = scan_atx_header_start(&input, first_nonspace))) {
offset = first_nonspace + matched;
container = add_child(container, atx_header, line_number, offset + 1);
- int hashpos = gh_buf_strchr(ln, '#', first_nonspace);
- assert(hashpos >= 0);
-
+ int hashpos = chunk_strchr(&input, '#', first_nonspace);
int level = 0;
- while (gh_buf_at(ln, hashpos) == '#') {
+
+ while (peek_at(&input, hashpos) == '#') {
level++;
hashpos++;
}
container->attributes.header_level = level;
- } else if ((matched = scan_open_code_fence(ln, first_nonspace))) {
+ } else if ((matched = scan_open_code_fence(&input, first_nonspace))) {
- container = add_child(container, fenced_code, line_number,
- first_nonspace + 1);
- container->attributes.fenced_code_data.fence_char = gh_buf_at(ln,
- first_nonspace);
+ container = add_child(container, fenced_code, line_number, first_nonspace + 1);
+ container->attributes.fenced_code_data.fence_char = peek_at(&input, first_nonspace);
container->attributes.fenced_code_data.fence_length = matched;
- container->attributes.fenced_code_data.fence_offset =
- first_nonspace - offset;
+ container->attributes.fenced_code_data.fence_offset = first_nonspace - offset;
offset = first_nonspace + matched;
- } else if ((matched = scan_html_block_tag(ln, first_nonspace))) {
+ } else if ((matched = scan_html_block_tag(&input, first_nonspace))) {
- container = add_child(container, html_block, line_number,
- first_nonspace + 1);
+ container = add_child(container, html_block, line_number, first_nonspace + 1);
// note, we don't adjust offset because the tag is part of the text
} else if (container->tag == paragraph &&
- (lev = scan_setext_header_line(ln, first_nonspace)) &&
+ (lev = scan_setext_header_line(&input, first_nonspace)) &&
// check that there is only one line in the paragraph:
gh_buf_strrchr(&container->string_content, '\n',
gh_buf_len(&container->string_content) - 2) < 0) {
container->tag = setext_header;
container->attributes.header_level = lev;
- offset = gh_buf_len(ln) - 1;
+ offset = input.len - 1;
} else if (!(container->tag == paragraph && !all_matched) &&
- (matched = scan_hrule(ln, first_nonspace))) {
+ (matched = scan_hrule(&input, first_nonspace))) {
// it's only now that we know the line is not part of a setext header:
container = add_child(container, hrule, line_number, first_nonspace + 1);
finalize(container, line_number);
container = container->parent;
- offset = gh_buf_len(ln) - 1;
+ offset = input.len - 1;
- } else if ((matched = parse_list_marker(ln, first_nonspace, &data))) {
+ } else if ((matched = parse_list_marker(&input, first_nonspace, &data))) {
// compute padding:
offset = first_nonspace + matched;
i = 0;
- while (i <= 5 && gh_buf_at(ln, offset + i) == ' ') {
+ while (i <= 5 && peek_at(&input, offset + i) == ' ') {
i++;
}
// i = number of spaces after marker, up to 5
- if (i >= 5 || i < 1 || gh_buf_at(ln, offset) == '\n') {
+ if (i >= 5 || i < 1 || peek_at(&input, offset) == '\n') {
data->padding = matched + 1;
if (i > 0) {
offset += 1;
@@ -674,6 +688,7 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
// add the list item
container = add_child(container, list_item, line_number,
first_nonspace + 1);
+ /* TODO: static */
container->attributes.list_data = *data;
free(data);
@@ -691,12 +706,11 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
// appropriate container.
first_nonspace = offset;
- while (gh_buf_at(ln, first_nonspace) == ' ') {
+ while (peek_at(&input, first_nonspace) == ' ')
first_nonspace++;
- }
indent = first_nonspace - offset;
- blank = gh_buf_at(ln, first_nonspace) == '\n';
+ blank = peek_at(&input, first_nonspace) == '\n';
// block quote lines are never blank as they start with >
// and we don't count blanks in fenced code for purposes of tight/loose
@@ -721,13 +735,12 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
cur->tag == paragraph &&
gh_buf_len(&cur->string_content) > 0) {
- add_line(cur, ln, offset);
+ add_line(cur, &input, offset);
} else { // not a lazy continuation
// finalize any blocks that were not matched and set cur to container:
while (cur != last_matched_container) {
-
finalize(cur, line_number);
cur = cur->parent;
assert(cur != NULL);
@@ -735,58 +748,46 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr)
if (container->tag == indented_code) {
- add_line(container, ln, offset);
+ add_line(container, &input, offset);
} else if (container->tag == fenced_code) {
matched = (indent <= 3
- && gh_buf_at(ln, first_nonspace) == container->attributes.fenced_code_data.fence_char)
- && scan_close_code_fence(ln, first_nonspace,
+ && peek_at(&input, first_nonspace) == container->attributes.fenced_code_data.fence_char)
+ && scan_close_code_fence(&input, first_nonspace,
container->attributes.fenced_code_data.fence_length);
if (matched) {
// if closing fence, don't add line to container; instead, close it:
finalize(container, line_number);
container = container->parent; // back up to parent
} else {
- add_line(container, ln, offset);
+ add_line(container, &input, offset);
}
} else if (container->tag == html_block) {
- add_line(container, ln, offset);
+ add_line(container, &input, offset);
} else if (blank) {
// ??? do nothing
} else if (container->tag == atx_header) {
- // chop off trailing ###s...use a scanner?
- gh_buf_trim(ln);
- int p = gh_buf_len(ln) - 1;
-
- // if string ends in #s, remove these:
- while (gh_buf_at(ln, p) == '#') {
- p--;
- }
- if (gh_buf_at(ln, p) == '\\') {
- // the last # was escaped, so we include it.
- p++;
- }
- gh_buf_truncate(ln, p + 1);
- add_line(container, ln, first_nonspace);
+ chop_trailing_hashtags(&input);
+ add_line(container, &input, first_nonspace);
finalize(container, line_number);
container = container->parent;
} else if (accepts_lines(container->tag)) {
- add_line(container, ln, first_nonspace);
+ add_line(container, &input, first_nonspace);
} else if (container->tag != hrule && container->tag != setext_header) {
// create paragraph container for line
container = add_child(container, paragraph, line_number, first_nonspace + 1);
- add_line(container, ln, first_nonspace);
+ add_line(container, &input, first_nonspace);
} else {
assert(false);
diff --git a/src/buffer.c b/src/buffer.c
index cfc6a7e..dc4a405 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -95,7 +95,7 @@ void gh_buf_clear(gh_buf *buf)
int gh_buf_set(gh_buf *buf, const unsigned char *data, int len)
{
- if (len == 0 || data == NULL) {
+ if (len <= 0 || data == NULL) {
gh_buf_clear(buf);
} else {
if (data != buf->ptr) {
@@ -125,6 +125,9 @@ int gh_buf_putc(gh_buf *buf, int c)
int gh_buf_put(gh_buf *buf, const unsigned char *data, int len)
{
+ if (len <= 0)
+ return 0;
+
ENSURE_SIZE(buf, buf->size + len + 1);
memmove(buf->ptr + buf->size, data, len);
buf->size += len;
@@ -272,15 +275,28 @@ void gh_buf_truncate(gh_buf *buf, int len)
}
}
+void gh_buf_drop(gh_buf *buf, int n)
+{
+ if (n > 0) {
+ buf->size = buf->size - n;
+ if (buf->size)
+ memmove(buf->ptr, buf->ptr + n, buf->size);
+
+ buf->ptr[buf->size] = '\0';
+ }
+}
+
void gh_buf_trim(gh_buf *buf)
{
- /* TODO: leading whitespace? */
- /*
+ int i = 0;
+
+ if (!buf->size)
+ return;
+
while (i < buf->size && isspace(buf->ptr[i]))
i++;
- gh_buf_truncate(buf, i);
- */
+ gh_buf_drop(buf, i);
/* rtrim */
while (buf->size > 0) {
diff --git a/src/buffer.h b/src/buffer.h
index 422ef02..0d5143e 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -105,8 +105,8 @@ extern void gh_buf_clear(gh_buf *buf);
int gh_buf_strchr(const gh_buf *buf, int c, int pos);
int gh_buf_strrchr(const gh_buf *buf, int c, int pos);
+void gh_buf_drop(gh_buf *buf, int n);
void gh_buf_truncate(gh_buf *buf, int len);
-void gh_buf_ltruncate(gh_buf *buf, int len);
void gh_buf_trim(gh_buf *buf);
#endif
diff --git a/src/html/houdini_href_e.c b/src/html/houdini_href_e.c
index 59fe850..b2a7d79 100644
--- a/src/html/houdini_href_e.c
+++ b/src/html/houdini_href_e.c
@@ -62,16 +62,8 @@ houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size)
while (i < size && HREF_SAFE[src[i]] != 0)
i++;
- if (likely(i > org)) {
- if (unlikely(org == 0)) {
- if (i >= size)
- return 0;
-
- gh_buf_grow(ob, HOUDINI_ESCAPED_SIZE(size));
- }
-
+ if (likely(i > org))
gh_buf_put(ob, src + org, i - org);
- }
/* escaping */
if (i >= size)
diff --git a/src/html/houdini_html_e.c b/src/html/houdini_html_e.c
index 316c5ce..5cdd3dd 100644
--- a/src/html/houdini_html_e.c
+++ b/src/html/houdini_html_e.c
@@ -54,16 +54,8 @@ houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure)
while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
i++;
- if (i > org) {
- if (unlikely(org == 0)) {
- if (i >= size)
- return 0;
-
- gh_buf_grow(ob, HOUDINI_ESCAPED_SIZE(size));
- }
-
+ if (i > org)
gh_buf_put(ob, src + org, i - org);
- }
/* escaping */
if (unlikely(i >= size))
diff --git a/src/html/html.c b/src/html/html.c
index 2f160ca..27ffe58 100644
--- a/src/html/html.c
+++ b/src/html/html.c
@@ -68,7 +68,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight)
cr(html);
gh_buf_puts(html, "<li>");
blocks_to_html(html, b->children, tight);
- gh_buf_trim(html);
+ gh_buf_trim(html); /* TODO: rtrim */
gh_buf_puts(html, "</li>");
cr(html);
break;
@@ -106,7 +106,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight)
cr(html);
gh_buf_puts(html, "<pre><code>");
escape_html(html, b->string_content.ptr, b->string_content.size);
- gh_buf_puts(html, "</pre></code>");
+ gh_buf_puts(html, "</code></pre>");
cr(html);
break;
diff --git a/src/inlines.c b/src/inlines.c
index 7b48ad9..ef27a24 100644
--- a/src/inlines.c
+++ b/src/inlines.c
@@ -9,10 +9,10 @@
#include "scanners.h"
typedef struct Subject {
- const gh_buf *buffer;
- int pos;
- reference** reference_map;
- int label_nestlevel;
+ chunk input;
+ int pos;
+ int label_nestlevel;
+ reference** reference_map;
} subject;
reference* lookup_reference(reference** refmap, chunk *label);
@@ -27,12 +27,16 @@ inline static void chunk_trim(chunk *c);
inline static chunk chunk_literal(const char *data);
inline static chunk chunk_buf_detach(gh_buf *buf);
-inline static chunk chunk_buf(const gh_buf *buf, int pos, int len);
+inline static chunk chunk_dup(const chunk *ch, int pos, int len);
static inl *parse_chunk_inlines(chunk *chunk, reference** refmap);
static inl *parse_inlines_while(subject* subj, int (*f)(subject*));
static int parse_inline(subject* subj, inl ** last);
+static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap);
+static void subject_from_buf(subject *e, gh_buf *buffer, reference** refmap);
+static int subject_find_special_char(subject *subj);
+
extern void free_reference(reference *ref) {
free(ref->label);
free(ref->url);
@@ -101,10 +105,12 @@ extern reference* make_reference(chunk *label, chunk *url, chunk *title)
extern void add_reference(reference** refmap, reference* ref)
{
reference * t = NULL;
- HASH_FIND(hh, *refmap, (char*)ref->label, (unsigned)strlen(ref->label), t);
+ const char *label = (const char *)ref->label;
+
+ HASH_FIND(hh, *refmap, label, strlen(label), t);
if (t == NULL) {
- HASH_ADD_KEYPTR(hh, *refmap, (char*)ref->label, (unsigned)strlen(ref->label), ref);
+ HASH_ADD_KEYPTR(hh, *refmap, label, strlen(label), ref);
} else {
free_reference(ref); // we free this now since it won't be in the refmap
}
@@ -210,87 +216,49 @@ inline static inl* append_inlines(inl* a, inl* b)
return a;
}
-// Make a 'subject' from an input string.
-static void init_subject(subject *e, gh_buf *buffer, int input_pos, reference** refmap)
+static void subject_from_buf(subject *e, gh_buf *buffer, reference** refmap)
{
- e->buffer = buffer;
- e->pos = input_pos;
+ e->input.data = buffer->ptr;
+ e->input.len = buffer->size;
+ e->input.alloc = 0;
+ e->pos = 0;
e->label_nestlevel = 0;
e->reference_map = refmap;
-}
-
-inline static int isbacktick(int c)
-{
- return (c == '`');
-}
-
-inline static void chunk_free(chunk *c)
-{
- if (c->alloc)
- free((char *)c->data);
-
- c->data = NULL;
- c->alloc = 0;
- c->len = 0;
-}
-
-inline static void chunk_trim(chunk *c)
-{
- while (c->len && isspace(c->data[0])) {
- c->data++;
- c->len--;
- }
-
- while (c->len > 0) {
- if (!isspace(c->data[c->len - 1]))
- break;
- c->len--;
- }
+ chunk_rtrim(&e->input);
}
-inline static unsigned char *chunk_to_cstr(chunk *c)
+static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap)
{
- unsigned char *str;
-
- str = malloc(c->len + 1);
- memcpy(str, c->data, c->len);
- str[c->len] = 0;
+ e->input.data = chunk->data;
+ e->input.len = chunk->len;
+ e->input.alloc = 0;
+ e->pos = 0;
+ e->label_nestlevel = 0;
+ e->reference_map = refmap;
- return str;
+ chunk_rtrim(&e->input);
}
-inline static chunk chunk_literal(const char *data)
+inline static int isbacktick(int c)
{
- chunk c = {data, data ? strlen(data) : 0, 0};
- return c;
+ return (c == '`');
}
-inline static chunk chunk_buf(const gh_buf *buf, int pos, int len)
+static inline unsigned char peek_char(subject *subj)
{
- chunk c = {buf->ptr + pos, len, 0};
- return c;
+ return (subj->pos < subj->input.len) ? subj->input.data[subj->pos] : 0;
}
-inline static chunk chunk_buf_detach(gh_buf *buf)
+static inline unsigned char peek_at(subject *subj, int pos)
{
- chunk c;
-
- c.len = buf->size;
- c.data = gh_buf_detach(buf);
- c.alloc = 1;
-
- return c;
+ return subj->input.data[pos];
}
-// Return the next character in the subject, without advancing.
-// Return 0 if at the end of the subject.
-#define peek_char(subj) gh_buf_at((subj)->buffer, (subj)->pos)
-
// Return true if there are more characters in the subject.
inline static int is_eof(subject* subj)
{
- return (subj->pos >= gh_buf_len(subj->buffer));
+ return (subj->pos >= subj->input.len);
}
// Advance the subject. Doesn't check for eof.
@@ -308,7 +276,7 @@ inline static chunk take_while(subject* subj, int (*f)(int))
len++;
}
- return chunk_buf(subj->buffer, startpos, len);
+ return chunk_dup(&subj->input, startpos, len);
}
// Try to process a backtick code span that began with a
@@ -388,7 +356,7 @@ static inl* handle_backticks(subject *subj)
} else {
gh_buf buf = GH_BUF_INIT;
- gh_buf_set(&buf, subj->buffer->ptr + startpos, endpos - startpos - openticks.len);
+ gh_buf_set(&buf, subj->input.data + startpos, endpos - startpos - openticks.len);
gh_buf_trim(&buf);
normalize_whitespace(&buf);
@@ -404,7 +372,7 @@ static int scan_delims(subject* subj, char c, bool * can_open, bool * can_close)
char char_before, char_after;
int startpos = subj->pos;
- char_before = subj->pos == 0 ? '\n' : gh_buf_at(subj->buffer, subj->pos - 1);
+ char_before = subj->pos == 0 ? '\n' : peek_at(subj, subj->pos - 1);
while (peek_char(subj) == c) {
numdelims++;
advance(subj);
@@ -439,7 +407,7 @@ static inl* handle_strong_emph(subject* subj, char c)
numdelims = scan_delims(subj, c, &can_open, &can_close);
subj->pos += numdelims;
- new = make_str(chunk_buf(subj->buffer, subj->pos - numdelims, numdelims));
+ new = make_str(chunk_dup(&subj->input, subj->pos - numdelims, numdelims));
*last = new;
first_head = new;
result = new;
@@ -488,7 +456,7 @@ static inl* handle_strong_emph(subject* subj, char c)
numdelims = scan_delims(subj, c, &can_open, &can_close);
if (can_close && numdelims >= 1 && numdelims <= 3 &&
numdelims != first_close_delims) {
- new = make_str(chunk_buf(subj->buffer, subj->pos, numdelims));
+ new = make_str(chunk_dup(&subj->input, subj->pos, numdelims));
append_inlines(*last, new);
*last = new;
if (first_close_delims == 1 && numdelims > 2) {
@@ -554,7 +522,7 @@ static inl* handle_backslash(subject *subj)
unsigned char nextchar = peek_char(subj);
if (ispunct(nextchar)) { // only ascii symbols and newline can be escaped
advance(subj);
- return make_str(chunk_buf(subj->buffer, subj->pos - 1, 1));
+ return make_str(chunk_dup(&subj->input, subj->pos - 1, 1));
} else if (nextchar == '\n') {
advance(subj);
return make_linebreak();
@@ -569,9 +537,9 @@ static inl* handle_entity(subject* subj)
{
int match;
inl *result;
- match = scan_entity(subj->buffer, subj->pos);
+ match = scan_entity(&subj->input, subj->pos);
if (match) {
- result = make_entity(chunk_buf(subj->buffer, subj->pos, match));
+ result = make_entity(chunk_dup(&subj->input, subj->pos, match));
subj->pos += match;
} else {
advance(subj);
@@ -584,15 +552,13 @@ static inl* handle_entity(subject* subj)
// Returns an inline sequence consisting of str and entity elements.
static inl *make_str_with_entities(chunk *content)
{
- inl * result = NULL;
- inl * new;
+ inl *result = NULL;
+ inl *new;
int searchpos;
char c;
subject subj;
- gh_buf content_buf = GH_BUF_INIT;
- gh_buf_set(&content_buf, content->data, content->len);
- init_subject(&subj, &content_buf, 0, NULL);
+ subject_from_chunk(&subj, content, NULL);
while ((c = peek_char(&subj))) {
switch (c) {
@@ -600,18 +566,13 @@ static inl *make_str_with_entities(chunk *content)
new = handle_entity(&subj);
break;
default:
- searchpos = gh_buf_strchr(subj.buffer, '&', subj.pos);
- if (searchpos < 0) {
- searchpos = gh_buf_len(subj.buffer);
- }
-
- new = make_str(chunk_buf(subj.buffer, subj.pos, searchpos - subj.pos));
+ searchpos = chunk_strchr(&subj.input, '&', subj.pos);
+ new = make_str(chunk_dup(&subj.input, subj.pos, searchpos - subj.pos));
subj.pos = searchpos;
}
result = append_inlines(result, new);
}
- gh_buf_free(&content_buf);
return result;
}
@@ -678,9 +639,9 @@ static inl* handle_pointy_brace(subject* subj)
advance(subj); // advance past first <
// first try to match a URL autolink
- matchlen = scan_autolink_uri(subj->buffer, subj->pos);
+ matchlen = scan_autolink_uri(&subj->input, subj->pos);
if (matchlen > 0) {
- contents = chunk_buf(subj->buffer, subj->pos, matchlen - 1);
+ contents = chunk_dup(&subj->input, subj->pos, matchlen - 1);
subj->pos += matchlen;
return make_link(
@@ -691,11 +652,11 @@ static inl* handle_pointy_brace(subject* subj)
}
// next try to match an email autolink
- matchlen = scan_autolink_email(subj->buffer, subj->pos);
+ matchlen = scan_autolink_email(&subj->input, subj->pos);
if (matchlen > 0) {
gh_buf mail_url = GH_BUF_INIT;
- contents = chunk_buf(subj->buffer, subj->pos, matchlen - 1);
+ contents = chunk_dup(&subj->input, subj->pos, matchlen - 1);
subj->pos += matchlen;
gh_buf_puts(&mail_url, "mailto:");
@@ -709,9 +670,9 @@ static inl* handle_pointy_brace(subject* subj)
}
// finally, try to match an html tag
- matchlen = scan_html_tag(subj->buffer, subj->pos);
+ matchlen = scan_html_tag(&subj->input, subj->pos);
if (matchlen > 0) {
- contents = chunk_buf(subj->buffer, subj->pos - 1, matchlen + 1);
+ contents = chunk_dup(&subj->input, subj->pos - 1, matchlen + 1);
subj->pos += matchlen;
return make_raw_html(contents);
}
@@ -776,12 +737,7 @@ static int link_label(subject* subj, chunk *raw_label)
}
}
if (c == ']') {
- *raw_label = chunk_buf(
- subj->buffer,
- startpos + 1,
- subj->pos - (startpos + 1)
- );
-
+ *raw_label = chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1));
subj->label_nestlevel = 0;
advance(subj); // advance past ]
return 1;
@@ -813,25 +769,25 @@ static inl* handle_left_bracket(subject* subj)
if (found_label) {
if (peek_char(subj) == '(' &&
- ((sps = scan_spacechars(subj->buffer, subj->pos + 1)) > -1) &&
- ((n = scan_link_url(subj->buffer, subj->pos + 1 + sps)) > -1)) {
+ ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
+ ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) {
// try to parse an explicit link:
starturl = subj->pos + 1 + sps; // after (
endurl = starturl + n;
- starttitle = endurl + scan_spacechars(subj->buffer, endurl);
+ starttitle = endurl + scan_spacechars(&subj->input, endurl);
// ensure there are spaces btw url and title
endtitle = (starttitle == endurl) ? starttitle :
- starttitle + scan_link_title(subj->buffer, starttitle);
+ starttitle + scan_link_title(&subj->input, starttitle);
- endall = endtitle + scan_spacechars(subj->buffer, endtitle);
+ endall = endtitle + scan_spacechars(&subj->input, endtitle);
- if (gh_buf_at(subj->buffer, endall) == ')') {
+ if (peek_at(subj, endall) == ')') {
subj->pos = endall + 1;
- url = chunk_buf(subj->buffer, starturl, endurl - starturl);
- title = chunk_buf(subj->buffer, starttitle, endtitle - starttitle);
+ url = chunk_dup(&subj->input, starturl, endurl - starturl);
+ title = chunk_dup(&subj->input, starttitle, endtitle - starttitle);
lab = parse_chunk_inlines(&rawlabel, NULL);
return make_link(lab, url, title);
@@ -850,7 +806,7 @@ static inl* handle_left_bracket(subject* subj)
// Check for reference link.
// First, see if there's another label:
- subj->pos = subj->pos + scan_spacechars(subj->buffer, endlabel);
+ subj->pos = subj->pos + scan_spacechars(&subj->input, endlabel);
reflabel = rawlabel;
// if followed by a nonempty link label, we change reflabel to it:
@@ -892,8 +848,8 @@ static inl* handle_newline(subject *subj)
advance(subj);
}
if (nlpos > 1 &&
- gh_buf_at(subj->buffer, nlpos - 1) == ' ' &&
- gh_buf_at(subj->buffer, nlpos - 2) == ' ') {
+ peek_at(subj, nlpos - 1) == ' ' &&
+ peek_at(subj, nlpos - 2) == ' ') {
return make_linebreak();
} else {
return make_softbreak();
@@ -917,30 +873,22 @@ extern inl* parse_inlines_while(subject* subj, int (*f)(subject*))
inl *parse_chunk_inlines(chunk *chunk, reference** refmap)
{
- inl *result;
subject subj;
- gh_buf full_chunk = GH_BUF_INIT;
-
- gh_buf_set(&full_chunk, chunk->data, chunk->len);
- init_subject(&subj, &full_chunk, 0, refmap);
- result = parse_inlines_while(&subj, not_eof);
-
- gh_buf_free(&full_chunk);
- return result;
+ subject_from_chunk(&subj, chunk, refmap);
+ return parse_inlines_while(&subj, not_eof);
}
-static int find_special_char(subject *subj)
+static int subject_find_special_char(subject *subj)
{
int n = subj->pos + 1;
- int size = (int)gh_buf_len(subj->buffer);
- while (n < size) {
- if (strchr("\n\\`&_*[]<!", gh_buf_at(subj->buffer, n)))
+ while (n < subj->input.len) {
+ if (strchr("\n\\`&_*[]<!", subj->input.data[n]))
return n;
n++;
}
- return -1;
+ return subj->input.len;
}
// Parse an inline, advancing subject, and add it to last element.
@@ -973,11 +921,13 @@ static int parse_inline(subject* subj, inl ** last)
new = handle_pointy_brace(subj);
break;
case '_':
- if (subj->pos > 0 && (isalnum(gh_buf_at(subj->buffer, subj->pos - 1)) ||
- gh_buf_at(subj->buffer, subj->pos - 1) == '_')) {
- new = make_str(chunk_literal("_"));
- advance(subj);
- break;
+ if (subj->pos > 0) {
+ unsigned char prev = peek_at(subj, subj->pos - 1);
+ if (isalnum(prev) || prev == '_') {
+ new = make_str(chunk_literal("_"));
+ advance(subj);
+ break;
+ }
}
new = handle_strong_emph(subj, '_');
@@ -1002,18 +952,13 @@ static int parse_inline(subject* subj, inl ** last)
}
break;
default:
- text_literal:
- endpos = find_special_char(subj);
- if (endpos < 0) {
- endpos = gh_buf_len(subj->buffer);
- }
-
- contents = chunk_buf(subj->buffer, subj->pos, endpos - subj->pos);
+ endpos = subject_find_special_char(subj);
+ contents = chunk_dup(&subj->input, subj->pos, endpos - subj->pos);
subj->pos = endpos;
// if we're at a newline, strip trailing spaces.
if (peek_char(subj) == '\n') {
- chunk_trim(&contents);
+ chunk_rtrim(&contents);
}
new = make_str(contents);
@@ -1026,10 +971,10 @@ static int parse_inline(subject* subj, inl ** last)
return 1;
}
-extern inl* parse_inlines(gh_buf *input, int input_pos, reference** refmap)
+extern inl* parse_inlines(gh_buf *input, reference** refmap)
{
subject subj;
- init_subject(&subj, input, input_pos, refmap);
+ subject_from_buf(&subj, input, refmap);
return parse_inlines_while(&subj, not_eof);
}
@@ -1048,7 +993,7 @@ void spnl(subject* subj)
// Modify refmap if a reference is encountered.
// Return 0 if no reference found, otherwise position of subject
// after reference is parsed.
-extern int parse_reference(gh_buf *input, int input_pos, reference** refmap)
+extern int parse_reference(gh_buf *input, reference** refmap)
{
subject subj;
@@ -1058,9 +1003,9 @@ extern int parse_reference(gh_buf *input, int input_pos, reference** refmap)
int matchlen = 0;
int beforetitle;
- reference * new = NULL;
+ reference *new = NULL;
- init_subject(&subj, input, input_pos, NULL);
+ subject_from_buf(&subj, input, NULL);
// parse label:
if (!link_label(&subj, &lab))
@@ -1075,9 +1020,9 @@ extern int parse_reference(gh_buf *input, int input_pos, reference** refmap)
// parse link url:
spnl(&subj);
- matchlen = scan_link_url(subj.buffer, subj.pos);
+ matchlen = scan_link_url(&subj.input, subj.pos);
if (matchlen) {
- url = chunk_buf(subj.buffer, subj.pos, matchlen);
+ url = chunk_dup(&subj.input, subj.pos, matchlen);
subj.pos += matchlen;
} else {
return 0;
@@ -1086,9 +1031,9 @@ extern int parse_reference(gh_buf *input, int input_pos, reference** refmap)
// parse optional link_title
beforetitle = subj.pos;
spnl(&subj);
- matchlen = scan_link_title(subj.buffer, subj.pos);
+ matchlen = scan_link_title(&subj.input, subj.pos);
if (matchlen) {
- title = chunk_buf(subj.buffer, subj.pos, matchlen);
+ title = chunk_dup(&subj.input, subj.pos, matchlen);
subj.pos += matchlen;
} else {
subj.pos = beforetitle;
diff --git a/src/print.c b/src/print.c
index 0a87925..c262995 100644
--- a/src/print.c
+++ b/src/print.c
@@ -9,7 +9,7 @@ static void print_str(const unsigned char *s, int len)
int i;
if (len < 0)
- len = strlen(s);
+ len = strlen((char *)s);
putchar('"');
for (i = 0; i < len; ++i) {
diff --git a/src/scanners.h b/src/scanners.h
index b6e586b..f96c42d 100644
--- a/src/scanners.h
+++ b/src/scanners.h
@@ -1,15 +1,15 @@
-#include "buffer.h"
+#include "stmd.h"
-int scan_autolink_uri(const gh_buf *s, int pos);
-int scan_autolink_email(const gh_buf *s, int pos);
-int scan_html_tag(const gh_buf *s, int pos);
-int scan_html_block_tag(const gh_buf *s, int pos);
-int scan_link_url(const gh_buf *s, int pos);
-int scan_link_title(const gh_buf *s, int pos);
-int scan_spacechars(const gh_buf *s, int pos);
-int scan_atx_header_start(const gh_buf *s, int pos);
-int scan_setext_header_line(const gh_buf *s, int pos);
-int scan_hrule(const gh_buf *s, int pos);
-int scan_open_code_fence(const gh_buf *s, int pos);
-int scan_close_code_fence(const gh_buf *s, int pos, int len);
-int scan_entity(const gh_buf *s, int pos);
+int scan_autolink_uri(chunk *c, int offset);
+int scan_autolink_email(chunk *c, int offset);
+int scan_html_tag(chunk *c, int offset);
+int scan_html_block_tag(chunk *c, int offset);
+int scan_link_url(chunk *c, int offset);
+int scan_link_title(chunk *c, int offset);
+int scan_spacechars(chunk *c, int offset);
+int scan_atx_header_start(chunk *c, int offset);
+int scan_setext_header_line(chunk *c, int offset);
+int scan_hrule(chunk *c, int offset);
+int scan_open_code_fence(chunk *c, int offset);
+int scan_close_code_fence(chunk *c, int offset, int len);
+int scan_entity(chunk *c, int offset);
diff --git a/src/scanners.re b/src/scanners.re
index 7323ef9..5ac7c15 100644
--- a/src/scanners.re
+++ b/src/scanners.re
@@ -1,8 +1,15 @@
-#include "buffer.h"
+#include "scanners.h"
+
+#define SCAN_DATA \
+ const unsigned char *marker = NULL; \
+ const unsigned char *p = c->data + offset; \
+ const unsigned char *start = p; \
+ const unsigned char *end = c->data + c->len
/*!re2c
re2c:define:YYCTYPE = "unsigned char";
re2c:define:YYCURSOR = p;
+ re2c:define:YYLIMIT = end;
re2c:define:YYMARKER = marker;
re2c:define:YYCTXMARKER = marker;
re2c:yyfill:enable = 0;
@@ -55,11 +62,9 @@
*/
// Try to match URI autolink after first <, returning number of chars matched.
-extern int scan_autolink_uri(const gh_buf *s, int pos)
+extern int scan_autolink_uri(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
scheme [:]([^\x00-\x20<>\\]|escaped_char)*[>] { return (p - start); }
.? { return 0; }
@@ -67,11 +72,9 @@ extern int scan_autolink_uri(const gh_buf *s, int pos)
}
// Try to match email autolink after first <, returning num of chars matched.
-extern int scan_autolink_email(const gh_buf *s, int pos)
+extern int scan_autolink_email(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+
[@]
@@ -83,11 +86,9 @@ extern int scan_autolink_email(const gh_buf *s, int pos)
}
// Try to match an HTML tag after first <, returning num of chars matched.
-extern int scan_html_tag(const gh_buf *s, int pos)
+extern int scan_html_tag(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
htmltag { return (p - start); }
.? { return 0; }
@@ -96,11 +97,9 @@ extern int scan_html_tag(const gh_buf *s, int pos)
// Try to match an HTML block tag including first <,
// returning num of chars matched.
-extern int scan_html_block_tag(const gh_buf *s, int pos)
+extern int scan_html_block_tag(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
[<] [/] blocktagname (spacechar | [>]) { return (p - start); }
[<] blocktagname (spacechar | [/>]) { return (p - start); }
@@ -113,11 +112,9 @@ extern int scan_html_block_tag(const gh_buf *s, int pos)
// This may optionally be contained in <..>; otherwise
// whitespace and unbalanced right parentheses aren't allowed.
// Newlines aren't ever allowed.
-extern int scan_link_url(const gh_buf *s, int pos)
+extern int scan_link_url(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
[ \n]* [<] ([^<>\n\\\x00] | escaped_char | [\\])* [>] { return (p - start); }
[ \n]* (reg_char+ | escaped_char | in_parens_nosp)* { return (p - start); }
@@ -128,11 +125,9 @@ extern int scan_link_url(const gh_buf *s, int pos)
// Try to match a link title (in single quotes, in double quotes, or
// in parentheses), returning number of chars matched. Allow one
// level of internal nesting (quotes within quotes).
-extern int scan_link_title(const gh_buf *s, int pos)
+extern int scan_link_title(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
["] (escaped_char|[^"\x00])* ["] { return (p - start); }
['] (escaped_char|[^'\x00])* ['] { return (p - start); }
@@ -142,10 +137,9 @@ extern int scan_link_title(const gh_buf *s, int pos)
}
// Match space characters, including newlines.
-extern int scan_spacechars(const gh_buf *s, int pos)
+extern int scan_spacechars(chunk *c, int offset)
{
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
[ \t\n]* { return (p - start); }
. { return 0; }
@@ -153,11 +147,9 @@ extern int scan_spacechars(const gh_buf *s, int pos)
}
// Match ATX header start.
-extern int scan_atx_header_start(const gh_buf *s, int pos)
+extern int scan_atx_header_start(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
[#]{1,6} ([ ]+|[\n]) { return (p - start); }
.? { return 0; }
@@ -166,10 +158,9 @@ extern int scan_atx_header_start(const gh_buf *s, int pos)
// Match sexext header line. Return 1 for level-1 header,
// 2 for level-2, 0 for no match.
-extern int scan_setext_header_line(const gh_buf *s, int pos)
+extern int scan_setext_header_line(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
+ SCAN_DATA;
/*!re2c
[=]+ [ ]* [\n] { return 1; }
[-]+ [ ]* [\n] { return 2; }
@@ -180,11 +171,9 @@ extern int scan_setext_header_line(const gh_buf *s, int pos)
// Scan a horizontal rule line: "...three or more hyphens, asterisks,
// or underscores on a line by themselves. If you wish, you may use
// spaces between the hyphens or asterisks."
-extern int scan_hrule(const gh_buf *s, int pos)
+extern int scan_hrule(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
([*][ ]*){3,} [ \t]* [\n] { return (p - start); }
([_][ ]*){3,} [ \t]* [\n] { return (p - start); }
@@ -194,11 +183,9 @@ extern int scan_hrule(const gh_buf *s, int pos)
}
// Scan an opening code fence.
-extern int scan_open_code_fence(const gh_buf *s, int pos)
+extern int scan_open_code_fence(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
[`]{3,} / [^`\n\x00]*[\n] { return (p - start); }
[~]{3,} / [^~\n\x00]*[\n] { return (p - start); }
@@ -207,11 +194,9 @@ extern int scan_open_code_fence(const gh_buf *s, int pos)
}
// Scan a closing code fence with length at least len.
-extern int scan_close_code_fence(const gh_buf *s, int pos, int len)
+extern int scan_close_code_fence(chunk *c, int offset, int len)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
([`]{3,} | [~]{3,}) / spacechar* [\n]
{ if (p - start > len) {
@@ -225,11 +210,9 @@ extern int scan_close_code_fence(const gh_buf *s, int pos, int len)
// Scans an entity.
// Returns number of chars matched.
-extern int scan_entity(const gh_buf *s, int pos)
+extern int scan_entity(chunk *c, int offset)
{
- unsigned char * marker = NULL;
- unsigned char * p = &(s->ptr[pos]);
- unsigned char * start = p;
+ SCAN_DATA;
/*!re2c
[&] ([#] ([Xx][A-Fa-f0-9]{1,8}|[0-9]{1,8}) |[A-Za-z][A-Za-z0-9]{1,31} ) [;]
{ return (p - start); }
diff --git a/src/stmd.h b/src/stmd.h
index 3e284bd..4a3c399 100644
--- a/src/stmd.h
+++ b/src/stmd.h
@@ -1,17 +1,15 @@
+#ifndef _STDMD_H_
+#define _STDMD_H_
+
#include <stdbool.h>
#include <stdio.h>
#include "buffer.h"
+#include "chunk.h"
#include "uthash.h"
#define VERSION "0.1"
#define CODE_INDENT 4
-typedef struct {
- const unsigned char *data;
- int len;
- int alloc;
-} chunk;
-
typedef struct Inline {
enum { INL_STRING, INL_SOFTBREAK, INL_LINEBREAK, INL_CODE, INL_RAW_HTML, INL_ENTITY,
INL_EMPH, INL_STRONG, INL_LINK, INL_IMAGE } tag;
@@ -79,7 +77,6 @@ typedef struct Block {
struct Block* parent;
struct Block* top;
gh_buf string_content;
- int string_pos;
inl* inline_content;
union {
struct ListData list_data;
@@ -91,10 +88,10 @@ typedef struct Block {
struct Block * prev;
} block;
-inl* parse_inlines(gh_buf *input, int input_pos, reference** refmap);
+inl* parse_inlines(gh_buf *input, reference** refmap);
void free_inlines(inl* e);
-int parse_reference(gh_buf *input, int input_pos, reference** refmap);
+int parse_reference(gh_buf *input, reference** refmap);
void free_reference(reference *ref);
void free_reference_map(reference **refmap);
@@ -117,3 +114,4 @@ void inlines_to_html(gh_buf *html, inl *b);
void utf8proc_case_fold(gh_buf *dest, const unsigned char *str, int len);
+#endif